From: Ruben Kerkhof Date: Tue, 29 Nov 2016 11:31:39 +0000 (+0100) Subject: Merge branch 'collectd-5.5' into collectd-5.6 X-Git-Tag: collectd-5.6.2~3 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=2079ee1517e34de372f58e7e2267ad5c71a8a41f;hp=4f9adeefbf3d8e1a556d12e287a14019dacbfd04 Merge branch 'collectd-5.5' into collectd-5.6 Conflicts: contrib/redhat/collectd.spec --- diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..70f50ad5 --- /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 new file mode 100644 index 00000000..49d24b30 --- /dev/null +++ b/.github/issue_template.md @@ -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 54eaa974..8154d733 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,6 @@ Makefile config.log config.status libtool -src/.deps src/collectd.conf src/config.h src/libcollectdclient/libcollectdclient.pc @@ -31,7 +30,7 @@ src/stamp-h1 *.lo *.o .libs/ -src/collectd +.deps/ src/collectd-nagios src/collectd-tg src/collectdctl @@ -53,6 +52,9 @@ src/liboconfig/scanner.c # protobuf stuff: src/*.pb-c.[ch] +src/*.grpc.pb.cc +src/*.pb.cc +src/*.pb.h # make dist stuff: /collectd-*.tar.gz @@ -73,19 +75,23 @@ bindings/java/org/collectd/java/*.class # 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 new file mode 100644 index 00000000..03d9dded --- /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" diff --git a/AUTHORS b/AUTHORS index 3f63c3dc..28220e79 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,9 +4,31 @@ Permanent project members Florian "octo" Forster - Initial author. +Marc Fournier + - 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 + - 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 + - Bugfixes and enhancements in many places all around the project. + - Fedora and EPEL packages. + Sebastian "tokkee" Harl - Bugfixes and enhancements in many places all around the project. + - grpc plugin. - perl plugin. + - postgresql plugin. - users plugin. - vserver plugin. - Debian package. @@ -75,9 +97,16 @@ Christophe Kalt - The version 3 `log' mode. - Many Solaris related hints and fixes. +Claudius Zingerli + - chrony plugin. + Cyril Feraudet - ethstat plugin. +Dagobert Michelsen + - zone plugin. + - Many Solaris related hints and fixes. + Dan Berrange - uuid plugin. @@ -115,6 +144,9 @@ Flavio Stanchina Franck Lombardi - UNIX socket code for the memcached plugin. +Gergely Nagy + - Write-Riemann plugin. + Jason Pepas - nfs plugin. @@ -131,6 +163,9 @@ Jérôme Renard Jiri Tyr - fhcount plugin. +Julien Ammous + - Lua plugin. + Kevin Bowling - write_tsdb plugin for http://opentsdb.net/ @@ -162,18 +197,14 @@ Manuel Sanmartin + swap - Various AIX-related fixes and hacks. -Marc Fournier - - 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 - uptime plugin. - ip6tables support in the iptables plugin. - openvpn plugin (support for more status file formats) +Mathijs Möhlmann + - zone plugin. + Michael Hanselmann - md plugin. @@ -191,6 +222,9 @@ Michał Mirosław Mirko Buffoni - Port/Socket selection in the MySQL plugin. +Nicolas Jourden + - gps plugin. + Niki W. Waibel - Initial autotools fixes. - libltdl code. @@ -215,6 +249,10 @@ Paul Sadauskas - `ReportByDevice' option of the df plugin. - write_http plugin. +Pavel Rochnyack + - xencpu plugin. + - Bugfixes and enhancements in many places all around the project. + Peter Holik - cpufreq plugin. - multimeter plugin. @@ -225,14 +263,6 @@ Peter Holik Phoenix Kayo - pinba plugin. -Pierre-Yves Ritschard - - 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 - SMF manifest for collectd. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..eeb174ba --- /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 87645451..771ce9c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,185 @@ +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 b79ea1ca..03bdd39a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,11 +6,11 @@ if BUILD_INCLUDED_LTDL 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 diff --git a/README b/README index 3e2c0233..ee909d64 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ collectd - System information collection daemon ================================================= -http://collectd.org/ +https://collectd.org/ About ----- @@ -51,6 +51,9 @@ Features - 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. @@ -64,6 +67,9 @@ Features - 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. @@ -119,6 +125,12 @@ Features - 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. @@ -156,6 +168,12 @@ Features 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). @@ -191,6 +209,9 @@ Features 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'. @@ -379,12 +400,19 @@ Features - 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. @@ -400,6 +428,10 @@ Features 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. @@ -495,6 +527,9 @@ Features 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). @@ -669,10 +704,19 @@ Prerequisites Used by the `gmond' plugin to process data received from Ganglia. + * libgrpc (optional) + Used by the `grpc' plugin. gRPC requires a C++ compiler supporting the + C++11 standard. + + * libgcrypt (optional) Used by the `network' plugin for encryption and authentication. + * libgps (optional) + Used by the `gps' plugin. + + * libhal (optional) If present, the `uuid' plugin will check for UUID from HAL. @@ -695,6 +739,10 @@ Prerequisites Used by the `openldap' plugin. + * liblua (optional) + Used by the `lua' plugin. Currently, Lua 5.1 and later are supported. + + * liblvm2 (optional) Used by the `lvm' plugin. @@ -758,14 +806,18 @@ Prerequisites The PostgreSQL C client library used by the `postgresql' plugin. + * 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. + + * 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. * 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. @@ -823,6 +875,10 @@ Prerequisites `virt' plugins. + * libxen (optional) + Used by the `xencpu' plugin. + + * libxmms (optional) @@ -836,6 +892,10 @@ Prerequisites `varnish' plugin. + * riemann-c-client (optional) + For the `write_riemann' plugin. + + Configuring / Compiling / Installing ------------------------------------ @@ -889,18 +949,19 @@ Configuring with libjvm 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 @@ -917,6 +978,7 @@ To generate the `configure` script, you'll need the following dependencies: - bison - libtool - libtool-ltdl +- pkg-config The `build.sh' script takes no arguments. @@ -969,6 +1031,5 @@ Author Sebastian tokkee Harl , 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 ea0f2fa2..887c2895 100644 --- a/bindings/java/org/collectd/java/GenericJMXConfConnection.java +++ b/bindings/java/org/collectd/java/GenericJMXConfConnection.java @@ -52,7 +52,8 @@ class GenericJMXConfConnection 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 _mbeans = null; /* @@ -92,55 +93,74 @@ class GenericJMXConfConnection return Collectd.getHostname(); } /* }}} String getHost */ -private void connect () /* {{{ */ -{ - JMXServiceURL service_url; - JMXConnector connector; - Map environment; + private void connect () /* {{{ */ + { + JMXServiceURL service_url; + Map 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 (); + 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 - * - * - * Host "tomcat0.mycompany" - * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi" - * Collect "java.lang:type=GarbageCollector,name=Copy" - * Collect "java.lang:type=Memory" - * - * - */ + this._jmx_connector = null; + this._mbean_connection = null; + } /* }}} void disconnect */ + + /* + * public methods + * + * + * Host "tomcat0.mycompany" + * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi" + * Collect "java.lang:type=GarbageCollector,name=Copy" + * Collect "java.lang:type=Memory" + * + * + */ public GenericJMXConfConnection (OConfigItem ci) /* {{{ */ throws IllegalArgumentException { @@ -217,9 +237,10 @@ private void connect () /* {{{ */ { PluginData pd; + // try to connect connect (); - if (this._jmx_connection == null) + if (this._mbean_connection == null) return; Collectd.logDebug ("GenericJMXConfConnection.query: " @@ -234,11 +255,11 @@ private void connect () /* {{{ */ { 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 4b42c911..63b76282 100644 --- a/bindings/java/org/collectd/java/GenericJMXConfValue.java +++ b/bindings/java/org/collectd/java/GenericJMXConfValue.java @@ -28,6 +28,7 @@ package org.collectd.java; import java.util.Arrays; import java.util.List; +import java.util.Collection; import java.util.Set; import java.util.Iterator; import java.util.ArrayList; @@ -39,6 +40,7 @@ import javax.management.MBeanServerConnection; 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; @@ -68,6 +70,7 @@ class GenericJMXConfValue private List _attributes; private String _instance_prefix; private List _instance_from; + private String _plugin_name; private boolean _is_table; /** @@ -295,6 +298,45 @@ class GenericJMXConfValue { 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 attrName) + { + String key; + Object value = null; + + key = attrName.remove (0); + + @SuppressWarnings("unchecked") + Collection table = (Collection) 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); } @@ -341,6 +383,8 @@ class GenericJMXConfValue { 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; @@ -351,7 +395,7 @@ class GenericJMXConfValue else { Collectd.logError ("GenericJMXConfValue: Received object of " - + "unknown class."); + + "unknown class. " + attrName + " " + ((value == null)?"null":value.getClass().getName())); return (null); } } @@ -436,6 +480,7 @@ class GenericJMXConfValue this._attributes = new ArrayList (); this._instance_prefix = null; this._instance_from = new ArrayList (); + this._plugin_name = null; this._is_table = false; /* @@ -485,6 +530,12 @@ class GenericJMXConfValue 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 ())); @@ -538,6 +589,10 @@ class GenericJMXConfValue 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 diff --git a/bindings/perl/lib/Collectd/Unixsock.pm b/bindings/perl/lib/Collectd/Unixsock.pm index 5e79d268..304bbbc3 100644 --- a/bindings/perl/lib/Collectd/Unixsock.pm +++ b/bindings/perl/lib/Collectd/Unixsock.pm @@ -137,13 +137,13 @@ sub _parse_identifier 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. @@ -193,6 +193,32 @@ sub _socket_chat 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 @@ -330,18 +356,8 @@ sub putval . _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>-EB ( C<%identifier> ) @@ -500,18 +516,7 @@ sub putnotif . 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>-EB (B =E I<$timeout>, B =E [...], B =E [...]); @@ -549,7 +554,6 @@ sub flush my $fh = $self->{sock} or confess; - my $status = 0; my $msg = "FLUSH"; $msg .= " timeout=$args{timeout}" if defined $args{timeout}; @@ -564,6 +568,7 @@ sub flush if ($args{identifier}) { + my $pre = $msg; for my $identifier (@{$args{identifier}}) { my $ident_str; @@ -576,24 +581,18 @@ sub flush } $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 diff --git a/bindings/perl/t/01_methods.t b/bindings/perl/t/01_methods.t index 2f7818b1..4e94f8e8 100644 --- a/bindings/perl/t/01_methods.t +++ b/bindings/perl/t/01_methods.t @@ -16,7 +16,7 @@ sub test_query { 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 20854b13..57f3d444 100755 --- a/build.sh +++ b/build.sh @@ -18,7 +18,7 @@ EOF 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 7748be86..a4603a9b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,7 @@ 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]) @@ -31,7 +32,7 @@ m4_ifdef([LT_PACKAGE_VERSION], 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) @@ -42,7 +43,10 @@ AC_SYS_LARGEFILE # # 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 @@ -56,6 +60,8 @@ AC_PROG_LIBTOOL 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]) @@ -73,26 +79,33 @@ then 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 ( 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 @@ -112,6 +125,10 @@ 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" @@ -125,12 +142,12 @@ case $host_os in 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 @@ -199,6 +216,19 @@ AC_HEADER_STDBOOL 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 +#endif +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_SYS_PARAM_H +# include +#endif +]) + # For ping library AC_CHECK_HEADERS(netinet/in_systm.h, [], [], [#if HAVE_STDINT_H @@ -413,7 +443,7 @@ AC_CHECK_HEADERS(sys/sysctl.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]) @@ -426,6 +456,22 @@ else 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) @@ -445,7 +491,7 @@ else 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 @@ -637,10 +683,26 @@ AC_CHECK_HEADERS([ \ 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) @@ -680,8 +742,6 @@ AC_CHECK_HEADERS(netinet/if_ether.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"], @@ -705,6 +765,23 @@ AC_CHECK_HEADERS(net/pfvar.h, 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 +]], +[[ + 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"]) @@ -731,28 +808,48 @@ fi 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 ( 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" @@ -852,8 +949,6 @@ fi 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" @@ -1382,15 +1491,15 @@ if test "x$have_getmntent" = "xc"; then 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 @@ -1481,6 +1590,24 @@ AC_CHECK_MEMBERS([struct kinfo_proc.p_pid, struct kinfo_proc.p_vm_rssize], #include ]) + +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 +#include +#include + ]) + + + AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [], [#define _BSD_SOURCE #define _DEFAULT_SOURCE @@ -1548,18 +1675,48 @@ AC_CHECK_LIB(resolv, res_search, 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:]) @@ -1859,6 +2016,36 @@ then 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 +]], +[[ +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" BUILD_WITH_LIBCURL_LIBS="$with_curl_libs" AC_SUBST(BUILD_WITH_LIBCURL_CFLAGS) @@ -1874,7 +2061,6 @@ then 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 {{{ @@ -2111,12 +2297,6 @@ then 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" @@ -2134,6 +2314,146 @@ AC_SUBST(GCRYPT_LIBS) 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 ( 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::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 @@ -2235,9 +2550,6 @@ if test "x$with_java_home" = "x" 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.])], @@ -2330,6 +2642,10 @@ if test "x$JAVA_LDFLAGS" != "x" 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" @@ -2370,9 +2686,11 @@ fi 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 @@ -2382,8 +2700,8 @@ if test "x$with_java" = "xyes" 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 @@ -2394,6 +2712,7 @@ fi CPPFLAGS="$SAVE_CPPFLAGS" CFLAGS="$SAVE_CFLAGS" LDFLAGS="$SAVE_LDFLAGS" +LIBS="$SAVE_LIBS" AC_SUBST(JAVA_CPPFLAGS) AC_SUBST(JAVA_CFLAGS) @@ -2460,22 +2779,110 @@ fi 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 @@ -2588,13 +2995,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 if test $? -ne 0 @@ -2718,27 +3118,76 @@ fi 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 @@ -2970,7 +3415,7 @@ 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]) @@ -2996,9 +3441,6 @@ AM_CONDITIONAL(BUILD_WITH_LIBNETAPP, test "x$with_libnetapp" = "xyes") # }}} # --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 {{{ @@ -3091,7 +3518,7 @@ save_LDFLAGS="$LDFLAGS" 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" @@ -3229,22 +3656,22 @@ then 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)"]) @@ -3266,7 +3693,7 @@ if test "x$with_libowcapi" = "xyes" 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)"]) @@ -3277,8 +3704,10 @@ fi 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 # }}} @@ -3373,7 +3802,7 @@ then 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" @@ -3607,161 +4036,197 @@ fi 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 ( 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 ( 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 ]], + [[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="" @@ -4113,11 +4578,6 @@ then 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 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" @@ -4148,74 +4608,13 @@ fi 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" \ @@ -4325,6 +4717,7 @@ fi if test "x$with_libstatgrab" = "xyes" then SAVE_CFLAGS="$CFLAGS" + SAVE_LDFLAGS="$LDFLAGS" SAVE_LIBS="$LIBS" CFLAGS="$CFLAGS $with_libstatgrab_cflags" @@ -4557,13 +4950,6 @@ fi # 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 if test $? -ne 0 @@ -4636,6 +5022,51 @@ then 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 ], @@ -4797,8 +5228,8 @@ then 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" @@ -4840,13 +5271,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 if test $? -ne 0 @@ -4906,23 +5330,20 @@ with_libxml2_ldflags="" 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 @@ -5021,17 +5442,6 @@ with_libopenipmipthread="yes" 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]) @@ -5155,11 +5565,12 @@ AM_CONDITIONAL(BUILD_WITH_LIBATASMART, test "x$with_libatasmart" = "xyes") 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 # @@ -5252,7 +5663,7 @@ AC_DEFUN( then enable_plugin="yes" else - enable_plugin="no" + enable_plugin="$2" fi else enable_plugin="$enable_all_plugins" @@ -5269,7 +5680,7 @@ AC_DEFUN( 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") @@ -5283,6 +5694,7 @@ collectd features:]) 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" @@ -5297,6 +5709,7 @@ plugin_conntrack="no" plugin_contextswitch="no" plugin_cpu="no" plugin_cpufreq="no" +plugin_cpusleep="no" plugin_curl_json="no" plugin_curl_xml="no" plugin_df="no" @@ -5306,6 +5719,8 @@ plugin_entropy="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" @@ -5317,8 +5732,10 @@ plugin_multimeter="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" @@ -5333,16 +5750,18 @@ plugin_virt="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" @@ -5378,6 +5797,11 @@ then 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" @@ -5385,6 +5809,14 @@ then 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 @@ -5396,27 +5828,28 @@ fi 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 @@ -5432,6 +5865,7 @@ then plugin_processes="yes" plugin_uptime="yes" plugin_zfs_arc="yes" + plugin_zone="yes" fi if test "x$with_devinfo$with_kstat" = "xyesyes" @@ -5444,7 +5878,6 @@ then fi # libi2c-dev -with_libi2c="no" if test "x$ac_system" = "xLinux" then AC_CHECK_DECL(i2c_smbus_read_i2c_block_data, @@ -5452,6 +5885,8 @@ 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 #include ]]) +else + with_libi2c="no (Linux only)" fi if test "x$with_libi2c" = "xyes" @@ -5568,11 +6003,21 @@ then 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" @@ -5588,6 +6033,11 @@ then 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 @@ -5618,6 +6068,11 @@ 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" @@ -5633,6 +6088,11 @@ then 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" @@ -5652,6 +6112,10 @@ then plugin_virt="yes" fi +if test "x$with_libxenctrl" = "xyes" +then + plugin_xencpu="yes" +fi m4_divert_once([HELP_ENABLE], [ collectd plugins:]) @@ -5673,141 +6137,150 @@ AC_ARG_ENABLE([all-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" @@ -5958,7 +6443,17 @@ AC_SUBST(LCC_VERSION_STRING) 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" \ @@ -5985,208 +6480,237 @@ then with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)" fi -cat <{'get_files_by_ident'}{$cache_key})) @@ -496,7 +498,20 @@ sub get_files_by_ident 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); diff --git a/contrib/examples/myplugin.c b/contrib/examples/myplugin.c index d836a793..aa8c49c6 100644 --- a/contrib/examples/myplugin.c +++ b/contrib/examples/myplugin.c @@ -18,20 +18,20 @@ * is optional */ -#if ! HAVE_CONFIG_H +#if !HAVE_CONFIG_H #include #include #ifndef __USE_ISOC99 /* required for NAN */ -# define DISABLE_ISOC99 1 -# define __USE_ISOC99 1 +#define DISABLE_ISOC99 1 +#define __USE_ISOC99 1 #endif /* !defined(__USE_ISOC99) */ #include #if DISABLE_ISOC99 -# undef DISABLE_ISOC99 -# undef __USE_ISOC99 +#undef DISABLE_ISOC99 +#undef __USE_ISOC99 #endif /* DISABLE_ISOC99 */ #include @@ -39,6 +39,7 @@ #endif /* ! HAVE_CONFIG */ #include + #include #include @@ -49,10 +50,7 @@ * - minimum allowed value * - maximum allowed value */ -static data_source_t dsrc[1] = -{ - { "my_ds", DS_TYPE_GAUGE, 0, NAN } -}; +static data_source_t dsrc[1] = {{"my_ds", DS_TYPE_GAUGE, 0, NAN}}; /* * data set definition: @@ -66,161 +64,151 @@ static data_source_t dsrc[1] = * It is strongly recommended to use one of the types and data-sets * pre-defined in the types.db file. */ -static data_set_t ds = -{ - "myplugin", STATIC_ARRAY_SIZE (dsrc), dsrc -}; +static data_set_t ds = {"myplugin", STATIC_ARRAY_SIZE(dsrc), dsrc}; /* * This function is called once upon startup to initialize the plugin. */ -static int my_init (void) -{ - /* open sockets, initialize data structures, ... */ +static int my_init(void) { + /* open sockets, initialize data structures, ... */ - /* A return value != 0 indicates an error and causes the plugin to be - disabled. */ - return 0; + /* A return value != 0 indicates an error and causes the plugin to be + disabled. */ + return 0; } /* static int my_init (void) */ /* * This function is called in regular intervalls to collect the data. */ -static int my_read (void) -{ - value_t values[1]; /* the size of this list should equal the number of - data sources */ - value_list_t vl = VALUE_LIST_INIT; - - /* do the magic to read the data */ - values[0].gauge = random (); - - vl.values = values; - vl.values_len = 1; - vl.time = time (NULL); - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin)); - - /* it is strongly recommended to use a type defined in the types.db file - * instead of a custom type */ - sstrncpy (vl.type, "myplugin", sizeof (vl.type)); - /* optionally set vl.plugin_instance and vl.type_instance to reasonable - * values (default: "") */ - - /* dispatch the values to collectd which passes them on to all registered - * write functions */ - plugin_dispatch_values (&vl); - - /* A return value != 0 indicates an error and the plugin will be skipped - * for an increasing amount of time. */ - return 0; +static int my_read(void) { + value_t values[1]; /* the size of this list should equal the number of + data sources */ + value_list_t vl = VALUE_LIST_INIT; + + /* do the magic to read the data */ + values[0].gauge = random(); + + vl.values = values; + vl.values_len = 1; + vl.time = time(NULL); + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "myplugin", sizeof(vl.plugin)); + + /* it is strongly recommended to use a type defined in the types.db file + * instead of a custom type */ + sstrncpy(vl.type, "myplugin", sizeof(vl.type)); + /* optionally set vl.plugin_instance and vl.type_instance to reasonable + * values (default: "") */ + + /* dispatch the values to collectd which passes them on to all registered + * write functions */ + plugin_dispatch_values(&vl); + + /* A return value != 0 indicates an error and the plugin will be skipped + * for an increasing amount of time. */ + return 0; } /* static int my_read (void) */ /* * This function is called after values have been dispatched to collectd. */ -static int my_write (const data_set_t *ds, const value_list_t *vl, - user_data_t *ud) -{ - char name[1024] = ""; - int i = 0; - - if (ds->ds_num != vl->values_len) { - plugin_log (LOG_WARNING, "DS number does not match values length"); - return -1; - } - - /* get the default base filename for the output file - depending on the - * provided values this will be something like - * /[-]/[-] */ - if (0 != format_name (name, 1024, vl->host, vl->plugin, - vl->plugin_instance, ds->type, vl->type_instance)) - return -1; - - for (i = 0; i < ds->ds_num; ++i) { - /* do the magic to output the data */ - printf ("%s (%s) at %i: ", name, - (ds->ds->type == DS_TYPE_GAUGE) ? "GAUGE" : "COUNTER", - (int)vl->time); - - if (ds->ds->type == DS_TYPE_GAUGE) - printf ("%f\n", vl->values[i].gauge); - else - printf ("%lld\n", vl->values[i].counter); - } - return 0; +static int my_write(const data_set_t *ds, const value_list_t *vl, + user_data_t *ud) { + char name[1024] = ""; + int i = 0; + + if (ds->ds_num != vl->values_len) { + plugin_log(LOG_WARNING, "DS number does not match values length"); + return -1; + } + + /* get the default base filename for the output file - depending on the + * provided values this will be something like + * /[-]/[-] */ + if (0 != format_name(name, 1024, vl->host, vl->plugin, vl->plugin_instance, + ds->type, vl->type_instance)) + return -1; + + for (i = 0; i < ds->ds_num; ++i) { + /* do the magic to output the data */ + printf("%s (%s) at %i: ", name, + (ds->ds->type == DS_TYPE_GAUGE) ? "GAUGE" : "COUNTER", + (int)vl->time); + + if (ds->ds->type == DS_TYPE_GAUGE) + printf("%f\n", vl->values[i].gauge); + else + printf("%lld\n", vl->values[i].counter); + } + return 0; } /* static int my_write (data_set_t *, value_list_t *) */ /* * This function is called when plugin_log () has been used. */ -static void my_log (int severity, const char *msg, user_data_t *ud) -{ - printf ("LOG: %i - %s\n", severity, msg); - return; +static void my_log(int severity, const char *msg, user_data_t *ud) { + printf("LOG: %i - %s\n", severity, msg); + return; } /* static void my_log (int, const char *) */ /* * This function is called when plugin_dispatch_notification () has been used. */ -static int my_notify (const notification_t *notif, user_data_t *ud) -{ - char time_str[32] = ""; - struct tm *tm = NULL; +static int my_notify(const notification_t *notif, user_data_t *ud) { + char time_str[32] = ""; + struct tm *tm = NULL; - int n = 0; + int n = 0; - if (NULL == (tm = localtime (¬if->time))) - time_str[0] = '\0'; + if (NULL == (tm = localtime(¬if->time))) + time_str[0] = '\0'; - n = strftime (time_str, 32, "%F %T", tm); - if (n >= 32) n = 31; - time_str[n] = '\0'; + n = strftime(time_str, 32, "%F %T", tm); + if (n >= 32) + n = 31; + time_str[n] = '\0'; - printf ("NOTIF (%s): %i - ", time_str, notif->severity); + printf("NOTIF (%s): %i - ", time_str, notif->severity); - if ('\0' != *notif->host) - printf ("%s: ", notif->host); + if ('\0' != *notif->host) + printf("%s: ", notif->host); - if ('\0' != *notif->plugin) - printf ("%s: ", notif->plugin); + if ('\0' != *notif->plugin) + printf("%s: ", notif->plugin); - if ('\0' != *notif->plugin_instance) - printf ("%s: ", notif->plugin_instance); + if ('\0' != *notif->plugin_instance) + printf("%s: ", notif->plugin_instance); - if ('\0' != *notif->type) - printf ("%s: ", notif->type); + if ('\0' != *notif->type) + printf("%s: ", notif->type); - if ('\0' != *notif->type_instance) - printf ("%s: ", notif->type_instance); + if ('\0' != *notif->type_instance) + printf("%s: ", notif->type_instance); - printf ("%s\n", notif->message); - return 0; + printf("%s\n", notif->message); + return 0; } /* static int my_notify (notification_t *) */ /* * This function is called before shutting down collectd. */ -static int my_shutdown (void) -{ - /* close sockets, free data structures, ... */ - return 0; +static int my_shutdown(void) { + /* close sockets, free data structures, ... */ + return 0; } /* static int my_shutdown (void) */ /* * This function is called after loading the plugin to register it with * collectd. */ -void module_register (void) -{ - plugin_register_log ("myplugin", my_log, /* user data */ NULL); - plugin_register_notification ("myplugin", my_notify, - /* user data */ NULL); - plugin_register_data_set (&ds); - plugin_register_read ("myplugin", my_read); - plugin_register_init ("myplugin", my_init); - plugin_register_write ("myplugin", my_write, /* user data */ NULL); - plugin_register_shutdown ("myplugin", my_shutdown); - return; +void module_register(void) { + plugin_register_log("myplugin", my_log, /* user data */ NULL); + plugin_register_notification("myplugin", my_notify, + /* user data */ NULL); + plugin_register_data_set(&ds); + plugin_register_read("myplugin", my_read); + plugin_register_init("myplugin", my_init); + plugin_register_write("myplugin", my_write, /* user data */ NULL); + plugin_register_shutdown("myplugin", my_shutdown); + return; } /* void module_register (void) */ - diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec deleted file mode 100644 index a35923c0..00000000 --- a/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 -Vendor: Florian octo Forster - -%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 4.2.0 -- New major release -- Changes to support 4.2.0 (ie. contrib/collection.conf) - -* Mon Aug 06 2007 Kjell Randa 4.0.6 -- New upstream version - -* Wed Jul 25 2007 Kjell Randa 4.0.5 -- New major release -- Changes to support 4.0.5 - -* Wed Jan 11 2007 Iain Lea 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 3.10.0-1 -- New upstream version - -* Tue Jun 25 2006 Florian octo Forster 3.9.4-1 -- New upstream version - -* Tue Jun 01 2006 Florian octo Forster 3.9.3-1 -- New upstream version - -* Tue May 09 2006 Florian octo Forster 3.9.2-1 -- New upstream version - -* Tue May 09 2006 Florian octo Forster 3.8.5-1 -- New upstream version - -* Fri Apr 21 2006 Florian octo Forster 3.9.1-1 -- New upstream version - -* Fri Apr 14 2006 Florian octo Forster 3.9.0-1 -- New upstream version -- Added the `apache' package. - -* Thu Mar 14 2006 Florian octo Forster 3.8.2-1 -- New upstream version - -* Thu Mar 13 2006 Florian octo Forster 3.8.1-1 -- New upstream version - -* Thu Mar 09 2006 Florian octo Forster 3.8.0-1 -- New upstream version - -* Sat Feb 18 2006 Florian octo Forster 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 3.7.1-1 -- New upstream version - -* Mon Jan 30 2006 Florian octo Forster 3.7.0-1 -- New upstream version -- Removed the extra `hddtemp' package - -* Tue Jan 24 2006 Florian octo Forster 3.6.2-1 -- New upstream version - -* Fri Jan 20 2006 Florian octo Forster 3.6.1-1 -- New upstream version - -* Fri Jan 20 2006 Florian octo Forster 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 3.5.0-1 -- New upstream version - -* Sat Nov 26 2005 Florian octo Forster 3.4.0-1 -- New upstream version - -* Sat Nov 05 2005 Florian octo Forster 3.3.0-1 -- New upstream version - -* Tue Oct 26 2005 Florian octo Forster 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 3.1.0-1 -- New upstream version -- Added package `collectd-hddtemp' - -* Fri Sep 30 2005 Florian octo Forster 3.0.0-1 -- New upstream version -- Split the package into `collectd' and `collectd-sensors' - -* Fri Sep 16 2005 Florian octo Forster 2.1.0-1 -- New upstream version - -* Mon Sep 10 2005 Florian octo Forster 2.0.0-1 -- New upstream version - -* Mon Aug 29 2005 Florian octo Forster 1.8.0-1 -- New upstream version - -* Sun Aug 25 2005 Florian octo Forster 1.7.0-1 -- New upstream version - -* Sun Aug 21 2005 Florian octo Forster 1.6.0-1 -- New upstream version - -* Sun Jul 17 2005 Florian octo Forster 1.5.1-1 -- New upstream version - -* Sun Jul 17 2005 Florian octo Forster 1.5-1 -- New upstream version - -* Mon Jul 11 2005 Florian octo Forster 1.4.2-1 -- New upstream version - -* Sat Jul 09 2005 Florian octo Forster 1.4-1 -- Built on RedHat 7.3 diff --git a/contrib/fedora/init.d-collectd b/contrib/fedora/init.d-collectd deleted file mode 100644 index ea8662ad..00000000 --- a/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 diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec index 295985fa..215c82b9 100644 --- a/contrib/redhat/collectd.spec +++ b/contrib/redhat/collectd.spec @@ -38,36 +38,6 @@ %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_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} @@ -76,57 +46,62 @@ %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} @@ -141,12 +116,12 @@ %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} @@ -159,20 +134,20 @@ %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}} @@ -188,6 +163,8 @@ %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 @@ -212,24 +189,57 @@ %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_redis 0 +%define with_rrdcached 0 +%define with_xmms 0 +%endif + +Summary: Statistics collection and monitoring daemon Name: collectd -Version: 5.5.3 -Release: 1%{?dist} +Version: 5.6.1 +Release: 2%{?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 -%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 @@ -316,6 +326,15 @@ BuildRequires: yajl-devel 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 @@ -403,6 +422,26 @@ The gmond plugin subscribes to a Multicast group to receive data from gmond, 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 @@ -458,6 +497,17 @@ BuildRequires: yajl-devel 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 @@ -512,6 +562,16 @@ MySQL querying plugin. This plugin provides data of issued commands, called 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 @@ -580,10 +640,10 @@ Summary: Perl 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 @@ -628,10 +688,10 @@ database. 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 @@ -748,7 +808,7 @@ using HTTP POST requests. 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 @@ -773,6 +833,16 @@ BuildRequires: protobuf-c-devel 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 @@ -903,6 +973,12 @@ Collectd utilities %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 @@ -927,6 +1003,12 @@ Collectd utilities %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 @@ -1035,6 +1117,18 @@ Collectd utilities %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 @@ -1113,6 +1207,12 @@ Collectd utilities %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 @@ -1173,6 +1273,12 @@ Collectd utilities %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 @@ -1221,6 +1327,12 @@ Collectd utilities %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 @@ -1318,10 +1430,11 @@ Collectd utilities %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 @@ -1567,6 +1680,12 @@ Collectd utilities %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 @@ -1579,6 +1698,12 @@ Collectd utilities %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 @@ -1586,6 +1711,7 @@ Collectd utilities %endif %configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \ + %{?_python_config} \ --disable-static \ --without-included-ltdl \ --enable-all-plugins=yes \ @@ -1611,14 +1737,16 @@ Collectd utilities %{?_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} \ @@ -1632,98 +1760,105 @@ Collectd utilities %{?_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} @@ -1732,7 +1867,7 @@ Collectd utilities %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 @@ -1766,6 +1901,10 @@ rm -f %{buildroot}%{_datadir}/collectd/java/generic-jmx.jar 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* @@ -1788,26 +1927,15 @@ rm -f %{buildroot}%{_mandir}/man5/collectd-snmp.5* %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 @@ -1818,7 +1946,7 @@ fi %endif %postun -%if 0%{?el7:1} +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_postun_with_restart collectd.service %else # restart collectd only when upgrading @@ -1834,7 +1962,7 @@ fi %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 @@ -1888,6 +2016,9 @@ fi %if %{with_cpufreq} %{_libdir}/%{name}/cpufreq.so %endif +%if %{with_cpusleep} +%{_libdir}/%{name}/cpusleep.so +%endif %if %{with_csv} %{_libdir}/%{name}/csv.so %endif @@ -1957,6 +2088,9 @@ fi %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 @@ -2111,6 +2245,11 @@ fi %{_libdir}/%{name}/ceph.so %endif +%if %{with_chrony} +%files chrony +%{_libdir}/%{name}/chrony.so +%endif + %if %{with_curl} %files curl %{_libdir}/%{name}/curl.so @@ -2151,6 +2290,16 @@ fi %{_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 @@ -2184,6 +2333,12 @@ fi %{_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 @@ -2204,6 +2359,11 @@ fi %{_libdir}/%{name}/modbus.so %endif +%if %{with_mqtt} +%files mqtt +%{_libdir}/%{name}/mqtt.so +%endif + %if %{with_mysql} %files mysql %{_libdir}/%{name}/mysql.so @@ -2331,6 +2491,11 @@ fi %{_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 @@ -2348,9 +2513,16 @@ fi %doc contrib/ %changelog -* Tue Nov 29 2016 Ruben Kerkhof - 5.5.3-1 +* Tue Nov 29 2016 Ruben Kerkhof - 5.6.1-2 +- Disable redis plugin on RHEL < 7, hiredis has been retired from EPEL6 + +* Mon Oct 10 2016 Victor Demonchy - 5.6.1-1 +- New upstream version + +* Sun Aug 14 2016 Ruben Kerkhof - 5.6.0-1 - New upstream version -- Disable redis plugin on EL6 +- 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 - 5.5.2-1 - New upstream version diff --git a/contrib/systemd.collectd.service b/contrib/systemd.collectd.service index c7806fed..d0f1bdea 100644 --- a/contrib/systemd.collectd.service +++ b/contrib/systemd.collectd.service @@ -1,7 +1,8 @@ [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 @@ -33,7 +34,7 @@ NoNewPrivileges=true # 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 new file mode 100644 index 00000000..3c0bfd7f --- /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 new file mode 100644 index 00000000..c706ea11 --- /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 + +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 new file mode 100644 index 00000000..952c5418 --- /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 + +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 dc07cb74..37160c10 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,10 +6,6 @@ SUBDIRS += daemon PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\' -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"' @@ -21,25 +17,69 @@ endif 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 @@ -47,26 +87,28 @@ if BUILD_AIX 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 @@ -76,11 +118,6 @@ 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 = @@ -88,6 +125,24 @@ 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 \ @@ -100,26 +155,22 @@ if BUILD_PLUGIN_AMQP 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 @@ -133,16 +184,15 @@ endif 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 @@ -165,7 +215,6 @@ if BUILD_PLUGIN_BATTERY 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 @@ -196,6 +245,12 @@ cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 @@ -239,6 +294,12 @@ cpufreq_la_SOURCES = cpufreq.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 @@ -247,32 +308,27 @@ endif 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) @@ -319,6 +375,9 @@ disk_la_CFLAGS += $(BUILD_WITH_LIBUDEV_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 @@ -328,21 +387,19 @@ if BUILD_PLUGIN_DNS 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 @@ -358,7 +415,6 @@ exec_la_SOURCES = exec.c \ 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 @@ -387,6 +443,23 @@ gmond_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(GANGLIA_LDFLAGS) 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 @@ -422,7 +495,6 @@ endif # BUILD_PLUGIN_INTERFACE if BUILD_PLUGIN_IPC pkglib_LTLIBRARIES += ipc.la ipc_la_SOURCES = ipc.c -ipc_la_CFLAGS = $(AM_CFLAGS) ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif @@ -445,8 +517,9 @@ 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 @@ -490,7 +563,6 @@ 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) @@ -503,10 +575,20 @@ lpar_la_LDFLAGS = $(PLUGIN_LDFLAGS) 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 @@ -617,6 +699,14 @@ modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS) 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 @@ -626,13 +716,9 @@ endif 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 @@ -657,7 +743,7 @@ network_la_SOURCES = network.c network.h \ 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 @@ -683,13 +769,9 @@ 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 @@ -704,7 +786,13 @@ if BUILD_PLUGIN_NOTIFY_EMAIL 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 @@ -728,7 +816,7 @@ pkglib_LTLIBRARIES += nut.la 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 @@ -744,24 +832,22 @@ endif 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 @@ -769,8 +855,7 @@ if BUILD_PLUGIN_ORACLE 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 @@ -781,6 +866,10 @@ perl_la_SOURCES = perl.c # Despite C99 providing the "bool" type thru stdbool.h, Perl defines its own # version of that type if HAS_BOOL is not defined... *sigh* perl_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAS_BOOL=1 +# 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)\" @@ -804,8 +893,9 @@ if BUILD_PLUGIN_PINBA 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 @@ -835,13 +925,11 @@ endif 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 @@ -909,9 +997,9 @@ endif 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 @@ -927,24 +1015,16 @@ endif 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 @@ -1095,7 +1175,6 @@ unixsock_la_SOURCES = unixsock.c \ 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 @@ -1170,34 +1249,28 @@ endif 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 @@ -1219,16 +1292,15 @@ if BUILD_PLUGIN_WRITE_REDIS 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 @@ -1243,6 +1315,14 @@ write_tsdb_la_SOURCES = write_tsdb.c 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 @@ -1254,17 +1334,12 @@ endif 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 @@ -1276,12 +1351,19 @@ 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 \ @@ -1292,15 +1374,12 @@ dist_man_MANS = collectd.1 \ 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 \ @@ -1311,10 +1390,17 @@ EXTRA_DIST += collectd.conf.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 '\' $@ >/dev/null 2>&1; \ then \ @@ -1322,7 +1408,7 @@ EXTRA_DIST += collectd.conf.pod \ 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 '\' $@ >/dev/null 2>&1; \ then \ @@ -1331,7 +1417,7 @@ EXTRA_DIST += collectd.conf.pod \ 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. @@ -1341,18 +1427,7 @@ CLEANFILES += pinba.pb-c.c pinba.pb-c.h 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: @@ -1373,27 +1448,11 @@ uninstall-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 56e4955c..ec94183a 100644 --- a/src/aggregation.c +++ b/src/aggregation.c @@ -26,17 +26,14 @@ #include "collectd.h" -#include - -#include "plugin.h" #include "common.h" -#include "configfile.h" #include "meta_data.h" +#include "plugin.h" #include "utils_cache.h" /* for uc_get_rate() */ #include "utils_subst.h" #include "utils_vl_lookup.h" -#define AGG_MATCHES_ALL(str) (strcmp ("/.*/", str) == 0) +#define AGG_MATCHES_ALL(str) (strcmp("/.*/", str) == 0) #define AGG_FUNC_PLACEHOLDER "%{aggregation}" struct aggregation_s /* {{{ */ @@ -91,14 +88,14 @@ static lookup_t *lookup = NULL; static pthread_mutex_t agg_instance_list_lock = PTHREAD_MUTEX_INITIALIZER; static agg_instance_t *agg_instance_list_head = NULL; -static _Bool agg_is_regex (char const *str) /* {{{ */ +static _Bool agg_is_regex(char const *str) /* {{{ */ { size_t len; if (str == NULL) return (0); - len = strlen (str); + len = strlen(str); if (len < 3) return (0); @@ -108,124 +105,120 @@ static _Bool agg_is_regex (char const *str) /* {{{ */ return (0); } /* }}} _Bool agg_is_regex */ -static void agg_destroy (aggregation_t *agg) /* {{{ */ +static void agg_destroy(aggregation_t *agg) /* {{{ */ { - sfree (agg); + sfree(agg); } /* }}} void agg_destroy */ /* Frees all dynamically allocated memory within the instance. */ -static void agg_instance_destroy (agg_instance_t *inst) /* {{{ */ +static void agg_instance_destroy(agg_instance_t *inst) /* {{{ */ { if (inst == NULL) return; /* Remove this instance from the global list of instances. */ - pthread_mutex_lock (&agg_instance_list_lock); + pthread_mutex_lock(&agg_instance_list_lock); if (agg_instance_list_head == inst) agg_instance_list_head = inst->next; - else if (agg_instance_list_head != NULL) - { + else if (agg_instance_list_head != NULL) { agg_instance_t *prev = agg_instance_list_head; while ((prev != NULL) && (prev->next != inst)) prev = prev->next; if (prev != NULL) prev->next = inst->next; } - pthread_mutex_unlock (&agg_instance_list_lock); + pthread_mutex_unlock(&agg_instance_list_lock); - sfree (inst->state_num); - sfree (inst->state_sum); - sfree (inst->state_average); - sfree (inst->state_min); - sfree (inst->state_max); - sfree (inst->state_stddev); + sfree(inst->state_num); + sfree(inst->state_sum); + sfree(inst->state_average); + sfree(inst->state_min); + sfree(inst->state_max); + sfree(inst->state_stddev); - memset (inst, 0, sizeof (*inst)); + memset(inst, 0, sizeof(*inst)); inst->ds_type = -1; inst->min = NAN; inst->max = NAN; } /* }}} void agg_instance_destroy */ -static int agg_instance_create_name (agg_instance_t *inst, /* {{{ */ - value_list_t const *vl, aggregation_t const *agg) -{ -#define COPY_FIELD(buffer, buffer_size, field, group_mask, all_value) do { \ - if (agg->set_ ## field != NULL) \ - sstrncpy (buffer, agg->set_ ## field, buffer_size); \ - else if ((agg->regex_fields & group_mask) \ - && (agg->group_by & group_mask)) \ - sstrncpy (buffer, vl->field, buffer_size); \ - else if ((agg->regex_fields & group_mask) \ - && (AGG_MATCHES_ALL (agg->ident.field))) \ - sstrncpy (buffer, all_value, buffer_size); \ - else \ - sstrncpy (buffer, agg->ident.field, buffer_size); \ -} while (0) +static int agg_instance_create_name(agg_instance_t *inst, /* {{{ */ + value_list_t const *vl, + aggregation_t const *agg) { +#define COPY_FIELD(buffer, buffer_size, field, group_mask, all_value) \ + do { \ + if (agg->set_##field != NULL) \ + sstrncpy(buffer, agg->set_##field, buffer_size); \ + else if ((agg->regex_fields & group_mask) && (agg->group_by & group_mask)) \ + sstrncpy(buffer, vl->field, buffer_size); \ + else if ((agg->regex_fields & group_mask) && \ + (AGG_MATCHES_ALL(agg->ident.field))) \ + sstrncpy(buffer, all_value, buffer_size); \ + else \ + sstrncpy(buffer, agg->ident.field, buffer_size); \ + } while (0) /* Host */ - COPY_FIELD (inst->ident.host, sizeof (inst->ident.host), - host, LU_GROUP_BY_HOST, "global"); + COPY_FIELD(inst->ident.host, sizeof(inst->ident.host), host, LU_GROUP_BY_HOST, + "global"); /* Plugin */ if (agg->set_plugin != NULL) - sstrncpy (inst->ident.plugin, agg->set_plugin, - sizeof (inst->ident.plugin)); + sstrncpy(inst->ident.plugin, agg->set_plugin, sizeof(inst->ident.plugin)); else - sstrncpy (inst->ident.plugin, "aggregation", sizeof (inst->ident.plugin)); + sstrncpy(inst->ident.plugin, "aggregation", sizeof(inst->ident.plugin)); /* Plugin instance */ if (agg->set_plugin_instance != NULL) - sstrncpy (inst->ident.plugin_instance, agg->set_plugin_instance, - sizeof (inst->ident.plugin_instance)); - else - { + sstrncpy(inst->ident.plugin_instance, agg->set_plugin_instance, + sizeof(inst->ident.plugin_instance)); + else { char tmp_plugin[DATA_MAX_NAME_LEN]; char tmp_plugin_instance[DATA_MAX_NAME_LEN] = ""; - if ((agg->regex_fields & LU_GROUP_BY_PLUGIN) - && (agg->group_by & LU_GROUP_BY_PLUGIN)) - sstrncpy (tmp_plugin, vl->plugin, sizeof (tmp_plugin)); - else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN) - && (AGG_MATCHES_ALL (agg->ident.plugin))) - sstrncpy (tmp_plugin, "", sizeof (tmp_plugin)); + if ((agg->regex_fields & LU_GROUP_BY_PLUGIN) && + (agg->group_by & LU_GROUP_BY_PLUGIN)) + sstrncpy(tmp_plugin, vl->plugin, sizeof(tmp_plugin)); + else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN) && + (AGG_MATCHES_ALL(agg->ident.plugin))) + sstrncpy(tmp_plugin, "", sizeof(tmp_plugin)); else - sstrncpy (tmp_plugin, agg->ident.plugin, sizeof (tmp_plugin)); - - if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE) - && (agg->group_by & LU_GROUP_BY_PLUGIN_INSTANCE)) - sstrncpy (tmp_plugin_instance, vl->plugin_instance, - sizeof (tmp_plugin_instance)); - else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE) - && (AGG_MATCHES_ALL (agg->ident.plugin_instance))) - sstrncpy (tmp_plugin_instance, "", sizeof (tmp_plugin_instance)); + sstrncpy(tmp_plugin, agg->ident.plugin, sizeof(tmp_plugin)); + + if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE) && + (agg->group_by & LU_GROUP_BY_PLUGIN_INSTANCE)) + sstrncpy(tmp_plugin_instance, vl->plugin_instance, + sizeof(tmp_plugin_instance)); + else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE) && + (AGG_MATCHES_ALL(agg->ident.plugin_instance))) + sstrncpy(tmp_plugin_instance, "", sizeof(tmp_plugin_instance)); else - sstrncpy (tmp_plugin_instance, agg->ident.plugin_instance, - sizeof (tmp_plugin_instance)); - - if ((strcmp ("", tmp_plugin) == 0) - && (strcmp ("", tmp_plugin_instance) == 0)) - sstrncpy (inst->ident.plugin_instance, AGG_FUNC_PLACEHOLDER, - sizeof (inst->ident.plugin_instance)); - else if (strcmp ("", tmp_plugin) != 0) - ssnprintf (inst->ident.plugin_instance, - sizeof (inst->ident.plugin_instance), - "%s-%s", tmp_plugin, AGG_FUNC_PLACEHOLDER); - else if (strcmp ("", tmp_plugin_instance) != 0) - ssnprintf (inst->ident.plugin_instance, - sizeof (inst->ident.plugin_instance), - "%s-%s", tmp_plugin_instance, AGG_FUNC_PLACEHOLDER); + sstrncpy(tmp_plugin_instance, agg->ident.plugin_instance, + sizeof(tmp_plugin_instance)); + + if ((strcmp("", tmp_plugin) == 0) && (strcmp("", tmp_plugin_instance) == 0)) + sstrncpy(inst->ident.plugin_instance, AGG_FUNC_PLACEHOLDER, + sizeof(inst->ident.plugin_instance)); + else if (strcmp("", tmp_plugin) != 0) + ssnprintf(inst->ident.plugin_instance, + sizeof(inst->ident.plugin_instance), "%s-%s", tmp_plugin, + AGG_FUNC_PLACEHOLDER); + else if (strcmp("", tmp_plugin_instance) != 0) + ssnprintf(inst->ident.plugin_instance, + sizeof(inst->ident.plugin_instance), "%s-%s", + tmp_plugin_instance, AGG_FUNC_PLACEHOLDER); else - ssnprintf (inst->ident.plugin_instance, - sizeof (inst->ident.plugin_instance), - "%s-%s-%s", tmp_plugin, tmp_plugin_instance, AGG_FUNC_PLACEHOLDER); + ssnprintf(inst->ident.plugin_instance, + sizeof(inst->ident.plugin_instance), "%s-%s-%s", tmp_plugin, + tmp_plugin_instance, AGG_FUNC_PLACEHOLDER); } /* Type */ - sstrncpy (inst->ident.type, agg->ident.type, sizeof (inst->ident.type)); + sstrncpy(inst->ident.type, agg->ident.type, sizeof(inst->ident.type)); /* Type instance */ - COPY_FIELD (inst->ident.type_instance, sizeof (inst->ident.type_instance), - type_instance, LU_GROUP_BY_TYPE_INSTANCE, ""); + COPY_FIELD(inst->ident.type_instance, sizeof(inst->ident.type_instance), + type_instance, LU_GROUP_BY_TYPE_INSTANCE, ""); #undef COPY_FIELD @@ -233,56 +226,54 @@ static int agg_instance_create_name (agg_instance_t *inst, /* {{{ */ } /* }}} int agg_instance_create_name */ /* Create a new aggregation instance. */ -static agg_instance_t *agg_instance_create (data_set_t const *ds, /* {{{ */ - value_list_t const *vl, aggregation_t *agg) -{ +static agg_instance_t *agg_instance_create(data_set_t const *ds, /* {{{ */ + value_list_t const *vl, + aggregation_t *agg) { agg_instance_t *inst; - DEBUG ("aggregation plugin: Creating new instance."); + DEBUG("aggregation plugin: Creating new instance."); - inst = malloc (sizeof (*inst)); - if (inst == NULL) - { - ERROR ("aggregation plugin: malloc() failed."); + inst = calloc(1, sizeof(*inst)); + if (inst == NULL) { + ERROR("aggregation plugin: calloc() failed."); return (NULL); } - memset (inst, 0, sizeof (*inst)); - pthread_mutex_init (&inst->lock, /* attr = */ NULL); + pthread_mutex_init(&inst->lock, /* attr = */ NULL); inst->ds_type = ds->ds[0].type; - agg_instance_create_name (inst, vl, agg); + agg_instance_create_name(inst, vl, agg); inst->min = NAN; inst->max = NAN; -#define INIT_STATE(field) do { \ - inst->state_ ## field = NULL; \ - if (agg->calc_ ## field) { \ - inst->state_ ## field = malloc (sizeof (*inst->state_ ## field)); \ - if (inst->state_ ## field == NULL) { \ - agg_instance_destroy (inst); \ - free (inst); \ - ERROR ("aggregation plugin: malloc() failed."); \ - return (NULL); \ - } \ - memset (inst->state_ ## field, 0, sizeof (*inst->state_ ## field)); \ - } \ -} while (0) - - INIT_STATE (num); - INIT_STATE (sum); - INIT_STATE (average); - INIT_STATE (min); - INIT_STATE (max); - INIT_STATE (stddev); +#define INIT_STATE(field) \ + do { \ + inst->state_##field = NULL; \ + if (agg->calc_##field) { \ + inst->state_##field = calloc(1, sizeof(*inst->state_##field)); \ + if (inst->state_##field == NULL) { \ + agg_instance_destroy(inst); \ + free(inst); \ + ERROR("aggregation plugin: calloc() failed."); \ + return (NULL); \ + } \ + } \ + } while (0) + + INIT_STATE(num); + INIT_STATE(sum); + INIT_STATE(average); + INIT_STATE(min); + INIT_STATE(max); + INIT_STATE(stddev); #undef INIT_STATE - pthread_mutex_lock (&agg_instance_list_lock); + pthread_mutex_lock(&agg_instance_list_lock); inst->next = agg_instance_list_head; agg_instance_list_head = inst; - pthread_mutex_unlock (&agg_instance_list_lock); + pthread_mutex_unlock(&agg_instance_list_lock); return (inst); } /* }}} agg_instance_t *agg_instance_create */ @@ -291,84 +282,79 @@ static agg_instance_t *agg_instance_create (data_set_t const *ds, /* {{{ */ * the rate of the value list is available. Value lists with more than one data * source are not supported and will return an error. Returns zero on success * and non-zero otherwise. */ -static int agg_instance_update (agg_instance_t *inst, /* {{{ */ - data_set_t const *ds, value_list_t const *vl) -{ +static int agg_instance_update(agg_instance_t *inst, /* {{{ */ + data_set_t const *ds, value_list_t const *vl) { gauge_t *rate; - if (ds->ds_num != 1) - { - ERROR ("aggregation plugin: The \"%s\" type (data set) has more than one " - "data source. This is currently not supported by this plugin. " - "Sorry.", ds->type); + if (ds->ds_num != 1) { + ERROR("aggregation plugin: The \"%s\" type (data set) has more than one " + "data source. This is currently not supported by this plugin. " + "Sorry.", + ds->type); return (EINVAL); } - rate = uc_get_rate (ds, vl); - if (rate == NULL) - { + rate = uc_get_rate(ds, vl); + if (rate == NULL) { char ident[6 * DATA_MAX_NAME_LEN]; - FORMAT_VL (ident, sizeof (ident), vl); - ERROR ("aggregation plugin: Unable to read the current rate of \"%s\".", - ident); + FORMAT_VL(ident, sizeof(ident), vl); + ERROR("aggregation plugin: Unable to read the current rate of \"%s\".", + ident); return (ENOENT); } - if (isnan (rate[0])) - { - sfree (rate); + if (isnan(rate[0])) { + sfree(rate); return (0); } - pthread_mutex_lock (&inst->lock); + pthread_mutex_lock(&inst->lock); inst->num++; inst->sum += rate[0]; inst->squares_sum += (rate[0] * rate[0]); - if (isnan (inst->min) || (inst->min > rate[0])) + if (isnan(inst->min) || (inst->min > rate[0])) inst->min = rate[0]; - if (isnan (inst->max) || (inst->max < rate[0])) + if (isnan(inst->max) || (inst->max < rate[0])) inst->max = rate[0]; - pthread_mutex_unlock (&inst->lock); + pthread_mutex_unlock(&inst->lock); - sfree (rate); + sfree(rate); return (0); } /* }}} int agg_instance_update */ -static int agg_instance_read_func (agg_instance_t *inst, /* {{{ */ - char const *func, gauge_t rate, rate_to_value_state_t *state, - value_list_t *vl, char const *pi_prefix, cdtime_t t) -{ +static int agg_instance_read_func(agg_instance_t *inst, /* {{{ */ + char const *func, gauge_t rate, + rate_to_value_state_t *state, + value_list_t *vl, char const *pi_prefix, + cdtime_t t) { value_t v; int status; if (pi_prefix[0] != 0) - subst_string (vl->plugin_instance, sizeof (vl->plugin_instance), - pi_prefix, AGG_FUNC_PLACEHOLDER, func); + subst_string(vl->plugin_instance, sizeof(vl->plugin_instance), pi_prefix, + AGG_FUNC_PLACEHOLDER, func); else - sstrncpy (vl->plugin_instance, func, sizeof (vl->plugin_instance)); + 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) - { + status = rate_to_value(&v, rate, state, inst->ds_type, t); + if (status != 0) { /* If this is the first iteration and rate_to_value() was asked to return a * COUNTER or a DERIVE, it will return EAGAIN. Catch this and handle * gracefully. */ if (status == EAGAIN) return (0); - WARNING ("aggregation plugin: rate_to_value failed with status %i.", - status); + WARNING("aggregation plugin: rate_to_value failed with status %i.", status); return (-1); } vl->values = &v; vl->values_len = 1; - plugin_dispatch_values (vl); + plugin_dispatch_values(vl); vl->values = NULL; vl->values_len = 0; @@ -376,7 +362,7 @@ static int agg_instance_read_func (agg_instance_t *inst, /* {{{ */ return (0); } /* }}} int agg_instance_read_func */ -static int agg_instance_read (agg_instance_t *inst, cdtime_t t) /* {{{ */ +static int agg_instance_read(agg_instance_t *inst, cdtime_t t) /* {{{ */ { value_list_t vl = VALUE_LIST_INIT; @@ -387,41 +373,41 @@ static int agg_instance_read (agg_instance_t *inst, cdtime_t t) /* {{{ */ vl.time = t; vl.interval = 0; - vl.meta = meta_data_create (); - if (vl.meta == NULL) - { - ERROR ("aggregation plugin: meta_data_create failed."); + vl.meta = meta_data_create(); + if (vl.meta == NULL) { + ERROR("aggregation plugin: meta_data_create failed."); return (-1); } - meta_data_add_boolean (vl.meta, "aggregation:created", 1); + meta_data_add_boolean(vl.meta, "aggregation:created", 1); - sstrncpy (vl.host, inst->ident.host, sizeof (vl.host)); - sstrncpy (vl.plugin, inst->ident.plugin, sizeof (vl.plugin)); - sstrncpy (vl.type, inst->ident.type, sizeof (vl.type)); - sstrncpy (vl.type_instance, inst->ident.type_instance, - sizeof (vl.type_instance)); + sstrncpy(vl.host, inst->ident.host, sizeof(vl.host)); + sstrncpy(vl.plugin, inst->ident.plugin, sizeof(vl.plugin)); + sstrncpy(vl.type, inst->ident.type, sizeof(vl.type)); + sstrncpy(vl.type_instance, inst->ident.type_instance, + sizeof(vl.type_instance)); -#define READ_FUNC(func, rate) do { \ - if (inst->state_ ## func != NULL) { \ - agg_instance_read_func (inst, #func, rate, \ - inst->state_ ## func, &vl, inst->ident.plugin_instance, t); \ - } \ -} while (0) +#define READ_FUNC(func, rate) \ + do { \ + if (inst->state_##func != NULL) { \ + agg_instance_read_func(inst, #func, rate, inst->state_##func, &vl, \ + inst->ident.plugin_instance, t); \ + } \ + } while (0) - pthread_mutex_lock (&inst->lock); + pthread_mutex_lock(&inst->lock); - READ_FUNC (num, (gauge_t) inst->num); + READ_FUNC(num, (gauge_t)inst->num); /* All other aggregations are only defined when there have been any values * at all. */ - if (inst->num > 0) - { - READ_FUNC (sum, inst->sum); - READ_FUNC (average, (inst->sum / ((gauge_t) inst->num))); - READ_FUNC (min, inst->min); - READ_FUNC (max, inst->max); - READ_FUNC (stddev, sqrt((((gauge_t) inst->num) * inst->squares_sum) - - (inst->sum * inst->sum)) / ((gauge_t) inst->num)); + if (inst->num > 0) { + READ_FUNC(sum, inst->sum); + READ_FUNC(average, (inst->sum / ((gauge_t)inst->num))); + READ_FUNC(min, inst->min); + READ_FUNC(max, inst->max); + READ_FUNC(stddev, sqrt((((gauge_t)inst->num) * inst->squares_sum) - + (inst->sum * inst->sum)) / + ((gauge_t)inst->num)); } /* Reset internal state. */ @@ -431,40 +417,40 @@ static int agg_instance_read (agg_instance_t *inst, cdtime_t t) /* {{{ */ inst->min = NAN; inst->max = NAN; - pthread_mutex_unlock (&inst->lock); + pthread_mutex_unlock(&inst->lock); - meta_data_destroy (vl.meta); + meta_data_destroy(vl.meta); vl.meta = NULL; return (0); } /* }}} int agg_instance_read */ /* lookup_class_callback_t for utils_vl_lookup */ -static void *agg_lookup_class_callback ( /* {{{ */ - data_set_t const *ds, value_list_t const *vl, void *user_class) -{ - return (agg_instance_create (ds, vl, (aggregation_t *) user_class)); +static void *agg_lookup_class_callback(/* {{{ */ + data_set_t const *ds, + value_list_t const *vl, + void *user_class) { + return (agg_instance_create(ds, vl, (aggregation_t *)user_class)); } /* }}} void *agg_class_callback */ /* lookup_obj_callback_t for utils_vl_lookup */ -static int agg_lookup_obj_callback (data_set_t const *ds, /* {{{ */ - value_list_t const *vl, - __attribute__((unused)) void *user_class, - void *user_obj) -{ - return (agg_instance_update ((agg_instance_t *) user_obj, ds, vl)); +static int agg_lookup_obj_callback(data_set_t const *ds, /* {{{ */ + value_list_t const *vl, + __attribute__((unused)) void *user_class, + void *user_obj) { + return (agg_instance_update((agg_instance_t *)user_obj, ds, vl)); } /* }}} int agg_lookup_obj_callback */ /* lookup_free_class_callback_t for utils_vl_lookup */ -static void agg_lookup_free_class_callback (void *user_class) /* {{{ */ +static void agg_lookup_free_class_callback(void *user_class) /* {{{ */ { - agg_destroy ((aggregation_t *) user_class); + agg_destroy((aggregation_t *)user_class); } /* }}} void agg_lookup_free_class_callback */ /* lookup_free_obj_callback_t for utils_vl_lookup */ -static void agg_lookup_free_obj_callback (void *user_obj) /* {{{ */ +static void agg_lookup_free_obj_callback(void *user_obj) /* {{{ */ { - agg_instance_destroy ((agg_instance_t *) user_obj); + agg_instance_destroy((agg_instance_t *)user_obj); } /* }}} void agg_lookup_free_obj_callback */ /* @@ -485,247 +471,229 @@ static void agg_lookup_free_obj_callback (void *user_obj) /* {{{ */ * * */ -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++) - { +static int agg_config_handle_group_by(oconfig_item_t const *ci, /* {{{ */ + aggregation_t *agg) { + for (int i = 0; i < ci->values_num; i++) { char const *value; - if (ci->values[i].type != OCONFIG_TYPE_STRING) - { - ERROR ("aggregation plugin: Argument %i of the \"GroupBy\" option " - "is not a string.", i + 1); + if (ci->values[i].type != OCONFIG_TYPE_STRING) { + ERROR("aggregation plugin: Argument %i of the \"GroupBy\" option " + "is not a string.", + i + 1); continue; } value = ci->values[i].value.string; - if (strcasecmp ("Host", value) == 0) + if (strcasecmp("Host", value) == 0) agg->group_by |= LU_GROUP_BY_HOST; - else if (strcasecmp ("Plugin", value) == 0) + else if (strcasecmp("Plugin", value) == 0) agg->group_by |= LU_GROUP_BY_PLUGIN; - else if (strcasecmp ("PluginInstance", value) == 0) + else if (strcasecmp("PluginInstance", value) == 0) agg->group_by |= LU_GROUP_BY_PLUGIN_INSTANCE; - else if (strcasecmp ("TypeInstance", value) == 0) + else if (strcasecmp("TypeInstance", value) == 0) agg->group_by |= LU_GROUP_BY_TYPE_INSTANCE; - else if (strcasecmp ("Type", value) == 0) - ERROR ("aggregation plugin: Grouping by type is not supported."); + else if (strcasecmp("Type", value) == 0) + ERROR("aggregation plugin: Grouping by type is not supported."); else - WARNING ("aggregation plugin: The \"%s\" argument to the \"GroupBy\" " - "option is invalid and will be ignored.", value); + WARNING("aggregation plugin: The \"%s\" argument to the \"GroupBy\" " + "option is invalid and will be ignored.", + value); } /* for (ci->values) */ return (0); } /* }}} int agg_config_handle_group_by */ -static int agg_config_aggregation (oconfig_item_t *ci) /* {{{ */ +static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */ { aggregation_t *agg; _Bool is_valid; int status; - int i; - agg = malloc (sizeof (*agg)); - if (agg == NULL) - { - ERROR ("aggregation plugin: malloc failed."); + agg = calloc(1, sizeof(*agg)); + if (agg == NULL) { + 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.plugin_instance, "/.*/", - sizeof (agg->ident.plugin_instance)); - sstrncpy (agg->ident.type, "/.*/", sizeof (agg->ident.type)); - sstrncpy (agg->ident.type_instance, "/.*/", - sizeof (agg->ident.type_instance)); + sstrncpy(agg->ident.host, "/.*/", sizeof(agg->ident.host)); + sstrncpy(agg->ident.plugin, "/.*/", sizeof(agg->ident.plugin)); + sstrncpy(agg->ident.plugin_instance, "/.*/", + sizeof(agg->ident.plugin_instance)); + sstrncpy(agg->ident.type, "/.*/", sizeof(agg->ident.type)); + 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; - if (strcasecmp ("Host", child->key) == 0) - cf_util_get_string_buffer (child, agg->ident.host, - sizeof (agg->ident.host)); - else if (strcasecmp ("Plugin", child->key) == 0) - cf_util_get_string_buffer (child, agg->ident.plugin, - sizeof (agg->ident.plugin)); - else if (strcasecmp ("PluginInstance", child->key) == 0) - cf_util_get_string_buffer (child, agg->ident.plugin_instance, - sizeof (agg->ident.plugin_instance)); - else if (strcasecmp ("Type", child->key) == 0) - cf_util_get_string_buffer (child, agg->ident.type, - sizeof (agg->ident.type)); - else if (strcasecmp ("TypeInstance", child->key) == 0) - cf_util_get_string_buffer (child, agg->ident.type_instance, - sizeof (agg->ident.type_instance)); - else if (strcasecmp ("SetHost", child->key) == 0) - cf_util_get_string (child, &agg->set_host); - else if (strcasecmp ("SetPlugin", child->key) == 0) - cf_util_get_string (child, &agg->set_plugin); - else if (strcasecmp ("SetPluginInstance", child->key) == 0) - cf_util_get_string (child, &agg->set_plugin_instance); - else if (strcasecmp ("SetTypeInstance", child->key) == 0) - cf_util_get_string (child, &agg->set_type_instance); - else if (strcasecmp ("GroupBy", child->key) == 0) - agg_config_handle_group_by (child, agg); - else if (strcasecmp ("CalculateNum", child->key) == 0) - cf_util_get_boolean (child, &agg->calc_num); - else if (strcasecmp ("CalculateSum", child->key) == 0) - cf_util_get_boolean (child, &agg->calc_sum); - else if (strcasecmp ("CalculateAverage", child->key) == 0) - cf_util_get_boolean (child, &agg->calc_average); - else if (strcasecmp ("CalculateMinimum", child->key) == 0) - cf_util_get_boolean (child, &agg->calc_min); - else if (strcasecmp ("CalculateMaximum", child->key) == 0) - cf_util_get_boolean (child, &agg->calc_max); - else if (strcasecmp ("CalculateStddev", child->key) == 0) - cf_util_get_boolean (child, &agg->calc_stddev); + if (strcasecmp("Host", child->key) == 0) + cf_util_get_string_buffer(child, agg->ident.host, + sizeof(agg->ident.host)); + else if (strcasecmp("Plugin", child->key) == 0) + cf_util_get_string_buffer(child, agg->ident.plugin, + sizeof(agg->ident.plugin)); + else if (strcasecmp("PluginInstance", child->key) == 0) + cf_util_get_string_buffer(child, agg->ident.plugin_instance, + sizeof(agg->ident.plugin_instance)); + else if (strcasecmp("Type", child->key) == 0) + cf_util_get_string_buffer(child, agg->ident.type, + sizeof(agg->ident.type)); + else if (strcasecmp("TypeInstance", child->key) == 0) + cf_util_get_string_buffer(child, agg->ident.type_instance, + sizeof(agg->ident.type_instance)); + else if (strcasecmp("SetHost", child->key) == 0) + cf_util_get_string(child, &agg->set_host); + else if (strcasecmp("SetPlugin", child->key) == 0) + cf_util_get_string(child, &agg->set_plugin); + else if (strcasecmp("SetPluginInstance", child->key) == 0) + cf_util_get_string(child, &agg->set_plugin_instance); + else if (strcasecmp("SetTypeInstance", child->key) == 0) + cf_util_get_string(child, &agg->set_type_instance); + else if (strcasecmp("GroupBy", child->key) == 0) + agg_config_handle_group_by(child, agg); + else if (strcasecmp("CalculateNum", child->key) == 0) + cf_util_get_boolean(child, &agg->calc_num); + else if (strcasecmp("CalculateSum", child->key) == 0) + cf_util_get_boolean(child, &agg->calc_sum); + else if (strcasecmp("CalculateAverage", child->key) == 0) + cf_util_get_boolean(child, &agg->calc_average); + else if (strcasecmp("CalculateMinimum", child->key) == 0) + cf_util_get_boolean(child, &agg->calc_min); + else if (strcasecmp("CalculateMaximum", child->key) == 0) + cf_util_get_boolean(child, &agg->calc_max); + else if (strcasecmp("CalculateStddev", child->key) == 0) + cf_util_get_boolean(child, &agg->calc_stddev); else - WARNING ("aggregation plugin: The \"%s\" key is not allowed inside " - " blocks and will be ignored.", child->key); + WARNING("aggregation plugin: The \"%s\" key is not allowed inside " + " blocks and will be ignored.", + child->key); } - if (agg_is_regex (agg->ident.host)) + if (agg_is_regex(agg->ident.host)) agg->regex_fields |= LU_GROUP_BY_HOST; - if (agg_is_regex (agg->ident.plugin)) + if (agg_is_regex(agg->ident.plugin)) agg->regex_fields |= LU_GROUP_BY_PLUGIN; - if (agg_is_regex (agg->ident.plugin_instance)) + if (agg_is_regex(agg->ident.plugin_instance)) agg->regex_fields |= LU_GROUP_BY_PLUGIN_INSTANCE; - if (agg_is_regex (agg->ident.type_instance)) + if (agg_is_regex(agg->ident.type_instance)) agg->regex_fields |= LU_GROUP_BY_TYPE_INSTANCE; /* Sanity checking */ is_valid = 1; - if (strcmp ("/.*/", agg->ident.type) == 0) /* {{{ */ + if (strcmp("/.*/", agg->ident.type) == 0) /* {{{ */ { - ERROR ("aggregation plugin: It appears you did not specify the required " - "\"Type\" option in this aggregation. " - "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " - "Type \"%s\", TypeInstance \"%s\")", - agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, - agg->ident.type, agg->ident.type_instance); + ERROR("aggregation plugin: It appears you did not specify the required " + "\"Type\" option in this aggregation. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); is_valid = 0; - } - else if (strchr (agg->ident.type, '/') != NULL) - { - ERROR ("aggregation plugin: The \"Type\" may not contain the '/' " - "character. Especially, it may not be a regex. The current " - "value is \"%s\".", agg->ident.type); + } else if (strchr(agg->ident.type, '/') != NULL) { + ERROR("aggregation plugin: The \"Type\" may not contain the '/' " + "character. Especially, it may not be a regex. The current " + "value is \"%s\".", + agg->ident.type); is_valid = 0; } /* }}} */ /* Check that there is at least one regex field without a grouping. {{{ */ - if ((agg->regex_fields & ~agg->group_by) == 0) - { - ERROR ("aggregation plugin: An aggregation must contain at least one " - "wildcard. This is achieved by leaving at least one of the \"Host\", " - "\"Plugin\", \"PluginInstance\" and \"TypeInstance\" options blank " - "or using a regular expression and not grouping by that field. " - "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " - "Type \"%s\", TypeInstance \"%s\")", - agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, - agg->ident.type, agg->ident.type_instance); + if ((agg->regex_fields & ~agg->group_by) == 0) { + ERROR("aggregation plugin: An aggregation must contain at least one " + "wildcard. This is achieved by leaving at least one of the \"Host\", " + "\"Plugin\", \"PluginInstance\" and \"TypeInstance\" options blank " + "or using a regular expression and not grouping by that field. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); is_valid = 0; } /* }}} */ /* Check that all grouping fields are regular expressions. {{{ */ - if (agg->group_by & ~agg->regex_fields) - { - ERROR ("aggregation plugin: Only wildcard fields (fields for which a " - "regular expression is configured or which are left blank) can be " - "specified in the \"GroupBy\" option. " - "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " - "Type \"%s\", TypeInstance \"%s\")", - agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, - agg->ident.type, agg->ident.type_instance); + if (agg->group_by & ~agg->regex_fields) { + ERROR("aggregation plugin: Only wildcard fields (fields for which a " + "regular expression is configured or which are left blank) can be " + "specified in the \"GroupBy\" option. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); is_valid = 0; } /* }}} */ if (!agg->calc_num && !agg->calc_sum && !agg->calc_average /* {{{ */ - && !agg->calc_min && !agg->calc_max && !agg->calc_stddev) - { - ERROR ("aggregation plugin: No aggregation function has been specified. " - "Without this, I don't know what I should be calculating. " - "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " - "Type \"%s\", TypeInstance \"%s\")", - agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, - agg->ident.type, agg->ident.type_instance); + && !agg->calc_min && !agg->calc_max && !agg->calc_stddev) { + ERROR("aggregation plugin: No aggregation function has been specified. " + "Without this, I don't know what I should be calculating. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); is_valid = 0; } /* }}} */ if (!is_valid) /* {{{ */ { - sfree (agg); + sfree(agg); return (-1); } /* }}} */ - status = lookup_add (lookup, &agg->ident, agg->group_by, agg); - if (status != 0) - { - ERROR ("aggregation plugin: lookup_add failed with status %i.", status); - sfree (agg); + status = lookup_add(lookup, &agg->ident, agg->group_by, agg); + if (status != 0) { + ERROR("aggregation plugin: lookup_add failed with status %i.", status); + sfree(agg); return (-1); } - DEBUG ("aggregation plugin: Successfully added aggregation: " - "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " - "Type \"%s\", TypeInstance \"%s\")", - agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, - agg->ident.type, agg->ident.type_instance); + DEBUG("aggregation plugin: Successfully added aggregation: " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); return (0); } /* }}} int agg_config_aggregation */ -static int agg_config (oconfig_item_t *ci) /* {{{ */ +static int agg_config(oconfig_item_t *ci) /* {{{ */ { - int i; - - pthread_mutex_lock (&agg_instance_list_lock); - - if (lookup == NULL) - { - lookup = lookup_create (agg_lookup_class_callback, - agg_lookup_obj_callback, - agg_lookup_free_class_callback, - agg_lookup_free_obj_callback); - if (lookup == NULL) - { - pthread_mutex_unlock (&agg_instance_list_lock); - ERROR ("aggregation plugin: lookup_create failed."); + pthread_mutex_lock(&agg_instance_list_lock); + + if (lookup == NULL) { + lookup = lookup_create(agg_lookup_class_callback, agg_lookup_obj_callback, + agg_lookup_free_class_callback, + agg_lookup_free_obj_callback); + if (lookup == NULL) { + pthread_mutex_unlock(&agg_instance_list_lock); + ERROR("aggregation plugin: lookup_create 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; - if (strcasecmp ("Aggregation", child->key) == 0) - agg_config_aggregation (child); + if (strcasecmp("Aggregation", child->key) == 0) + agg_config_aggregation(child); else - WARNING ("aggregation plugin: The \"%s\" key is not allowed inside " - " blocks and will be ignored.", child->key); + WARNING("aggregation plugin: The \"%s\" key is not allowed inside " + " blocks and will be ignored.", + child->key); } - pthread_mutex_unlock (&agg_instance_list_lock); + pthread_mutex_unlock(&agg_instance_list_lock); return (0); } /* }}} int agg_config */ -static int agg_read (void) /* {{{ */ +static int agg_read(void) /* {{{ */ { - agg_instance_t *this; cdtime_t t; int success; - t = cdtime (); + t = cdtime(); success = 0; - pthread_mutex_lock (&agg_instance_list_lock); + pthread_mutex_lock(&agg_instance_list_lock); /* agg_instance_list_head only holds data, after the "write" callback has * been called with a matching value list at least once. So on startup, @@ -733,47 +701,45 @@ static int agg_read (void) /* {{{ */ * the read() callback is called first, agg_instance_list_head is NULL and * "success" may be zero. This is expected and should not result in an error. * Therefore we need to handle this case separately. */ - if (agg_instance_list_head == NULL) - { - pthread_mutex_unlock (&agg_instance_list_lock); + if (agg_instance_list_head == NULL) { + pthread_mutex_unlock(&agg_instance_list_lock); 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; - status = agg_instance_read (this, t); + status = agg_instance_read(this, t); if (status != 0) - WARNING ("aggregation plugin: Reading an aggregation instance " - "failed with status %i.", status); + WARNING("aggregation plugin: Reading an aggregation instance " + "failed with status %i.", + status); else success++; } - pthread_mutex_unlock (&agg_instance_list_lock); + pthread_mutex_unlock(&agg_instance_list_lock); return ((success > 0) ? 0 : -1); } /* }}} int agg_read */ -static int agg_write (data_set_t const *ds, value_list_t const *vl, /* {{{ */ - __attribute__((unused)) user_data_t *user_data) -{ +static int agg_write(data_set_t const *ds, value_list_t const *vl, /* {{{ */ + __attribute__((unused)) user_data_t *user_data) { _Bool created_by_aggregation = 0; int status; /* Ignore values that were created by the aggregation plugin to avoid weird * effects. */ - (void) meta_data_get_boolean (vl->meta, "aggregation:created", - &created_by_aggregation); + (void)meta_data_get_boolean(vl->meta, "aggregation:created", + &created_by_aggregation); if (created_by_aggregation) return (0); if (lookup == NULL) status = ENOENT; - else - { - status = lookup_search (lookup, ds, vl); + else { + status = lookup_search(lookup, ds, vl); if (status > 0) status = 0; } @@ -781,11 +747,10 @@ static int agg_write (data_set_t const *ds, value_list_t const *vl, /* {{{ */ return (status); } /* }}} int agg_write */ -void module_register (void) -{ - plugin_register_complex_config ("aggregation", agg_config); - plugin_register_read ("aggregation", agg_read); - plugin_register_write ("aggregation", agg_write, /* user_data = */ NULL); +void module_register(void) { + plugin_register_complex_config("aggregation", agg_config); + plugin_register_read("aggregation", agg_read); + plugin_register_write("aggregation", agg_write, /* user_data = */ NULL); } /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */ diff --git a/src/amqp.c b/src/amqp.c index 4206bdc1..a9d91a7d 100644 --- a/src/amqp.c +++ b/src/amqp.c @@ -27,22 +27,21 @@ **/ #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 +#include "utils_format_json.h" #include #include #ifdef HAVE_AMQP_TCP_SOCKET_H -# include +#include #endif #ifdef HAVE_AMQP_SOCKET_H -# include +#include #endif #ifdef HAVE_AMQP_TCP_SOCKET #if defined HAVE_DECL_AMQP_SOCKET_CLOSE && !HAVE_DECL_AMQP_SOCKET_CLOSE @@ -54,1078 +53,973 @@ int amqp_socket_close(amqp_socket_t *); /* Defines for the delivery mode. I have no idea why they're not defined by the * library.. */ -#define CAMQP_DM_VOLATILE 1 +#define CAMQP_DM_VOLATILE 1 #define CAMQP_DM_PERSISTENT 2 -#define CAMQP_FORMAT_COMMAND 1 -#define CAMQP_FORMAT_JSON 2 -#define CAMQP_FORMAT_GRAPHITE 3 +#define CAMQP_FORMAT_COMMAND 1 +#define CAMQP_FORMAT_JSON 2 +#define CAMQP_FORMAT_GRAPHITE 3 #define CAMQP_CHANNEL 1 /* * Data types */ -struct camqp_config_s -{ - _Bool publish; - char *name; - - char *host; - int port; - char *vhost; - char *user; - char *password; - - char *exchange; - char *routing_key; - - /* Number of seconds to wait before connection is retried */ - int connection_retry_delay; - - /* publish only */ - uint8_t delivery_mode; - _Bool store_rates; - int format; - /* publish & graphite format only */ - char *prefix; - char *postfix; - char escape_char; - unsigned int graphite_flags; - - /* subscribe only */ - char *exchange_type; - char *queue; - _Bool queue_durable; - _Bool queue_auto_delete; - - amqp_connection_state_t connection; - pthread_mutex_t lock; +struct camqp_config_s { + _Bool publish; + char *name; + + char *host; + int port; + char *vhost; + char *user; + char *password; + + char *exchange; + char *routing_key; + + /* Number of seconds to wait before connection is retried */ + int connection_retry_delay; + + /* publish only */ + uint8_t delivery_mode; + _Bool store_rates; + int format; + /* publish & graphite format only */ + char *prefix; + char *postfix; + char escape_char; + unsigned int graphite_flags; + + /* subscribe only */ + char *exchange_type; + char *queue; + _Bool queue_durable; + _Bool queue_auto_delete; + + amqp_connection_state_t connection; + pthread_mutex_t lock; }; typedef struct camqp_config_s camqp_config_t; /* * Global variables */ -static const char *def_host = "localhost"; -static const char *def_vhost = "/"; -static const char *def_user = "guest"; -static const char *def_password = "guest"; -static const char *def_exchange = "amq.fanout"; +static const char *def_host = "localhost"; +static const char *def_vhost = "/"; +static const char *def_user = "guest"; +static const char *def_password = "guest"; +static const char *def_exchange = "amq.fanout"; -static pthread_t *subscriber_threads = NULL; -static size_t subscriber_threads_num = 0; -static _Bool subscriber_threads_running = 1; +static pthread_t *subscriber_threads = NULL; +static size_t subscriber_threads_num = 0; +static _Bool subscriber_threads_running = 1; -#define CONF(c,f) (((c)->f != NULL) ? (c)->f : def_##f) +#define CONF(c, f) (((c)->f != NULL) ? (c)->f : def_##f) /* * Functions */ -static void camqp_close_connection (camqp_config_t *conf) /* {{{ */ +static void camqp_close_connection(camqp_config_t *conf) /* {{{ */ { - int sockfd; + int sockfd; - if ((conf == NULL) || (conf->connection == NULL)) - return; + if ((conf == NULL) || (conf->connection == NULL)) + return; - sockfd = amqp_get_sockfd (conf->connection); - amqp_channel_close (conf->connection, CAMQP_CHANNEL, AMQP_REPLY_SUCCESS); - amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS); - amqp_destroy_connection (conf->connection); - close (sockfd); - conf->connection = NULL; + sockfd = amqp_get_sockfd(conf->connection); + amqp_channel_close(conf->connection, CAMQP_CHANNEL, AMQP_REPLY_SUCCESS); + amqp_connection_close(conf->connection, AMQP_REPLY_SUCCESS); + amqp_destroy_connection(conf->connection); + close(sockfd); + conf->connection = NULL; } /* }}} void camqp_close_connection */ -static void camqp_config_free (void *ptr) /* {{{ */ +static void camqp_config_free(void *ptr) /* {{{ */ { - camqp_config_t *conf = ptr; - - if (conf == NULL) - return; - - camqp_close_connection (conf); - - sfree (conf->name); - sfree (conf->host); - sfree (conf->vhost); - sfree (conf->user); - sfree (conf->password); - sfree (conf->exchange); - sfree (conf->exchange_type); - sfree (conf->queue); - sfree (conf->routing_key); - sfree (conf->prefix); - sfree (conf->postfix); - - - sfree (conf); + camqp_config_t *conf = ptr; + + if (conf == NULL) + return; + + camqp_close_connection(conf); + + sfree(conf->name); + sfree(conf->host); + sfree(conf->vhost); + sfree(conf->user); + sfree(conf->password); + sfree(conf->exchange); + sfree(conf->exchange_type); + sfree(conf->queue); + sfree(conf->routing_key); + sfree(conf->prefix); + sfree(conf->postfix); + + sfree(conf); } /* }}} void camqp_config_free */ -static char *camqp_bytes_cstring (amqp_bytes_t *in) /* {{{ */ +static char *camqp_bytes_cstring(amqp_bytes_t *in) /* {{{ */ { - char *ret; + char *ret; - if ((in == NULL) || (in->bytes == NULL)) - return (NULL); + if ((in == NULL) || (in->bytes == NULL)) + return (NULL); - ret = malloc (in->len + 1); - if (ret == NULL) - return (NULL); + ret = malloc(in->len + 1); + if (ret == NULL) + return (NULL); - memcpy (ret, in->bytes, in->len); - ret[in->len] = 0; + memcpy(ret, in->bytes, in->len); + ret[in->len] = 0; - return (ret); + return (ret); } /* }}} char *camqp_bytes_cstring */ -static _Bool camqp_is_error (camqp_config_t *conf) /* {{{ */ +static _Bool camqp_is_error(camqp_config_t *conf) /* {{{ */ { - amqp_rpc_reply_t r; + amqp_rpc_reply_t r; - r = amqp_get_rpc_reply (conf->connection); - if (r.reply_type == AMQP_RESPONSE_NORMAL) - return (0); + r = amqp_get_rpc_reply(conf->connection); + if (r.reply_type == AMQP_RESPONSE_NORMAL) + return (0); - return (1); + return (1); } /* }}} _Bool camqp_is_error */ -static char *camqp_strerror (camqp_config_t *conf, /* {{{ */ - char *buffer, size_t buffer_size) -{ - amqp_rpc_reply_t r; +static char *camqp_strerror(camqp_config_t *conf, /* {{{ */ + char *buffer, size_t buffer_size) { + amqp_rpc_reply_t r; - r = amqp_get_rpc_reply (conf->connection); - switch (r.reply_type) - { - case AMQP_RESPONSE_NORMAL: - sstrncpy (buffer, "Success", buffer_size); - break; + r = amqp_get_rpc_reply(conf->connection); + switch (r.reply_type) { + case AMQP_RESPONSE_NORMAL: + sstrncpy(buffer, "Success", buffer_size); + break; - case AMQP_RESPONSE_NONE: - sstrncpy (buffer, "Missing RPC reply type", buffer_size); - break; + case AMQP_RESPONSE_NONE: + sstrncpy(buffer, "Missing RPC reply type", buffer_size); + break; - case AMQP_RESPONSE_LIBRARY_EXCEPTION: + case AMQP_RESPONSE_LIBRARY_EXCEPTION: #if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO - if (r.library_errno) - return (sstrerror (r.library_errno, buffer, buffer_size)); + if (r.library_errno) + return (sstrerror(r.library_errno, buffer, buffer_size)); #else - if (r.library_error) - return (sstrerror (r.library_error, buffer, buffer_size)); + if (r.library_error) + return (sstrerror(r.library_error, buffer, buffer_size)); #endif - else - sstrncpy (buffer, "End of stream", buffer_size); - break; - - case AMQP_RESPONSE_SERVER_EXCEPTION: - if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD) - { - amqp_connection_close_t *m = r.reply.decoded; - char *tmp = camqp_bytes_cstring (&m->reply_text); - ssnprintf (buffer, buffer_size, "Server connection error %d: %s", - m->reply_code, tmp); - sfree (tmp); - } - else if (r.reply.id == AMQP_CHANNEL_CLOSE_METHOD) - { - amqp_channel_close_t *m = r.reply.decoded; - char *tmp = camqp_bytes_cstring (&m->reply_text); - ssnprintf (buffer, buffer_size, "Server channel error %d: %s", - m->reply_code, tmp); - sfree (tmp); - } - else - { - ssnprintf (buffer, buffer_size, "Server error method %#"PRIx32, - r.reply.id); - } - break; - - default: - ssnprintf (buffer, buffer_size, "Unknown reply type %i", - (int) r.reply_type); + else + sstrncpy(buffer, "End of stream", buffer_size); + break; + + case AMQP_RESPONSE_SERVER_EXCEPTION: + if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD) { + amqp_connection_close_t *m = r.reply.decoded; + char *tmp = camqp_bytes_cstring(&m->reply_text); + ssnprintf(buffer, buffer_size, "Server connection error %d: %s", + m->reply_code, tmp); + sfree(tmp); + } else if (r.reply.id == AMQP_CHANNEL_CLOSE_METHOD) { + amqp_channel_close_t *m = r.reply.decoded; + char *tmp = camqp_bytes_cstring(&m->reply_text); + ssnprintf(buffer, buffer_size, "Server channel error %d: %s", + m->reply_code, tmp); + sfree(tmp); + } else { + ssnprintf(buffer, buffer_size, "Server error method %#" PRIx32, + r.reply.id); } + break; - return (buffer); + default: + ssnprintf(buffer, buffer_size, "Unknown reply type %i", (int)r.reply_type); + } + + return (buffer); } /* }}} char *camqp_strerror */ #if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO -static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */ +static int camqp_create_exchange(camqp_config_t *conf) /* {{{ */ { - amqp_exchange_declare_ok_t *ed_ret; - - if (conf->exchange_type == NULL) - return (0); - - ed_ret = amqp_exchange_declare (conf->connection, - /* channel = */ CAMQP_CHANNEL, - /* exchange = */ amqp_cstring_bytes (conf->exchange), - /* type = */ amqp_cstring_bytes (conf->exchange_type), - /* passive = */ 0, - /* durable = */ 0, - /* auto_delete = */ 1, - /* arguments = */ AMQP_EMPTY_TABLE); - if ((ed_ret == NULL) && camqp_is_error (conf)) - { - char errbuf[1024]; - ERROR ("amqp plugin: amqp_exchange_declare failed: %s", - camqp_strerror (conf, errbuf, sizeof (errbuf))); - camqp_close_connection (conf); - return (-1); - } - - INFO ("amqp plugin: Successfully created exchange \"%s\" " - "with type \"%s\".", - conf->exchange, conf->exchange_type); + amqp_exchange_declare_ok_t *ed_ret; + if (conf->exchange_type == NULL) return (0); + + ed_ret = amqp_exchange_declare( + conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* exchange = */ amqp_cstring_bytes(conf->exchange), + /* type = */ amqp_cstring_bytes(conf->exchange_type), + /* passive = */ 0, + /* durable = */ 0, + /* auto_delete = */ 1, + /* arguments = */ AMQP_EMPTY_TABLE); + if ((ed_ret == NULL) && camqp_is_error(conf)) { + char errbuf[1024]; + ERROR("amqp plugin: amqp_exchange_declare failed: %s", + camqp_strerror(conf, errbuf, sizeof(errbuf))); + camqp_close_connection(conf); + return (-1); + } + + INFO("amqp plugin: Successfully created exchange \"%s\" " + "with type \"%s\".", + conf->exchange, conf->exchange_type); + + return (0); } /* }}} int camqp_create_exchange */ #else -static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */ +static int camqp_create_exchange(camqp_config_t *conf) /* {{{ */ { - amqp_exchange_declare_ok_t *ed_ret; - amqp_table_t argument_table; - struct amqp_table_entry_t_ argument_table_entries[1]; - - if (conf->exchange_type == NULL) - return (0); - - /* Valid arguments: "auto_delete", "internal" */ - argument_table.num_entries = STATIC_ARRAY_SIZE (argument_table_entries); - argument_table.entries = argument_table_entries; - argument_table_entries[0].key = amqp_cstring_bytes ("auto_delete"); - argument_table_entries[0].value.kind = AMQP_FIELD_KIND_BOOLEAN; - argument_table_entries[0].value.value.boolean = 1; - - ed_ret = amqp_exchange_declare (conf->connection, - /* channel = */ CAMQP_CHANNEL, - /* exchange = */ amqp_cstring_bytes (conf->exchange), - /* type = */ amqp_cstring_bytes (conf->exchange_type), - /* passive = */ 0, - /* durable = */ 0, -#if defined(AMQP_VERSION) && AMQP_VERSION >= 0x00060000 - /* auto delete = */ 0, - /* internal = */ 0, -#endif - /* arguments = */ argument_table); - if ((ed_ret == NULL) && camqp_is_error (conf)) - { - char errbuf[1024]; - ERROR ("amqp plugin: amqp_exchange_declare failed: %s", - camqp_strerror (conf, errbuf, sizeof (errbuf))); - camqp_close_connection (conf); - return (-1); - } - - INFO ("amqp plugin: Successfully created exchange \"%s\" " - "with type \"%s\".", - conf->exchange, conf->exchange_type); + amqp_exchange_declare_ok_t *ed_ret; + amqp_table_t argument_table; + struct amqp_table_entry_t_ argument_table_entries[1]; + if (conf->exchange_type == NULL) return (0); + + /* Valid arguments: "auto_delete", "internal" */ + argument_table.num_entries = STATIC_ARRAY_SIZE(argument_table_entries); + argument_table.entries = argument_table_entries; + argument_table_entries[0].key = amqp_cstring_bytes("auto_delete"); + argument_table_entries[0].value.kind = AMQP_FIELD_KIND_BOOLEAN; + argument_table_entries[0].value.value.boolean = 1; + + ed_ret = amqp_exchange_declare( + conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* exchange = */ amqp_cstring_bytes(conf->exchange), + /* type = */ amqp_cstring_bytes(conf->exchange_type), + /* passive = */ 0, + /* durable = */ 0, +#if defined(AMQP_VERSION) && AMQP_VERSION >= 0x00060000 + /* auto delete = */ 0, + /* internal = */ 0, +#endif + /* arguments = */ argument_table); + if ((ed_ret == NULL) && camqp_is_error(conf)) { + char errbuf[1024]; + ERROR("amqp plugin: amqp_exchange_declare failed: %s", + camqp_strerror(conf, errbuf, sizeof(errbuf))); + camqp_close_connection(conf); + return (-1); + } + + INFO("amqp plugin: Successfully created exchange \"%s\" " + "with type \"%s\".", + conf->exchange, conf->exchange_type); + + return (0); } /* }}} int camqp_create_exchange */ #endif -static int camqp_setup_queue (camqp_config_t *conf) /* {{{ */ +static int camqp_setup_queue(camqp_config_t *conf) /* {{{ */ { - amqp_queue_declare_ok_t *qd_ret; - amqp_basic_consume_ok_t *cm_ret; - - qd_ret = amqp_queue_declare (conf->connection, - /* channel = */ CAMQP_CHANNEL, - /* queue = */ (conf->queue != NULL) - ? amqp_cstring_bytes (conf->queue) - : AMQP_EMPTY_BYTES, - /* passive = */ 0, - /* durable = */ conf->queue_durable, - /* exclusive = */ 0, - /* auto_delete = */ conf->queue_auto_delete, - /* arguments = */ AMQP_EMPTY_TABLE); - if (qd_ret == NULL) - { - ERROR ("amqp plugin: amqp_queue_declare failed."); - camqp_close_connection (conf); - return (-1); + amqp_queue_declare_ok_t *qd_ret; + amqp_basic_consume_ok_t *cm_ret; + + qd_ret = amqp_queue_declare(conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* queue = */ (conf->queue != NULL) + ? amqp_cstring_bytes(conf->queue) + : AMQP_EMPTY_BYTES, + /* passive = */ 0, + /* durable = */ conf->queue_durable, + /* exclusive = */ 0, + /* auto_delete = */ conf->queue_auto_delete, + /* arguments = */ AMQP_EMPTY_TABLE); + if (qd_ret == NULL) { + ERROR("amqp plugin: amqp_queue_declare failed."); + camqp_close_connection(conf); + return (-1); + } + + if (conf->queue == NULL) { + conf->queue = camqp_bytes_cstring(&qd_ret->queue); + if (conf->queue == NULL) { + ERROR("amqp plugin: camqp_bytes_cstring failed."); + camqp_close_connection(conf); + return (-1); } - if (conf->queue == NULL) - { - conf->queue = camqp_bytes_cstring (&qd_ret->queue); - if (conf->queue == NULL) - { - ERROR ("amqp plugin: camqp_bytes_cstring failed."); - camqp_close_connection (conf); - return (-1); - } - - INFO ("amqp plugin: Created queue \"%s\".", conf->queue); - } - DEBUG ("amqp plugin: Successfully created queue \"%s\".", conf->queue); - - /* bind to an exchange */ - if (conf->exchange != NULL) - { - amqp_queue_bind_ok_t *qb_ret; - - assert (conf->queue != NULL); - qb_ret = amqp_queue_bind (conf->connection, - /* channel = */ CAMQP_CHANNEL, - /* queue = */ amqp_cstring_bytes (conf->queue), - /* exchange = */ amqp_cstring_bytes (conf->exchange), - /* routing_key = */ (conf->routing_key != NULL) - ? amqp_cstring_bytes (conf->routing_key) - : AMQP_EMPTY_BYTES, - /* arguments = */ AMQP_EMPTY_TABLE); - if ((qb_ret == NULL) && camqp_is_error (conf)) - { - char errbuf[1024]; - ERROR ("amqp plugin: amqp_queue_bind failed: %s", - camqp_strerror (conf, errbuf, sizeof (errbuf))); - camqp_close_connection (conf); - return (-1); - } - - DEBUG ("amqp plugin: Successfully bound queue \"%s\" to exchange \"%s\".", - conf->queue, conf->exchange); - } /* if (conf->exchange != NULL) */ - - cm_ret = amqp_basic_consume (conf->connection, - /* channel = */ CAMQP_CHANNEL, - /* queue = */ amqp_cstring_bytes (conf->queue), - /* consumer_tag = */ AMQP_EMPTY_BYTES, - /* no_local = */ 0, - /* no_ack = */ 1, - /* exclusive = */ 0, - /* arguments = */ AMQP_EMPTY_TABLE - ); - if ((cm_ret == NULL) && camqp_is_error (conf)) - { - char errbuf[1024]; - ERROR ("amqp plugin: amqp_basic_consume failed: %s", - camqp_strerror (conf, errbuf, sizeof (errbuf))); - camqp_close_connection (conf); - return (-1); + INFO("amqp plugin: Created queue \"%s\".", conf->queue); + } + DEBUG("amqp plugin: Successfully created queue \"%s\".", conf->queue); + + /* bind to an exchange */ + if (conf->exchange != NULL) { + amqp_queue_bind_ok_t *qb_ret; + + assert(conf->queue != NULL); + qb_ret = + amqp_queue_bind(conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* queue = */ amqp_cstring_bytes(conf->queue), + /* exchange = */ amqp_cstring_bytes(conf->exchange), + /* routing_key = */ (conf->routing_key != NULL) + ? amqp_cstring_bytes(conf->routing_key) + : AMQP_EMPTY_BYTES, + /* arguments = */ AMQP_EMPTY_TABLE); + if ((qb_ret == NULL) && camqp_is_error(conf)) { + char errbuf[1024]; + ERROR("amqp plugin: amqp_queue_bind failed: %s", + camqp_strerror(conf, errbuf, sizeof(errbuf))); + camqp_close_connection(conf); + return (-1); } - return (0); + DEBUG("amqp plugin: Successfully bound queue \"%s\" to exchange \"%s\".", + conf->queue, conf->exchange); + } /* if (conf->exchange != NULL) */ + + cm_ret = + amqp_basic_consume(conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* queue = */ amqp_cstring_bytes(conf->queue), + /* consumer_tag = */ AMQP_EMPTY_BYTES, + /* no_local = */ 0, + /* no_ack = */ 1, + /* exclusive = */ 0, + /* arguments = */ AMQP_EMPTY_TABLE); + if ((cm_ret == NULL) && camqp_is_error(conf)) { + char errbuf[1024]; + ERROR("amqp plugin: amqp_basic_consume failed: %s", + camqp_strerror(conf, errbuf, sizeof(errbuf))); + camqp_close_connection(conf); + return (-1); + } + + return (0); } /* }}} int camqp_setup_queue */ -static int camqp_connect (camqp_config_t *conf) /* {{{ */ +static int camqp_connect(camqp_config_t *conf) /* {{{ */ { - static time_t last_connect_time = 0; + static time_t last_connect_time = 0; - amqp_rpc_reply_t reply; - int status; + amqp_rpc_reply_t reply; + int status; #ifdef HAVE_AMQP_TCP_SOCKET - amqp_socket_t *socket; + amqp_socket_t *socket; #else - int sockfd; + int sockfd; #endif - if (conf->connection != NULL) - return (0); + if (conf->connection != NULL) + return (0); - time_t now = time(NULL); - if (now < (last_connect_time + conf->connection_retry_delay)) - { - DEBUG("amqp plugin: skipping connection retry, " - "ConnectionRetryDelay: %d", conf->connection_retry_delay); - return(1); - } - else - { - DEBUG ("amqp plugin: retrying connection"); - last_connect_time = now; - } + time_t now = time(NULL); + if (now < (last_connect_time + conf->connection_retry_delay)) { + DEBUG("amqp plugin: skipping connection retry, " + "ConnectionRetryDelay: %d", + conf->connection_retry_delay); + return (1); + } else { + DEBUG("amqp plugin: retrying connection"); + last_connect_time = now; + } - conf->connection = amqp_new_connection (); - if (conf->connection == NULL) - { - ERROR ("amqp plugin: amqp_new_connection failed."); - return (ENOMEM); - } + conf->connection = amqp_new_connection(); + if (conf->connection == NULL) { + ERROR("amqp plugin: amqp_new_connection failed."); + return (ENOMEM); + } #ifdef HAVE_AMQP_TCP_SOCKET -# define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us */ - /* TODO: add support for SSL using amqp_ssl_socket_new - * and related functions */ - socket = amqp_tcp_socket_new (conf->connection); - if (! socket) - { - ERROR ("amqp plugin: amqp_tcp_socket_new failed."); - amqp_destroy_connection (conf->connection); - conf->connection = NULL; - return (ENOMEM); - } - - status = amqp_socket_open (socket, CONF(conf, host), conf->port); - if (status < 0) - { - char errbuf[1024]; - status *= -1; - ERROR ("amqp plugin: amqp_socket_open failed: %s", - sstrerror (status, errbuf, sizeof (errbuf))); - amqp_destroy_connection (conf->connection); - conf->connection = NULL; - return (status); - } +#define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us \ + */ + /* TODO: add support for SSL using amqp_ssl_socket_new + * and related functions */ + socket = amqp_tcp_socket_new(conf->connection); + if (!socket) { + ERROR("amqp plugin: amqp_tcp_socket_new failed."); + amqp_destroy_connection(conf->connection); + conf->connection = NULL; + return (ENOMEM); + } + + status = amqp_socket_open(socket, CONF(conf, host), conf->port); + if (status < 0) { + char errbuf[1024]; + status *= -1; + ERROR("amqp plugin: amqp_socket_open failed: %s", + sstrerror(status, errbuf, sizeof(errbuf))); + amqp_destroy_connection(conf->connection); + conf->connection = NULL; + return (status); + } #else /* HAVE_AMQP_TCP_SOCKET */ -# define CLOSE_SOCKET() close(sockfd) - /* this interface is deprecated as of rabbitmq-c 0.4 */ - sockfd = amqp_open_socket (CONF(conf, host), conf->port); - if (sockfd < 0) - { - char errbuf[1024]; - status = (-1) * sockfd; - ERROR ("amqp plugin: amqp_open_socket failed: %s", - sstrerror (status, errbuf, sizeof (errbuf))); - amqp_destroy_connection (conf->connection); - conf->connection = NULL; - return (status); - } - amqp_set_sockfd (conf->connection, sockfd); +#define CLOSE_SOCKET() close(sockfd) + /* this interface is deprecated as of rabbitmq-c 0.4 */ + sockfd = amqp_open_socket(CONF(conf, host), conf->port); + if (sockfd < 0) { + char errbuf[1024]; + status = (-1) * sockfd; + ERROR("amqp plugin: amqp_open_socket failed: %s", + sstrerror(status, errbuf, sizeof(errbuf))); + amqp_destroy_connection(conf->connection); + conf->connection = NULL; + return (status); + } + amqp_set_sockfd(conf->connection, sockfd); #endif - reply = amqp_login (conf->connection, CONF(conf, vhost), - /* channel max = */ 0, - /* frame max = */ 131072, - /* heartbeat = */ 0, - /* authentication = */ AMQP_SASL_METHOD_PLAIN, - CONF(conf, user), CONF(conf, password)); - if (reply.reply_type != AMQP_RESPONSE_NORMAL) - { - ERROR ("amqp plugin: amqp_login (vhost = %s, user = %s) failed.", - CONF(conf, vhost), CONF(conf, user)); - amqp_destroy_connection (conf->connection); - CLOSE_SOCKET (); - conf->connection = NULL; - return (1); - } - - amqp_channel_open (conf->connection, /* channel = */ 1); - /* FIXME: Is checking "reply.reply_type" really correct here? How does - * it get set? --octo */ - if (reply.reply_type != AMQP_RESPONSE_NORMAL) - { - ERROR ("amqp plugin: amqp_channel_open failed."); - amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS); - amqp_destroy_connection (conf->connection); - CLOSE_SOCKET (); - conf->connection = NULL; - return (1); - } + reply = amqp_login(conf->connection, CONF(conf, vhost), + /* channel max = */ 0, + /* frame max = */ 131072, + /* heartbeat = */ 0, + /* authentication = */ AMQP_SASL_METHOD_PLAIN, + CONF(conf, user), CONF(conf, password)); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + ERROR("amqp plugin: amqp_login (vhost = %s, user = %s) failed.", + CONF(conf, vhost), CONF(conf, user)); + amqp_destroy_connection(conf->connection); + CLOSE_SOCKET(); + conf->connection = NULL; + return (1); + } + + amqp_channel_open(conf->connection, /* channel = */ 1); + /* FIXME: Is checking "reply.reply_type" really correct here? How does + * it get set? --octo */ + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + ERROR("amqp plugin: amqp_channel_open failed."); + amqp_connection_close(conf->connection, AMQP_REPLY_SUCCESS); + amqp_destroy_connection(conf->connection); + CLOSE_SOCKET(); + conf->connection = NULL; + return (1); + } - INFO ("amqp plugin: Successfully opened connection to vhost \"%s\" " - "on %s:%i.", CONF(conf, vhost), CONF(conf, host), conf->port); + INFO("amqp plugin: Successfully opened connection to vhost \"%s\" " + "on %s:%i.", + CONF(conf, vhost), CONF(conf, host), conf->port); - status = camqp_create_exchange (conf); - if (status != 0) - return (status); + status = camqp_create_exchange(conf); + if (status != 0) + return (status); - if (!conf->publish) - return (camqp_setup_queue (conf)); - return (0); + if (!conf->publish) + return (camqp_setup_queue(conf)); + return (0); } /* }}} int camqp_connect */ -static int camqp_shutdown (void) /* {{{ */ +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++) - { - /* 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 - * intervals. */ - pthread_kill (subscriber_threads[i], SIGTERM); - pthread_join (subscriber_threads[i], /* retval = */ NULL); - } + DEBUG("amqp plugin: Shutting down %zu subscriber threads.", + subscriber_threads_num); - subscriber_threads_num = 0; - sfree (subscriber_threads); + subscriber_threads_running = 0; + 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 + * intervals. */ + pthread_kill(subscriber_threads[i], SIGTERM); + pthread_join(subscriber_threads[i], /* retval = */ NULL); + } - DEBUG ("amqp plugin: All subscriber threads exited."); + subscriber_threads_num = 0; + sfree(subscriber_threads); - return (0); + DEBUG("amqp plugin: All subscriber threads exited."); + + return (0); } /* }}} int camqp_shutdown */ /* * Subscribing code */ -static int camqp_read_body (camqp_config_t *conf, /* {{{ */ - size_t body_size, const char *content_type) -{ - char body[body_size + 1]; - char *body_ptr; - size_t received; - amqp_frame_t frame; - int status; - - memset (body, 0, sizeof (body)); - body_ptr = &body[0]; - received = 0; - - while (received < body_size) - { - status = amqp_simple_wait_frame (conf->connection, &frame); - if (status < 0) - { - char errbuf[1024]; - status = (-1) * status; - ERROR ("amqp plugin: amqp_simple_wait_frame failed: %s", - sstrerror (status, errbuf, sizeof (errbuf))); - camqp_close_connection (conf); - return (status); - } - - if (frame.frame_type != AMQP_FRAME_BODY) - { - NOTICE ("amqp plugin: Unexpected frame type: %#"PRIx8, - frame.frame_type); - return (-1); - } - - if ((body_size - received) < frame.payload.body_fragment.len) - { - WARNING ("amqp plugin: Body is larger than indicated by header."); - return (-1); - } - - memcpy (body_ptr, frame.payload.body_fragment.bytes, - frame.payload.body_fragment.len); - body_ptr += frame.payload.body_fragment.len; - received += frame.payload.body_fragment.len; - } /* while (received < body_size) */ - - if (strcasecmp ("text/collectd", content_type) == 0) - { - status = handle_putval (stderr, body); - if (status != 0) - ERROR ("amqp plugin: handle_putval failed with status %i.", - status); - return (status); +static int camqp_read_body(camqp_config_t *conf, /* {{{ */ + size_t body_size, const char *content_type) { + char body[body_size + 1]; + char *body_ptr; + size_t received; + amqp_frame_t frame; + int status; + + memset(body, 0, sizeof(body)); + body_ptr = &body[0]; + received = 0; + + while (received < body_size) { + status = amqp_simple_wait_frame(conf->connection, &frame); + if (status < 0) { + char errbuf[1024]; + status = (-1) * status; + ERROR("amqp plugin: amqp_simple_wait_frame failed: %s", + sstrerror(status, errbuf, sizeof(errbuf))); + camqp_close_connection(conf); + return (status); } - else if (strcasecmp ("application/json", content_type) == 0) - { - ERROR ("amqp plugin: camqp_read_body: Parsing JSON data has not " - "been implemented yet. FIXME!"); - return (0); + + if (frame.frame_type != AMQP_FRAME_BODY) { + NOTICE("amqp plugin: Unexpected frame type: %#" PRIx8, frame.frame_type); + return (-1); } - else - { - ERROR ("amqp plugin: camqp_read_body: Unknown content type \"%s\".", - content_type); - return (EINVAL); + + if ((body_size - received) < frame.payload.body_fragment.len) { + WARNING("amqp plugin: Body is larger than indicated by header."); + return (-1); } - /* not reached */ + memcpy(body_ptr, frame.payload.body_fragment.bytes, + frame.payload.body_fragment.len); + body_ptr += frame.payload.body_fragment.len; + received += frame.payload.body_fragment.len; + } /* while (received < body_size) */ + + if (strcasecmp("text/collectd", content_type) == 0) { + status = handle_putval(stderr, body); + if (status != 0) + ERROR("amqp plugin: handle_putval failed with status %i.", status); + return (status); + } else if (strcasecmp("application/json", content_type) == 0) { + ERROR("amqp plugin: camqp_read_body: Parsing JSON data has not " + "been implemented yet. FIXME!"); return (0); + } else { + ERROR("amqp plugin: camqp_read_body: Unknown content type \"%s\".", + content_type); + return (EINVAL); + } + + /* not reached */ + return (0); } /* }}} int camqp_read_body */ -static int camqp_read_header (camqp_config_t *conf) /* {{{ */ +static int camqp_read_header(camqp_config_t *conf) /* {{{ */ { - int status; + int status; + amqp_frame_t frame; + amqp_basic_properties_t *properties; + char *content_type; + + status = amqp_simple_wait_frame(conf->connection, &frame); + if (status < 0) { + char errbuf[1024]; + status = (-1) * status; + ERROR("amqp plugin: amqp_simple_wait_frame failed: %s", + sstrerror(status, errbuf, sizeof(errbuf))); + camqp_close_connection(conf); + return (status); + } + + if (frame.frame_type != AMQP_FRAME_HEADER) { + NOTICE("amqp plugin: Unexpected frame type: %#" PRIx8, frame.frame_type); + return (-1); + } + + properties = frame.payload.properties.decoded; + content_type = camqp_bytes_cstring(&properties->content_type); + if (content_type == NULL) { + ERROR("amqp plugin: Unable to determine content type."); + return (-1); + } + + status = camqp_read_body(conf, (size_t)frame.payload.properties.body_size, + content_type); + + sfree(content_type); + return (status); +} /* }}} int camqp_read_header */ + +static void *camqp_subscribe_thread(void *user_data) /* {{{ */ +{ + camqp_config_t *conf = user_data; + int status; + + cdtime_t interval = plugin_get_interval(); + + while (subscriber_threads_running) { amqp_frame_t frame; - amqp_basic_properties_t *properties; - char *content_type; - - status = amqp_simple_wait_frame (conf->connection, &frame); - if (status < 0) - { - char errbuf[1024]; - status = (-1) * status; - ERROR ("amqp plugin: amqp_simple_wait_frame failed: %s", - sstrerror (status, errbuf, sizeof (errbuf))); - camqp_close_connection (conf); - return (status); + + status = camqp_connect(conf); + if (status != 0) { + struct timespec ts_interval; + ERROR("amqp plugin: camqp_connect failed. " + "Will sleep for %.3f seconds.", + CDTIME_T_TO_DOUBLE(interval)); + CDTIME_T_TO_TIMESPEC(interval, &ts_interval); + nanosleep(&ts_interval, /* remaining = */ NULL); + continue; } - if (frame.frame_type != AMQP_FRAME_HEADER) - { - NOTICE ("amqp plugin: Unexpected frame type: %#"PRIx8, - frame.frame_type); - return (-1); + status = amqp_simple_wait_frame(conf->connection, &frame); + if (status < 0) { + struct timespec ts_interval; + ERROR("amqp plugin: amqp_simple_wait_frame failed. " + "Will sleep for %.3f seconds.", + CDTIME_T_TO_DOUBLE(interval)); + camqp_close_connection(conf); + CDTIME_T_TO_TIMESPEC(interval, &ts_interval); + nanosleep(&ts_interval, /* remaining = */ NULL); + continue; } - properties = frame.payload.properties.decoded; - content_type = camqp_bytes_cstring (&properties->content_type); - if (content_type == NULL) - { - ERROR ("amqp plugin: Unable to determine content type."); - return (-1); + if (frame.frame_type != AMQP_FRAME_METHOD) { + DEBUG("amqp plugin: Unexpected frame type: %#" PRIx8, frame.frame_type); + continue; } - status = camqp_read_body (conf, - (size_t) frame.payload.properties.body_size, - content_type); + if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD) { + DEBUG("amqp plugin: Unexpected method id: %#" PRIx32, + frame.payload.method.id); + continue; + } - sfree (content_type); - return (status); -} /* }}} int camqp_read_header */ + camqp_read_header(conf); -static void *camqp_subscribe_thread (void *user_data) /* {{{ */ -{ - camqp_config_t *conf = user_data; - int status; - - cdtime_t interval = plugin_get_interval (); - - while (subscriber_threads_running) - { - amqp_frame_t frame; - - status = camqp_connect (conf); - if (status != 0) - { - struct timespec ts_interval; - ERROR ("amqp plugin: camqp_connect failed. " - "Will sleep for %.3f seconds.", - CDTIME_T_TO_DOUBLE (interval)); - CDTIME_T_TO_TIMESPEC (interval, &ts_interval); - nanosleep (&ts_interval, /* remaining = */ NULL); - continue; - } - - status = amqp_simple_wait_frame (conf->connection, &frame); - if (status < 0) - { - struct timespec ts_interval; - ERROR ("amqp plugin: amqp_simple_wait_frame failed. " - "Will sleep for %.3f seconds.", - CDTIME_T_TO_DOUBLE (interval)); - camqp_close_connection (conf); - CDTIME_T_TO_TIMESPEC (interval, &ts_interval); - nanosleep (&ts_interval, /* remaining = */ NULL); - continue; - } - - if (frame.frame_type != AMQP_FRAME_METHOD) - { - DEBUG ("amqp plugin: Unexpected frame type: %#"PRIx8, - frame.frame_type); - continue; - } - - if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD) - { - DEBUG ("amqp plugin: Unexpected method id: %#"PRIx32, - frame.payload.method.id); - continue; - } - - camqp_read_header (conf); - - amqp_maybe_release_buffers (conf->connection); - } /* while (subscriber_threads_running) */ - - camqp_config_free (conf); - pthread_exit (NULL); - return (NULL); + amqp_maybe_release_buffers(conf->connection); + } /* while (subscriber_threads_running) */ + + camqp_config_free(conf); + pthread_exit(NULL); + return (NULL); } /* }}} void *camqp_subscribe_thread */ -static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */ +static int camqp_subscribe_init(camqp_config_t *conf) /* {{{ */ { - int status; - pthread_t *tmp; - - tmp = realloc (subscriber_threads, - sizeof (*subscriber_threads) * (subscriber_threads_num + 1)); - if (tmp == NULL) - { - ERROR ("amqp plugin: realloc failed."); - camqp_config_free (conf); - return (ENOMEM); - } - subscriber_threads = tmp; - tmp = subscriber_threads + subscriber_threads_num; - memset (tmp, 0, sizeof (*tmp)); - - status = plugin_thread_create (tmp, /* attr = */ NULL, - camqp_subscribe_thread, conf); - if (status != 0) - { - char errbuf[1024]; - ERROR ("amqp plugin: pthread_create failed: %s", - sstrerror (status, errbuf, sizeof (errbuf))); - camqp_config_free (conf); - return (status); - } + int status; + pthread_t *tmp; + + tmp = realloc(subscriber_threads, + sizeof(*subscriber_threads) * (subscriber_threads_num + 1)); + if (tmp == NULL) { + ERROR("amqp plugin: realloc failed."); + sfree(subscriber_threads); + return (ENOMEM); + } + subscriber_threads = tmp; + tmp = subscriber_threads + subscriber_threads_num; + memset(tmp, 0, sizeof(*tmp)); + + status = plugin_thread_create(tmp, /* attr = */ NULL, camqp_subscribe_thread, + conf); + if (status != 0) { + char errbuf[1024]; + ERROR("amqp plugin: pthread_create failed: %s", + sstrerror(status, errbuf, sizeof(errbuf))); + return (status); + } - subscriber_threads_num++; + subscriber_threads_num++; - return (0); + return (0); } /* }}} int camqp_subscribe_init */ /* * Publishing code */ /* XXX: You must hold "conf->lock" when calling this function! */ -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; - 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("application/json"); - else if (conf->format == CAMQP_FORMAT_GRAPHITE) - 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, - amqp_cstring_bytes(CONF(conf, exchange)), - amqp_cstring_bytes (routing_key), - /* mandatory = */ 0, - /* immediate = */ 0, - &props, - amqp_cstring_bytes(buffer)); - if (status != 0) - { - ERROR ("amqp plugin: amqp_basic_publish failed with status %i.", - status); - camqp_close_connection (conf); - } +static int camqp_write_locked(camqp_config_t *conf, /* {{{ */ + const char *buffer, const char *routing_key) { + int status; + status = camqp_connect(conf); + if (status != 0) return (status); -} /* }}} int camqp_write_locked */ - -static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ - user_data_t *user_data) -{ - camqp_config_t *conf = user_data->data; - char routing_key[6 * DATA_MAX_NAME_LEN]; - char buffer[8192]; - int status; - - if ((ds == NULL) || (vl == NULL) || (conf == NULL)) - return (EINVAL); - memset (buffer, 0, sizeof (buffer)); + 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("application/json"); + else if (conf->format == CAMQP_FORMAT_GRAPHITE) + props.content_type = amqp_cstring_bytes("text/graphite"); + else + assert(23 == 42); + + status = amqp_basic_publish( + conf->connection, + /* channel = */ 1, amqp_cstring_bytes(CONF(conf, exchange)), + amqp_cstring_bytes(routing_key), + /* mandatory = */ 0, + /* immediate = */ 0, &props, amqp_cstring_bytes(buffer)); + if (status != 0) { + ERROR("amqp plugin: amqp_basic_publish failed with status %i.", status); + camqp_close_connection(conf); + } + + return (status); +} /* }}} int camqp_write_locked */ - 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, - vl->type, vl->type_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++) - { - if (routing_key[i] == '.') - routing_key[i] = '/'; - else if (routing_key[i] == '/') - routing_key[i] = '.'; - } +static int camqp_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ + user_data_t *user_data) { + camqp_config_t *conf = user_data->data; + char routing_key[6 * DATA_MAX_NAME_LEN]; + char buffer[8192]; + int status; + + if ((ds == NULL) || (vl == NULL) || (conf == NULL)) + return (EINVAL); + + if (conf->routing_key != NULL) { + sstrncpy(routing_key, conf->routing_key, sizeof(routing_key)); + } else { + ssnprintf(routing_key, sizeof(routing_key), "collectd/%s/%s/%s/%s/%s", + vl->host, vl->plugin, vl->plugin_instance, vl->type, + vl->type_instance); + + /* Switch slashes (the only character forbidden by collectd) and dots + * (the separation character used by AMQP). */ + for (size_t i = 0; routing_key[i] != 0; i++) { + if (routing_key[i] == '.') + routing_key[i] = '/'; + else if (routing_key[i] == '/') + routing_key[i] = '.'; } + } - if (conf->format == CAMQP_FORMAT_COMMAND) - { - status = create_putval (buffer, sizeof (buffer), ds, vl); - if (status != 0) - { - ERROR ("amqp plugin: create_putval failed with status %i.", - status); - return (status); - } + if (conf->format == CAMQP_FORMAT_COMMAND) { + status = create_putval(buffer, sizeof(buffer), ds, vl); + if (status != 0) { + ERROR("amqp plugin: create_putval failed with status %i.", status); + return (status); } - else if (conf->format == CAMQP_FORMAT_JSON) - { - size_t bfree = sizeof (buffer); - size_t bfill = 0; - - format_json_initialize (buffer, &bfill, &bfree); - format_json_value_list (buffer, &bfill, &bfree, ds, vl, conf->store_rates); - format_json_finalize (buffer, &bfill, &bfree); - } - else if (conf->format == CAMQP_FORMAT_GRAPHITE) - { - status = format_graphite (buffer, sizeof (buffer), ds, vl, - conf->prefix, conf->postfix, conf->escape_char, - conf->graphite_flags); - if (status != 0) - { - ERROR ("amqp plugin: format_graphite failed with status %i.", - status); - return (status); - } - } - else - { - ERROR ("amqp plugin: Invalid format (%i).", conf->format); - return (-1); + } else if (conf->format == CAMQP_FORMAT_JSON) { + size_t bfree = sizeof(buffer); + size_t bfill = 0; + + format_json_initialize(buffer, &bfill, &bfree); + format_json_value_list(buffer, &bfill, &bfree, ds, vl, conf->store_rates); + format_json_finalize(buffer, &bfill, &bfree); + } else if (conf->format == CAMQP_FORMAT_GRAPHITE) { + status = + format_graphite(buffer, sizeof(buffer), ds, vl, conf->prefix, + conf->postfix, conf->escape_char, conf->graphite_flags); + if (status != 0) { + ERROR("amqp plugin: format_graphite failed with status %i.", status); + return (status); } + } else { + ERROR("amqp plugin: Invalid format (%i).", conf->format); + return (-1); + } - pthread_mutex_lock (&conf->lock); - status = camqp_write_locked (conf, buffer, routing_key); - pthread_mutex_unlock (&conf->lock); + pthread_mutex_lock(&conf->lock); + status = camqp_write_locked(conf, buffer, routing_key); + pthread_mutex_unlock(&conf->lock); - return (status); + return (status); } /* }}} int camqp_write */ /* * Config handling */ -static int camqp_config_set_format (oconfig_item_t *ci, /* {{{ */ - camqp_config_t *conf) -{ - char *string; - int status; +static int camqp_config_set_format(oconfig_item_t *ci, /* {{{ */ + camqp_config_t *conf) { + char *string; + int status; + + string = NULL; + status = cf_util_get_string(ci, &string); + if (status != 0) + return (status); - string = NULL; - status = cf_util_get_string (ci, &string); - if (status != 0) - return (status); - - assert (string != NULL); - if (strcasecmp ("Command", string) == 0) - conf->format = CAMQP_FORMAT_COMMAND; - else if (strcasecmp ("JSON", string) == 0) - conf->format = CAMQP_FORMAT_JSON; - else if (strcasecmp ("Graphite", string) == 0) - conf->format = CAMQP_FORMAT_GRAPHITE; - else - { - WARNING ("amqp plugin: Invalid format string: %s", - string); - } + assert(string != NULL); + if (strcasecmp("Command", string) == 0) + conf->format = CAMQP_FORMAT_COMMAND; + else if (strcasecmp("JSON", string) == 0) + conf->format = CAMQP_FORMAT_JSON; + else if (strcasecmp("Graphite", string) == 0) + conf->format = CAMQP_FORMAT_GRAPHITE; + else { + WARNING("amqp plugin: Invalid format string: %s", string); + } - free (string); + free(string); - return (0); + return (0); } /* }}} int config_set_string */ -static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */ - _Bool publish) -{ - camqp_config_t *conf; - int status; - int i; - - conf = malloc (sizeof (*conf)); - if (conf == NULL) - { - ERROR ("amqp plugin: malloc failed."); - return (ENOMEM); - } - - /* Initialize "conf" {{{ */ - memset (conf, 0, sizeof (*conf)); - conf->publish = publish; - conf->name = NULL; - conf->format = CAMQP_FORMAT_COMMAND; - conf->host = NULL; - conf->port = 5672; - conf->vhost = NULL; - conf->user = NULL; - conf->password = NULL; - conf->exchange = NULL; - conf->routing_key = NULL; - conf->connection_retry_delay = 0; - - /* publish only */ - conf->delivery_mode = CAMQP_DM_VOLATILE; - conf->store_rates = 0; - conf->graphite_flags = 0; - /* publish & graphite only */ - conf->prefix = NULL; - conf->postfix = NULL; - conf->escape_char = '_'; - /* subscribe only */ - conf->exchange_type = NULL; - conf->queue = NULL; - conf->queue_durable = 0; - conf->queue_auto_delete = 1; - /* general */ - conf->connection = NULL; - pthread_mutex_init (&conf->lock, /* attr = */ NULL); - /* }}} */ +static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */ + _Bool publish) { + camqp_config_t *conf; + int status; + + conf = calloc(1, sizeof(*conf)); + if (conf == NULL) { + ERROR("amqp plugin: calloc failed."); + return (ENOMEM); + } + + /* Initialize "conf" {{{ */ + conf->publish = publish; + conf->name = NULL; + conf->format = CAMQP_FORMAT_COMMAND; + conf->host = NULL; + conf->port = 5672; + conf->vhost = NULL; + conf->user = NULL; + conf->password = NULL; + conf->exchange = NULL; + conf->routing_key = NULL; + conf->connection_retry_delay = 0; + + /* publish only */ + conf->delivery_mode = CAMQP_DM_VOLATILE; + conf->store_rates = 0; + conf->graphite_flags = 0; + /* publish & graphite only */ + conf->prefix = NULL; + conf->postfix = NULL; + conf->escape_char = '_'; + /* subscribe only */ + conf->exchange_type = NULL; + conf->queue = NULL; + conf->queue_durable = 0; + conf->queue_auto_delete = 1; + /* general */ + conf->connection = NULL; + pthread_mutex_init(&conf->lock, /* attr = */ NULL); + /* }}} */ + + status = cf_util_get_string(ci, &conf->name); + if (status != 0) { + sfree(conf); + return (status); + } + + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("Host", child->key) == 0) + status = cf_util_get_string(child, &conf->host); + else if (strcasecmp("Port", child->key) == 0) { + status = cf_util_get_port_number(child); + if (status > 0) { + conf->port = status; + status = 0; + } + } else if (strcasecmp("VHost", child->key) == 0) + status = cf_util_get_string(child, &conf->vhost); + else if (strcasecmp("User", child->key) == 0) + status = cf_util_get_string(child, &conf->user); + else if (strcasecmp("Password", child->key) == 0) + status = cf_util_get_string(child, &conf->password); + else if (strcasecmp("Exchange", child->key) == 0) + status = cf_util_get_string(child, &conf->exchange); + else if ((strcasecmp("ExchangeType", child->key) == 0) && !publish) + status = cf_util_get_string(child, &conf->exchange_type); + else if ((strcasecmp("Queue", child->key) == 0) && !publish) + status = cf_util_get_string(child, &conf->queue); + else if ((strcasecmp("QueueDurable", child->key) == 0) && !publish) + status = cf_util_get_boolean(child, &conf->queue_durable); + else if ((strcasecmp("QueueAutoDelete", child->key) == 0) && !publish) + status = cf_util_get_boolean(child, &conf->queue_auto_delete); + else if (strcasecmp("RoutingKey", child->key) == 0) + status = cf_util_get_string(child, &conf->routing_key); + else if ((strcasecmp("Persistent", child->key) == 0) && publish) { + _Bool tmp = 0; + status = cf_util_get_boolean(child, &tmp); + if (tmp) + conf->delivery_mode = CAMQP_DM_PERSISTENT; + else + conf->delivery_mode = CAMQP_DM_VOLATILE; + } else if ((strcasecmp("StoreRates", child->key) == 0) && publish) { + status = cf_util_get_boolean(child, &conf->store_rates); + (void)cf_util_get_flag(child, &conf->graphite_flags, + GRAPHITE_STORE_RATES); + } else if ((strcasecmp("Format", child->key) == 0) && publish) + status = camqp_config_set_format(child, conf); + else if ((strcasecmp("GraphiteSeparateInstances", child->key) == 0) && + publish) + status = cf_util_get_flag(child, &conf->graphite_flags, + GRAPHITE_SEPARATE_INSTANCES); + else if ((strcasecmp("GraphiteAlwaysAppendDS", child->key) == 0) && publish) + status = cf_util_get_flag(child, &conf->graphite_flags, + GRAPHITE_ALWAYS_APPEND_DS); + else if ((strcasecmp("GraphitePrefix", child->key) == 0) && publish) + status = cf_util_get_string(child, &conf->prefix); + else if ((strcasecmp("GraphitePostfix", child->key) == 0) && publish) + status = cf_util_get_string(child, &conf->postfix); + else if ((strcasecmp("GraphiteEscapeChar", child->key) == 0) && publish) { + char *tmp_buff = NULL; + status = cf_util_get_string(child, &tmp_buff); + if (strlen(tmp_buff) > 1) + WARNING("amqp plugin: The option \"GraphiteEscapeChar\" handles " + "only one character. Others will be ignored."); + conf->escape_char = tmp_buff[0]; + sfree(tmp_buff); + } else if (strcasecmp("ConnectionRetryDelay", child->key) == 0) + status = cf_util_get_int(child, &conf->connection_retry_delay); + else + WARNING("amqp plugin: Ignoring unknown " + "configuration option \"%s\".", + child->key); - status = cf_util_get_string (ci, &conf->name); if (status != 0) - { - sfree (conf); - return (status); - } + break; + } /* for (i = 0; i < ci->children_num; i++) */ - for (i = 0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; - - if (strcasecmp ("Host", child->key) == 0) - status = cf_util_get_string (child, &conf->host); - else if (strcasecmp ("Port", child->key) == 0) - { - status = cf_util_get_port_number (child); - if (status > 0) - { - conf->port = status; - status = 0; - } - } - else if (strcasecmp ("VHost", child->key) == 0) - status = cf_util_get_string (child, &conf->vhost); - else if (strcasecmp ("User", child->key) == 0) - status = cf_util_get_string (child, &conf->user); - else if (strcasecmp ("Password", child->key) == 0) - status = cf_util_get_string (child, &conf->password); - else if (strcasecmp ("Exchange", child->key) == 0) - status = cf_util_get_string (child, &conf->exchange); - else if ((strcasecmp ("ExchangeType", child->key) == 0) && !publish) - status = cf_util_get_string (child, &conf->exchange_type); - else if ((strcasecmp ("Queue", child->key) == 0) && !publish) - status = cf_util_get_string (child, &conf->queue); - else if ((strcasecmp ("QueueDurable", child->key) == 0) && !publish) - status = cf_util_get_boolean (child, &conf->queue_durable); - else if ((strcasecmp ("QueueAutoDelete", child->key) == 0) && !publish) - status = cf_util_get_boolean (child, &conf->queue_auto_delete); - else if (strcasecmp ("RoutingKey", child->key) == 0) - status = cf_util_get_string (child, &conf->routing_key); - else if ((strcasecmp ("Persistent", child->key) == 0) && publish) - { - _Bool tmp = 0; - status = cf_util_get_boolean (child, &tmp); - if (tmp) - conf->delivery_mode = CAMQP_DM_PERSISTENT; - else - conf->delivery_mode = CAMQP_DM_VOLATILE; - } - else if ((strcasecmp ("StoreRates", child->key) == 0) && publish) - { - status = cf_util_get_boolean (child, &conf->store_rates); - (void) cf_util_get_flag (child, &conf->graphite_flags, - GRAPHITE_STORE_RATES); - } - else if ((strcasecmp ("Format", child->key) == 0) && publish) - status = camqp_config_set_format (child, conf); - else if ((strcasecmp ("GraphiteSeparateInstances", child->key) == 0) && publish) - status = cf_util_get_flag (child, &conf->graphite_flags, - GRAPHITE_SEPARATE_INSTANCES); - else if ((strcasecmp ("GraphiteAlwaysAppendDS", child->key) == 0) && publish) - status = cf_util_get_flag (child, &conf->graphite_flags, - GRAPHITE_ALWAYS_APPEND_DS); - else if ((strcasecmp ("GraphitePrefix", child->key) == 0) && publish) - status = cf_util_get_string (child, &conf->prefix); - else if ((strcasecmp ("GraphitePostfix", child->key) == 0) && publish) - status = cf_util_get_string (child, &conf->postfix); - else if ((strcasecmp ("GraphiteEscapeChar", child->key) == 0) && publish) - { - char *tmp_buff = NULL; - status = cf_util_get_string (child, &tmp_buff); - if (strlen (tmp_buff) > 1) - WARNING ("amqp plugin: The option \"GraphiteEscapeChar\" handles " - "only one character. Others will be ignored."); - conf->escape_char = tmp_buff[0]; - sfree (tmp_buff); - } - else if (strcasecmp ("ConnectionRetryDelay", child->key) == 0) - status = cf_util_get_int (child, &conf->connection_retry_delay); - else - WARNING ("amqp plugin: Ignoring unknown " - "configuration option \"%s\".", child->key); - - if (status != 0) - break; - } /* for (i = 0; i < ci->children_num; i++) */ - - if ((status == 0) && (conf->exchange == NULL)) - { - if (conf->exchange_type != NULL) - WARNING ("amqp plugin: The option \"ExchangeType\" was given " - "without the \"Exchange\" option. It will be ignored."); - - if (!publish && (conf->routing_key != NULL)) - WARNING ("amqp plugin: The option \"RoutingKey\" was given " - "without the \"Exchange\" option. It will be ignored."); + if ((status == 0) && (conf->exchange == NULL)) { + if (conf->exchange_type != NULL) + WARNING("amqp plugin: The option \"ExchangeType\" was given " + "without the \"Exchange\" option. It will be ignored."); - } + if (!publish && (conf->routing_key != NULL)) + WARNING("amqp plugin: The option \"RoutingKey\" was given " + "without the \"Exchange\" option. It will be ignored."); + } - if (status != 0) - { - camqp_config_free (conf); - return (status); - } + if (status != 0) { + camqp_config_free(conf); + return (status); + } - if (conf->exchange != NULL) - { - DEBUG ("amqp plugin: camqp_config_connection: exchange = %s;", - conf->exchange); - } + if (conf->exchange != NULL) { + DEBUG("amqp plugin: camqp_config_connection: exchange = %s;", + conf->exchange); + } - if (publish) - { - char cbname[128]; - user_data_t ud = { conf, camqp_config_free }; + if (publish) { + char cbname[128]; + user_data_t ud = {conf, camqp_config_free}; - ssnprintf (cbname, sizeof (cbname), "amqp/%s", conf->name); + ssnprintf(cbname, sizeof(cbname), "amqp/%s", conf->name); - status = plugin_register_write (cbname, camqp_write, &ud); - if (status != 0) - { - camqp_config_free (conf); - return (status); - } + status = plugin_register_write(cbname, camqp_write, &ud); + if (status != 0) { + camqp_config_free(conf); + return (status); } - else - { - status = camqp_subscribe_init (conf); - if (status != 0) - { - camqp_config_free (conf); - return (status); - } + } else { + status = camqp_subscribe_init(conf); + if (status != 0) { + camqp_config_free(conf); + return (status); } + } - return (0); + return (0); } /* }}} int camqp_config_connection */ -static int camqp_config (oconfig_item_t *ci) /* {{{ */ +static int camqp_config(oconfig_item_t *ci) /* {{{ */ { - int i; + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; - for (i = 0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; - - if (strcasecmp ("Publish", child->key) == 0) - camqp_config_connection (child, /* publish = */ 1); - else if (strcasecmp ("Subscribe", child->key) == 0) - camqp_config_connection (child, /* publish = */ 0); - else - WARNING ("amqp plugin: Ignoring unknown config option \"%s\".", - child->key); - } /* for (ci->children_num) */ + if (strcasecmp("Publish", child->key) == 0) + camqp_config_connection(child, /* publish = */ 1); + else if (strcasecmp("Subscribe", child->key) == 0) + camqp_config_connection(child, /* publish = */ 0); + else + WARNING("amqp plugin: Ignoring unknown config option \"%s\".", + child->key); + } /* for (ci->children_num) */ - return (0); + return (0); } /* }}} int camqp_config */ -void module_register (void) -{ - plugin_register_complex_config ("amqp", camqp_config); - plugin_register_shutdown ("amqp", camqp_shutdown); +void module_register(void) { + plugin_register_complex_config("amqp", camqp_config); + plugin_register_shutdown("amqp", camqp_shutdown); } /* void module_register */ /* vim: set sw=4 sts=4 et fdm=marker : */ diff --git a/src/apache.c b/src/apache.c index 5b6914c4..35e02ab5 100644 --- a/src/apache.c +++ b/src/apache.c @@ -25,140 +25,128 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" -#include "configfile.h" #include -enum server_enum -{ - APACHE = 0, - LIGHTTPD -}; - -struct apache_s -{ - int server_type; - char *name; - char *host; - char *url; - char *user; - char *pass; - _Bool verify_peer; - _Bool verify_host; - char *cacert; - char *ssl_ciphers; - char *server; /* user specific server type */ - char *apache_buffer; - char apache_curl_error[CURL_ERROR_SIZE]; - size_t apache_buffer_size; - size_t apache_buffer_fill; - int timeout; - CURL *curl; +enum server_enum { APACHE = 0, LIGHTTPD }; + +struct apache_s { + int server_type; + char *name; + char *host; + char *url; + char *user; + char *pass; + _Bool verify_peer; + _Bool verify_host; + char *cacert; + char *ssl_ciphers; + char *server; /* user specific server type */ + char *apache_buffer; + char apache_curl_error[CURL_ERROR_SIZE]; + size_t apache_buffer_size; + size_t apache_buffer_fill; + int timeout; + CURL *curl; }; /* apache_s */ typedef struct apache_s apache_t; /* TODO: Remove this prototype */ -static int apache_read_host (user_data_t *user_data); - -static void apache_free (apache_t *st) -{ - if (st == NULL) - return; - - sfree (st->name); - sfree (st->host); - sfree (st->url); - sfree (st->user); - sfree (st->pass); - sfree (st->cacert); - sfree (st->ssl_ciphers); - sfree (st->server); - sfree (st->apache_buffer); - if (st->curl) { - curl_easy_cleanup(st->curl); - st->curl = NULL; - } - sfree (st); +static int apache_read_host(user_data_t *user_data); + +static void apache_free(void *arg) { + apache_t *st = arg; + + if (st == NULL) + return; + + sfree(st->name); + sfree(st->host); + sfree(st->url); + sfree(st->user); + sfree(st->pass); + sfree(st->cacert); + sfree(st->ssl_ciphers); + sfree(st->server); + sfree(st->apache_buffer); + if (st->curl) { + curl_easy_cleanup(st->curl); + st->curl = NULL; + } + sfree(st); } /* apache_free */ -static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, - void *user_data) -{ - size_t len = size * nmemb; - apache_t *st; - - st = user_data; - if (st == NULL) - { - ERROR ("apache plugin: apache_curl_callback: " - "user_data pointer is NULL."); - return (0); - } - - if (len <= 0) - return (len); - - if ((st->apache_buffer_fill + len) >= st->apache_buffer_size) - { - char *temp; - - temp = (char *) realloc (st->apache_buffer, - st->apache_buffer_fill + len + 1); - if (temp == NULL) - { - ERROR ("apache plugin: realloc failed."); - return (0); - } - st->apache_buffer = temp; - st->apache_buffer_size = st->apache_buffer_fill + len + 1; - } - - memcpy (st->apache_buffer + st->apache_buffer_fill, (char *) buf, len); - st->apache_buffer_fill += len; - st->apache_buffer[st->apache_buffer_fill] = 0; - - return (len); +static size_t apache_curl_callback(void *buf, size_t size, size_t nmemb, + void *user_data) { + size_t len = size * nmemb; + apache_t *st; + + st = user_data; + if (st == NULL) { + ERROR("apache plugin: apache_curl_callback: " + "user_data pointer is NULL."); + return (0); + } + + if (len == 0) + return (len); + + if ((st->apache_buffer_fill + len) >= st->apache_buffer_size) { + char *temp; + + temp = realloc(st->apache_buffer, st->apache_buffer_fill + len + 1); + if (temp == NULL) { + ERROR("apache plugin: realloc failed."); + return (0); + } + st->apache_buffer = temp; + st->apache_buffer_size = st->apache_buffer_fill + len + 1; + } + + memcpy(st->apache_buffer + st->apache_buffer_fill, (char *)buf, len); + st->apache_buffer_fill += len; + st->apache_buffer[st->apache_buffer_fill] = 0; + + return (len); } /* int apache_curl_callback */ -static size_t apache_header_callback (void *buf, size_t size, size_t nmemb, - void *user_data) -{ - size_t len = size * nmemb; - apache_t *st; - - st = user_data; - if (st == NULL) - { - ERROR ("apache plugin: apache_header_callback: " - "user_data pointer is NULL."); - return (0); - } - - if (len <= 0) - return (len); - - /* look for the Server header */ - if (strncasecmp (buf, "Server: ", strlen ("Server: ")) != 0) - return (len); - - if (strstr (buf, "Apache") != NULL) - st->server_type = APACHE; - else if (strstr (buf, "lighttpd") != NULL) - st->server_type = LIGHTTPD; - else if (strstr (buf, "IBM_HTTP_Server") != NULL) - st->server_type = APACHE; - else - { - const char *hdr = buf; - - hdr += strlen ("Server: "); - NOTICE ("apache plugin: Unknown server software: %s", hdr); - } - - return (len); +static size_t apache_header_callback(void *buf, size_t size, size_t nmemb, + void *user_data) { + size_t len = size * nmemb; + apache_t *st; + + st = user_data; + if (st == NULL) { + ERROR("apache plugin: apache_header_callback: " + "user_data pointer is NULL."); + return (0); + } + + if (len == 0) + return (len); + + /* look for the Server header */ + if (strncasecmp(buf, "Server: ", strlen("Server: ")) != 0) + return (len); + + if (strstr(buf, "Apache") != NULL) + st->server_type = APACHE; + else if (strstr(buf, "lighttpd") != NULL) + st->server_type = LIGHTTPD; + else if (strstr(buf, "IBM_HTTP_Server") != NULL) + st->server_type = APACHE; + else { + const char *hdr = buf; + + hdr += strlen("Server: "); + NOTICE("apache plugin: Unknown server software: %s", hdr); + } + + return (len); } /* apache_header_callback */ /* Configuration handling functiions @@ -169,454 +157,425 @@ static size_t apache_header_callback (void *buf, size_t size, size_t nmemb, * URL ... * */ -static int config_add (oconfig_item_t *ci) -{ - apache_t *st; - int i; - int status; - - st = malloc (sizeof (*st)); - if (st == NULL) - { - ERROR ("apache plugin: malloc failed."); - return (-1); - } - memset (st, 0, sizeof (*st)); - - st->timeout = -1; - - status = cf_util_get_string (ci, &st->name); - if (status != 0) - { - sfree (st); - return (status); - } - assert (st->name != NULL); - - for (i = 0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; - - if (strcasecmp ("URL", child->key) == 0) - status = cf_util_get_string (child, &st->url); - else if (strcasecmp ("Host", child->key) == 0) - status = cf_util_get_string (child, &st->host); - else if (strcasecmp ("User", child->key) == 0) - status = cf_util_get_string (child, &st->user); - else if (strcasecmp ("Password", child->key) == 0) - status = cf_util_get_string (child, &st->pass); - else if (strcasecmp ("VerifyPeer", child->key) == 0) - status = cf_util_get_boolean (child, &st->verify_peer); - else if (strcasecmp ("VerifyHost", child->key) == 0) - status = cf_util_get_boolean (child, &st->verify_host); - else if (strcasecmp ("CACert", child->key) == 0) - status = cf_util_get_string (child, &st->cacert); - else if (strcasecmp ("SSLCiphers", child->key) == 0) - status = cf_util_get_string (child, &st->ssl_ciphers); - else if (strcasecmp ("Server", child->key) == 0) - status = cf_util_get_string (child, &st->server); - else if (strcasecmp ("Timeout", child->key) == 0) - status = cf_util_get_int (child, &st->timeout); - else - { - WARNING ("apache plugin: Option `%s' not allowed here.", - child->key); - status = -1; - } - - if (status != 0) - break; - } - - /* Check if struct is complete.. */ - if ((status == 0) && (st->url == NULL)) - { - ERROR ("apache plugin: Instance `%s': " - "No URL has been configured.", - st->name); - status = -1; - } - - if (status == 0) - { - user_data_t ud; - char callback_name[3*DATA_MAX_NAME_LEN]; - - memset (&ud, 0, sizeof (ud)); - ud.data = st; - ud.free_func = (void *) apache_free; - - memset (callback_name, 0, sizeof (callback_name)); - ssnprintf (callback_name, sizeof (callback_name), - "apache/%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 = */ apache_read_host, - /* interval = */ NULL, - /* user_data = */ &ud); - } - - if (status != 0) - { - apache_free (st); - return (-1); - } - - return (0); +static int config_add(oconfig_item_t *ci) { + apache_t *st; + int status; + + st = calloc(1, sizeof(*st)); + if (st == NULL) { + ERROR("apache plugin: calloc failed."); + return (-1); + } + + st->timeout = -1; + + status = cf_util_get_string(ci, &st->name); + if (status != 0) { + sfree(st); + return (status); + } + assert(st->name != NULL); + + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("URL", child->key) == 0) + status = cf_util_get_string(child, &st->url); + else if (strcasecmp("Host", child->key) == 0) + status = cf_util_get_string(child, &st->host); + else if (strcasecmp("User", child->key) == 0) + status = cf_util_get_string(child, &st->user); + else if (strcasecmp("Password", child->key) == 0) + status = cf_util_get_string(child, &st->pass); + else if (strcasecmp("VerifyPeer", child->key) == 0) + status = cf_util_get_boolean(child, &st->verify_peer); + else if (strcasecmp("VerifyHost", child->key) == 0) + status = cf_util_get_boolean(child, &st->verify_host); + else if (strcasecmp("CACert", child->key) == 0) + status = cf_util_get_string(child, &st->cacert); + else if (strcasecmp("SSLCiphers", child->key) == 0) + status = cf_util_get_string(child, &st->ssl_ciphers); + else if (strcasecmp("Server", child->key) == 0) + status = cf_util_get_string(child, &st->server); + else if (strcasecmp("Timeout", child->key) == 0) + status = cf_util_get_int(child, &st->timeout); + else { + WARNING("apache plugin: Option `%s' not allowed here.", child->key); + status = -1; + } + + if (status != 0) + break; + } + + /* Check if struct is complete.. */ + if ((status == 0) && (st->url == NULL)) { + ERROR("apache plugin: Instance `%s': " + "No URL has been configured.", + st->name); + status = -1; + } + + if (status == 0) { + user_data_t ud = {.data = st, .free_func = apache_free}; + + char callback_name[3 * DATA_MAX_NAME_LEN]; + + ssnprintf(callback_name, sizeof(callback_name), "apache/%s/%s", + (st->host != NULL) ? st->host : hostname_g, + (st->name != NULL) ? st->name : "default"); + + status = plugin_register_complex_read(/* group = */ NULL, + /* name = */ callback_name, + /* callback = */ apache_read_host, + /* interval = */ 0, + /* user_data = */ &ud); + } + + if (status != 0) { + apache_free(st); + return (-1); + } + + return (0); } /* int config_add */ -static int config (oconfig_item_t *ci) -{ - int status = 0; - int i; - - for (i = 0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; - - if (strcasecmp ("Instance", child->key) == 0) - config_add (child); - else - WARNING ("apache plugin: The configuration option " - "\"%s\" is not allowed here. Did you " - "forget to add an block " - "around the configuration?", - child->key); - } /* for (ci->children) */ - - return (status); +static int 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("Instance", child->key) == 0) + config_add(child); + else + WARNING("apache plugin: The configuration option " + "\"%s\" is not allowed here. Did you " + "forget to add an block " + "around the configuration?", + child->key); + } /* for (ci->children) */ + + return (status); } /* int config */ /* initialize curl for each host */ -static int init_host (apache_t *st) /* {{{ */ +static int init_host(apache_t *st) /* {{{ */ { - assert (st->url != NULL); - /* (Assured by `config_add') */ - - if (st->curl != NULL) - { - curl_easy_cleanup (st->curl); - st->curl = NULL; - } - - if ((st->curl = curl_easy_init ()) == NULL) - { - ERROR ("apache plugin: init_host: `curl_easy_init' failed."); - return (-1); - } - - curl_easy_setopt (st->curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (st->curl, CURLOPT_WRITEFUNCTION, apache_curl_callback); - curl_easy_setopt (st->curl, CURLOPT_WRITEDATA, st); - - /* not set as yet if the user specified string doesn't match apache or - * lighttpd, then ignore it. Headers will be parsed to find out the - * server type */ - st->server_type = -1; - - if (st->server != NULL) - { - if (strcasecmp(st->server, "apache") == 0) - st->server_type = APACHE; - else if (strcasecmp(st->server, "lighttpd") == 0) - st->server_type = LIGHTTPD; - else if (strcasecmp(st->server, "ibm_http_server") == 0) - st->server_type = APACHE; - else - WARNING ("apache plugin: Unknown `Server' setting: %s", - st->server); - } - - /* if not found register a header callback to determine the server_type */ - if (st->server_type == -1) - { - curl_easy_setopt (st->curl, CURLOPT_HEADERFUNCTION, apache_header_callback); - curl_easy_setopt (st->curl, CURLOPT_WRITEHEADER, st); - } - - curl_easy_setopt (st->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); - curl_easy_setopt (st->curl, CURLOPT_ERRORBUFFER, st->apache_curl_error); - - if (st->user != NULL) - { + assert(st->url != NULL); + /* (Assured by `config_add') */ + + if (st->curl != NULL) { + curl_easy_cleanup(st->curl); + st->curl = NULL; + } + + if ((st->curl = curl_easy_init()) == NULL) { + ERROR("apache plugin: init_host: `curl_easy_init' failed."); + return (-1); + } + + curl_easy_setopt(st->curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(st->curl, CURLOPT_WRITEFUNCTION, apache_curl_callback); + curl_easy_setopt(st->curl, CURLOPT_WRITEDATA, st); + + /* not set as yet if the user specified string doesn't match apache or + * lighttpd, then ignore it. Headers will be parsed to find out the + * server type */ + st->server_type = -1; + + if (st->server != NULL) { + if (strcasecmp(st->server, "apache") == 0) + st->server_type = APACHE; + else if (strcasecmp(st->server, "lighttpd") == 0) + st->server_type = LIGHTTPD; + else if (strcasecmp(st->server, "ibm_http_server") == 0) + st->server_type = APACHE; + else + WARNING("apache plugin: Unknown `Server' setting: %s", st->server); + } + + /* if not found register a header callback to determine the server_type */ + if (st->server_type == -1) { + curl_easy_setopt(st->curl, CURLOPT_HEADERFUNCTION, apache_header_callback); + curl_easy_setopt(st->curl, CURLOPT_WRITEHEADER, st); + } + + curl_easy_setopt(st->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); + curl_easy_setopt(st->curl, CURLOPT_ERRORBUFFER, st->apache_curl_error); + + if (st->user != NULL) { #ifdef HAVE_CURLOPT_USERNAME - curl_easy_setopt (st->curl, CURLOPT_USERNAME, st->user); - curl_easy_setopt (st->curl, CURLOPT_PASSWORD, - (st->pass == NULL) ? "" : st->pass); + curl_easy_setopt(st->curl, CURLOPT_USERNAME, st->user); + curl_easy_setopt(st->curl, CURLOPT_PASSWORD, + (st->pass == NULL) ? "" : st->pass); #else - static char credentials[1024]; - int status; - - status = ssnprintf (credentials, sizeof (credentials), "%s:%s", - st->user, (st->pass == NULL) ? "" : st->pass); - if ((status < 0) || ((size_t) status >= sizeof (credentials))) - { - ERROR ("apache plugin: init_host: Returning an error " - "because the credentials have been " - "truncated."); - curl_easy_cleanup (st->curl); - st->curl = NULL; - return (-1); - } - - curl_easy_setopt (st->curl, CURLOPT_USERPWD, credentials); + static char credentials[1024]; + int status; + + status = ssnprintf(credentials, sizeof(credentials), "%s:%s", st->user, + (st->pass == NULL) ? "" : st->pass); + if ((status < 0) || ((size_t)status >= sizeof(credentials))) { + ERROR("apache plugin: init_host: Returning an error " + "because the credentials have been " + "truncated."); + curl_easy_cleanup(st->curl); + st->curl = NULL; + return (-1); + } + + curl_easy_setopt(st->curl, CURLOPT_USERPWD, credentials); #endif - } + } - curl_easy_setopt (st->curl, CURLOPT_URL, st->url); - curl_easy_setopt (st->curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt (st->curl, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(st->curl, CURLOPT_URL, st->url); + curl_easy_setopt(st->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(st->curl, CURLOPT_MAXREDIRS, 50L); - curl_easy_setopt (st->curl, CURLOPT_SSL_VERIFYPEER, - (long) st->verify_peer); - curl_easy_setopt (st->curl, CURLOPT_SSL_VERIFYHOST, - st->verify_host ? 2L : 0L); - if (st->cacert != NULL) - curl_easy_setopt (st->curl, CURLOPT_CAINFO, st->cacert); - if (st->ssl_ciphers != NULL) - curl_easy_setopt (st->curl, CURLOPT_SSL_CIPHER_LIST,st->ssl_ciphers); + curl_easy_setopt(st->curl, CURLOPT_SSL_VERIFYPEER, (long)st->verify_peer); + curl_easy_setopt(st->curl, CURLOPT_SSL_VERIFYHOST, st->verify_host ? 2L : 0L); + if (st->cacert != NULL) + curl_easy_setopt(st->curl, CURLOPT_CAINFO, st->cacert); + if (st->ssl_ciphers != NULL) + curl_easy_setopt(st->curl, CURLOPT_SSL_CIPHER_LIST, st->ssl_ciphers); #ifdef HAVE_CURLOPT_TIMEOUT_MS - 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())); + if (st->timeout >= 0) + curl_easy_setopt(st->curl, CURLOPT_TIMEOUT_MS, (long)st->timeout); + else + curl_easy_setopt(st->curl, CURLOPT_TIMEOUT_MS, + (long)CDTIME_T_TO_MS(plugin_get_interval())); #endif - return (0); + return (0); } /* }}} int init_host */ -static void submit_value (const char *type, const char *type_instance, - value_t value, apache_t *st) -{ - value_list_t vl = VALUE_LIST_INIT; +static void submit_value(const char *type, const char *type_instance, + value_t value, apache_t *st) { + value_list_t vl = VALUE_LIST_INIT; - vl.values = &value; - vl.values_len = 1; + vl.values = &value; + vl.values_len = 1; - sstrncpy (vl.host, (st->host != NULL) ? st->host : hostname_g, - sizeof (vl.host)); + sstrncpy(vl.host, (st->host != NULL) ? st->host : hostname_g, + sizeof(vl.host)); - sstrncpy (vl.plugin, "apache", sizeof (vl.plugin)); - if (st->name != NULL) - sstrncpy (vl.plugin_instance, st->name, - sizeof (vl.plugin_instance)); + sstrncpy(vl.plugin, "apache", sizeof(vl.plugin)); + if (st->name != NULL) + sstrncpy(vl.plugin_instance, st->name, sizeof(vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - if (type_instance != NULL) - sstrncpy (vl.type_instance, type_instance, - sizeof (vl.type_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + if (type_instance != NULL) + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } /* void submit_value */ -static void submit_derive (const char *type, const char *type_instance, - derive_t c, apache_t *st) -{ - value_t v; - v.derive = c; - submit_value (type, type_instance, v, st); +static void submit_derive(const char *type, const char *type_instance, + derive_t c, apache_t *st) { + value_t v; + v.derive = c; + submit_value(type, type_instance, v, st); } /* void submit_derive */ -static void submit_gauge (const char *type, const char *type_instance, - gauge_t g, apache_t *st) -{ - value_t v; - v.gauge = g; - submit_value (type, type_instance, v, st); +static void submit_gauge(const char *type, const char *type_instance, gauge_t g, + apache_t *st) { + value_t v; + v.gauge = g; + submit_value(type, type_instance, v, st); } /* void submit_gauge */ -static void submit_scoreboard (char *buf, apache_t *st) -{ - /* - * Scoreboard Key: - * "_" Waiting for Connection, "S" Starting up, - * "R" Reading Request for apache and read-POST for lighttpd, - * "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup, - * "C" Closing connection, "L" Logging, "G" Gracefully finishing, - * "I" Idle cleanup of worker, "." Open slot with no current process - * Lighttpd specific legends - - * "E" hard error, "." connect, "h" handle-request, - * "q" request-start, "Q" request-end, "s" response-start - * "S" response-end, "r" read - */ - long long open = 0LL; - long long waiting = 0LL; - long long starting = 0LL; - long long reading = 0LL; - long long sending = 0LL; - long long keepalive = 0LL; - long long dnslookup = 0LL; - long long closing = 0LL; - long long logging = 0LL; - long long finishing = 0LL; - long long idle_cleanup = 0LL; - - /* lighttpd specific */ - long long hard_error = 0LL; - long long lighttpd_read = 0LL; - long long handle_request = 0LL; - long long request_start = 0LL; - long long request_end = 0LL; - long long response_start = 0LL; - long long response_end = 0LL; - - int i; - for (i = 0; buf[i] != '\0'; i++) - { - if (buf[i] == '.') open++; - else if (buf[i] == '_') waiting++; - else if (buf[i] == 'S') starting++; - else if (buf[i] == 'R') reading++; - else if (buf[i] == 'W') sending++; - else if (buf[i] == 'K') keepalive++; - else if (buf[i] == 'D') dnslookup++; - else if (buf[i] == 'C') closing++; - else if (buf[i] == 'L') logging++; - else if (buf[i] == 'G') finishing++; - else if (buf[i] == 'I') idle_cleanup++; - else if (buf[i] == 'r') lighttpd_read++; - else if (buf[i] == 'h') handle_request++; - else if (buf[i] == 'E') hard_error++; - else if (buf[i] == 'q') request_start++; - else if (buf[i] == 'Q') request_end++; - else if (buf[i] == 's') response_start++; - else if (buf[i] == 'S') response_end++; - } - - if (st->server_type == APACHE) - { - submit_gauge ("apache_scoreboard", "open" , open, st); - submit_gauge ("apache_scoreboard", "waiting" , waiting, st); - submit_gauge ("apache_scoreboard", "starting" , starting, st); - submit_gauge ("apache_scoreboard", "reading" , reading, st); - submit_gauge ("apache_scoreboard", "sending" , sending, st); - submit_gauge ("apache_scoreboard", "keepalive", keepalive, st); - submit_gauge ("apache_scoreboard", "dnslookup", dnslookup, st); - submit_gauge ("apache_scoreboard", "closing" , closing, st); - submit_gauge ("apache_scoreboard", "logging" , logging, st); - submit_gauge ("apache_scoreboard", "finishing", finishing, st); - submit_gauge ("apache_scoreboard", "idle_cleanup", idle_cleanup, st); - } - else - { - submit_gauge ("apache_scoreboard", "connect" , open, st); - submit_gauge ("apache_scoreboard", "close" , closing, st); - submit_gauge ("apache_scoreboard", "hard_error" , hard_error, st); - submit_gauge ("apache_scoreboard", "read" , lighttpd_read, st); - submit_gauge ("apache_scoreboard", "read_post" , reading, st); - submit_gauge ("apache_scoreboard", "write" , sending, st); - submit_gauge ("apache_scoreboard", "handle_request", handle_request, st); - submit_gauge ("apache_scoreboard", "request_start" , request_start, st); - submit_gauge ("apache_scoreboard", "request_end" , request_end, st); - submit_gauge ("apache_scoreboard", "response_start", response_start, st); - submit_gauge ("apache_scoreboard", "response_end" , response_end, st); - } +static void submit_scoreboard(char *buf, apache_t *st) { + /* + * Scoreboard Key: + * "_" Waiting for Connection, "S" Starting up, + * "R" Reading Request for apache and read-POST for lighttpd, + * "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup, + * "C" Closing connection, "L" Logging, "G" Gracefully finishing, + * "I" Idle cleanup of worker, "." Open slot with no current process + * Lighttpd specific legends - + * "E" hard error, "." connect, "h" handle-request, + * "q" request-start, "Q" request-end, "s" response-start + * "S" response-end, "r" read + */ + long long open = 0LL; + long long waiting = 0LL; + long long starting = 0LL; + long long reading = 0LL; + long long sending = 0LL; + long long keepalive = 0LL; + long long dnslookup = 0LL; + long long closing = 0LL; + long long logging = 0LL; + long long finishing = 0LL; + long long idle_cleanup = 0LL; + + /* lighttpd specific */ + long long hard_error = 0LL; + long long lighttpd_read = 0LL; + long long handle_request = 0LL; + long long request_start = 0LL; + long long request_end = 0LL; + long long response_start = 0LL; + long long response_end = 0LL; + + for (int i = 0; buf[i] != '\0'; i++) { + if (buf[i] == '.') + open++; + else if (buf[i] == '_') + waiting++; + else if (buf[i] == 'S') + starting++; + else if (buf[i] == 'R') + reading++; + else if (buf[i] == 'W') + sending++; + else if (buf[i] == 'K') + keepalive++; + else if (buf[i] == 'D') + dnslookup++; + else if (buf[i] == 'C') + closing++; + else if (buf[i] == 'L') + logging++; + else if (buf[i] == 'G') + finishing++; + else if (buf[i] == 'I') + idle_cleanup++; + else if (buf[i] == 'r') + lighttpd_read++; + else if (buf[i] == 'h') + handle_request++; + else if (buf[i] == 'E') + hard_error++; + else if (buf[i] == 'q') + request_start++; + else if (buf[i] == 'Q') + request_end++; + else if (buf[i] == 's') + response_start++; + else if (buf[i] == 'S') + response_end++; + } + + if (st->server_type == APACHE) { + submit_gauge("apache_scoreboard", "open", open, st); + submit_gauge("apache_scoreboard", "waiting", waiting, st); + submit_gauge("apache_scoreboard", "starting", starting, st); + submit_gauge("apache_scoreboard", "reading", reading, st); + submit_gauge("apache_scoreboard", "sending", sending, st); + submit_gauge("apache_scoreboard", "keepalive", keepalive, st); + submit_gauge("apache_scoreboard", "dnslookup", dnslookup, st); + submit_gauge("apache_scoreboard", "closing", closing, st); + submit_gauge("apache_scoreboard", "logging", logging, st); + submit_gauge("apache_scoreboard", "finishing", finishing, st); + submit_gauge("apache_scoreboard", "idle_cleanup", idle_cleanup, st); + } else { + submit_gauge("apache_scoreboard", "connect", open, st); + submit_gauge("apache_scoreboard", "close", closing, st); + submit_gauge("apache_scoreboard", "hard_error", hard_error, st); + submit_gauge("apache_scoreboard", "read", lighttpd_read, st); + submit_gauge("apache_scoreboard", "read_post", reading, st); + submit_gauge("apache_scoreboard", "write", sending, st); + submit_gauge("apache_scoreboard", "handle_request", handle_request, st); + submit_gauge("apache_scoreboard", "request_start", request_start, st); + submit_gauge("apache_scoreboard", "request_end", request_end, st); + submit_gauge("apache_scoreboard", "response_start", response_start, st); + submit_gauge("apache_scoreboard", "response_end", response_end, st); + } } -static int apache_read_host (user_data_t *user_data) /* {{{ */ +static int apache_read_host(user_data_t *user_data) /* {{{ */ { - char *ptr; - char *saveptr; - char *line; - - char *fields[4]; - int fields_num; - - apache_t *st; - - st = user_data->data; - - int status; - - char *content_type; - static const char *text_plain = "text/plain"; - - assert (st->url != NULL); - /* (Assured by `config_add') */ - - if (st->curl == NULL) - { - status = init_host (st); - if (status != 0) - return (-1); - } - assert (st->curl != NULL); - - st->apache_buffer_fill = 0; - if (curl_easy_perform (st->curl) != CURLE_OK) - { - ERROR ("apache: curl_easy_perform failed: %s", - st->apache_curl_error); - return (-1); - } - - /* fallback - server_type to apache if not set at this time */ - if (st->server_type == -1) - { - WARNING ("apache plugin: Unable to determine server software " - "automatically. Will assume Apache."); - st->server_type = APACHE; - } - - status = curl_easy_getinfo (st->curl, CURLINFO_CONTENT_TYPE, &content_type); - if ((status == CURLE_OK) && (content_type != NULL) && - (strncasecmp (content_type, text_plain, strlen (text_plain)) != 0)) - { - WARNING ("apache plugin: `Content-Type' response header is not `%s' " - "(received: `%s'). Expecting unparseable data. Please check `URL' " - "parameter (missing `?auto' suffix ?)", - text_plain, content_type); - } - - ptr = st->apache_buffer; - saveptr = NULL; - while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL) - { - ptr = NULL; - fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields)); - - if (fields_num == 3) - { - if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "Accesses:") == 0)) - submit_derive ("apache_requests", "", atoll (fields[2]), st); - else if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "kBytes:") == 0)) - submit_derive ("apache_bytes", "", 1024LL * atoll (fields[2]), st); - } - else if (fields_num == 2) - { - if (strcmp (fields[0], "Scoreboard:") == 0) - submit_scoreboard (fields[1], st); - else if ((strcmp (fields[0], "BusyServers:") == 0) /* Apache 1.* */ - || (strcmp (fields[0], "BusyWorkers:") == 0) /* Apache 2.* */) - submit_gauge ("apache_connections", NULL, atol (fields[1]), st); - else if ((strcmp (fields[0], "IdleServers:") == 0) /* Apache 1.x */ - || (strcmp (fields[0], "IdleWorkers:") == 0) /* Apache 2.x */) - submit_gauge ("apache_idle_workers", NULL, atol (fields[1]), st); - } - } - - st->apache_buffer_fill = 0; - - return (0); + char *ptr; + char *saveptr; + char *line; + + char *fields[4]; + int fields_num; + + apache_t *st; + + st = user_data->data; + + int status; + + char *content_type; + static const char *text_plain = "text/plain"; + + assert(st->url != NULL); + /* (Assured by `config_add') */ + + if (st->curl == NULL) { + status = init_host(st); + if (status != 0) + return (-1); + } + assert(st->curl != NULL); + + st->apache_buffer_fill = 0; + if (curl_easy_perform(st->curl) != CURLE_OK) { + ERROR("apache: curl_easy_perform failed: %s", st->apache_curl_error); + return (-1); + } + + /* fallback - server_type to apache if not set at this time */ + if (st->server_type == -1) { + WARNING("apache plugin: Unable to determine server software " + "automatically. Will assume Apache."); + st->server_type = APACHE; + } + + status = curl_easy_getinfo(st->curl, CURLINFO_CONTENT_TYPE, &content_type); + if ((status == CURLE_OK) && (content_type != NULL) && + (strncasecmp(content_type, text_plain, strlen(text_plain)) != 0)) { + WARNING("apache plugin: `Content-Type' response header is not `%s' " + "(received: `%s'). Expecting unparseable data. Please check `URL' " + "parameter (missing `?auto' suffix ?)", + text_plain, content_type); + } + + ptr = st->apache_buffer; + saveptr = NULL; + while ((line = strtok_r(ptr, "\n\r", &saveptr)) != NULL) { + ptr = NULL; + fields_num = strsplit(line, fields, STATIC_ARRAY_SIZE(fields)); + + if (fields_num == 3) { + if ((strcmp(fields[0], "Total") == 0) && + (strcmp(fields[1], "Accesses:") == 0)) + submit_derive("apache_requests", "", atoll(fields[2]), st); + else if ((strcmp(fields[0], "Total") == 0) && + (strcmp(fields[1], "kBytes:") == 0)) + submit_derive("apache_bytes", "", 1024LL * atoll(fields[2]), st); + } else if (fields_num == 2) { + if (strcmp(fields[0], "Scoreboard:") == 0) + submit_scoreboard(fields[1], st); + else if ((strcmp(fields[0], "BusyServers:") == 0) /* Apache 1.* */ + || (strcmp(fields[0], "BusyWorkers:") == 0) /* Apache 2.* */) + submit_gauge("apache_connections", NULL, atol(fields[1]), st); + else if ((strcmp(fields[0], "IdleServers:") == 0) /* Apache 1.x */ + || (strcmp(fields[0], "IdleWorkers:") == 0) /* Apache 2.x */) + submit_gauge("apache_idle_workers", NULL, atol(fields[1]), st); + } + } + + st->apache_buffer_fill = 0; + + return (0); } /* }}} int apache_read_host */ -static int apache_init (void) /* {{{ */ +static int apache_init(void) /* {{{ */ { - /* Call this while collectd is still single-threaded to avoid - * initialization issues in libgcrypt. */ - curl_global_init (CURL_GLOBAL_SSL); - return (0); + /* Call this while collectd is still single-threaded to avoid + * initialization issues in libgcrypt. */ + curl_global_init(CURL_GLOBAL_SSL); + return (0); } /* }}} int apache_init */ -void module_register (void) -{ - plugin_register_complex_config ("apache", config); - plugin_register_init ("apache", apache_init); +void module_register(void) { + plugin_register_complex_config("apache", config); + plugin_register_init("apache", apache_init); } /* void module_register */ /* vim: set sw=8 noet fdm=marker : */ diff --git a/src/apcups.c b/src/apcups.c index eb1f0622..7a8aff4b 100644 --- a/src/apcups.c +++ b/src/apcups.c @@ -1,6 +1,6 @@ /* * collectd - src/apcups.c - * Copyright (C) 2006-2012 Florian octo Forster + * Copyright (C) 2006-2015 Florian octo Forster * Copyright (C) 2006 Anthony Gialluca * Copyright (C) 2000-2004 Kern Sibbald * Copyright (C) 1996-1999 Andre M. Hedrick @@ -25,90 +25,82 @@ **/ #include "collectd.h" -#include "common.h" /* rrd_update_file */ -#include "plugin.h" /* plugin_register, plugin_submit */ -#include "configfile.h" /* cf_register */ + +#include "common.h" /* rrd_update_file */ +#include "plugin.h" /* plugin_register, plugin_submit */ #if HAVE_SYS_TYPES_H -# include -#endif -#if HAVE_SYS_SOCKET_H -# include +#include #endif #if HAVE_NETDB_H -# include +#include #endif #if HAVE_NETINET_IN_H -# include +#include #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 */ -typedef struct -{ - gauge_t linev; - gauge_t loadpct; - gauge_t bcharge; - gauge_t timeleft; - gauge_t outputv; - gauge_t itemp; - gauge_t battv; - gauge_t linefreq; +typedef struct { + gauge_t linev; + gauge_t loadpct; + gauge_t bcharge; + gauge_t timeleft; + gauge_t outputv; + gauge_t itemp; + gauge_t battv; + gauge_t linefreq; } apc_detail_t; /* * 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) -{ - uint16_t packet_size = 0; +static int net_shutdown(int *fd) { + uint16_t packet_size = 0; - if ((fd == NULL) || (*fd < 0)) - return (EINVAL); + if ((fd == NULL) || (*fd < 0)) + return (EINVAL); - swrite (*fd, (void *) &packet_size, sizeof (packet_size)); - close (*fd); - *fd = -1; + (void)swrite(*fd, (void *)&packet_size, sizeof(packet_size)); + close(*fd); + *fd = -1; - return (0); + return (0); } /* int net_shutdown */ /* Close the network connection */ -static int apcups_shutdown (void) -{ - if (global_sockfd < 0) - return (0); +static int apcups_shutdown(void) { + if (global_sockfd < 0) + return (0); - net_shutdown (&global_sockfd); - return (0); + net_shutdown(&global_sockfd); + return (0); } /* int apcups_shutdown */ /* @@ -116,70 +108,56 @@ static int apcups_shutdown (void) * Returns -1 on error * Returns socket file descriptor otherwise */ -static int net_open (char *host, int port) -{ - 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; - - status = getaddrinfo (host, port_str, &ai_hints, &ai_return); - if (status != 0) - { - char errbuf[1024]; - INFO ("apcups plugin: getaddrinfo failed: %s", - (status == EAI_SYSTEM) - ? sstrerror (errno, errbuf, sizeof (errbuf)) - : gai_strerror (status)); - return (-1); - } - - /* Create socket */ - sd = -1; - for (ai_list = ai_return; ai_list != NULL; ai_list = ai_list->ai_next) - { - sd = socket (ai_list->ai_family, ai_list->ai_socktype, ai_list->ai_protocol); - if (sd >= 0) - break; - } - /* `ai_list' still holds the current description of the socket.. */ - - if (sd < 0) - { - DEBUG ("apcups plugin: Unable to open a socket"); - freeaddrinfo (ai_return); - return (-1); - } - - status = connect (sd, ai_list->ai_addr, ai_list->ai_addrlen); - - freeaddrinfo (ai_return); - - if (status != 0) /* `connect(2)' failed */ - { - char errbuf[1024]; - INFO ("apcups plugin: connect failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - close (sd); - return (-1); - } - - DEBUG ("apcups plugin: Done opening a socket %i", sd); - - return (sd); -} /* int net_open (char *host, char *service, int port) */ +static int net_open(char const *node, char const *service) { + int sd; + int status; + struct addrinfo *ai_return; + struct addrinfo *ai_list; + + /* 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(node, service, &ai_hints, &ai_return); + if (status != 0) { + char errbuf[1024]; + INFO("apcups plugin: getaddrinfo failed: %s", + (status == EAI_SYSTEM) ? sstrerror(errno, errbuf, sizeof(errbuf)) + : gai_strerror(status)); + return (-1); + } + + /* Create socket */ + sd = -1; + for (ai_list = ai_return; ai_list != NULL; ai_list = ai_list->ai_next) { + sd = socket(ai_list->ai_family, ai_list->ai_socktype, ai_list->ai_protocol); + if (sd >= 0) + break; + } + /* `ai_list' still holds the current description of the socket.. */ + + if (sd < 0) { + DEBUG("apcups plugin: Unable to open a socket"); + freeaddrinfo(ai_return); + return (-1); + } + + status = connect(sd, ai_list->ai_addr, ai_list->ai_addrlen); + + freeaddrinfo(ai_return); + + if (status != 0) /* `connect(2)' failed */ + { + char errbuf[1024]; + INFO("apcups plugin: connect failed: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + close(sd); + return (-1); + } + + DEBUG("apcups plugin: Done opening a socket %i", sd); + + return (sd); +} /* int net_open */ /* * Receive a message from the other end. Each message consists of @@ -190,41 +168,37 @@ static int net_open (char *host, int port) * Returns -1 on hard end of file (i.e. network connection close) * Returns -2 on error */ -static int net_recv (int *sockfd, char *buf, int buflen) -{ - uint16_t packet_size; - - /* get data size -- in short */ - if (sread (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0) - { - close (*sockfd); - *sockfd = -1; - return (-1); - } - - packet_size = ntohs (packet_size); - if (packet_size > buflen) - { - ERROR ("apcups plugin: Received %"PRIu16" bytes of payload " - "but have only %i bytes of buffer available.", - packet_size, buflen); - close (*sockfd); - *sockfd = -1; - return (-2); - } - - if (packet_size == 0) - return (0); - - /* now read the actual data */ - if (sread (*sockfd, (void *) buf, packet_size) != 0) - { - close (*sockfd); - *sockfd = -1; - return (-1); - } - - return ((int) packet_size); +static int net_recv(int *sockfd, char *buf, int buflen) { + uint16_t packet_size; + + /* get data size -- in short */ + if (sread(*sockfd, (void *)&packet_size, sizeof(packet_size)) != 0) { + close(*sockfd); + *sockfd = -1; + return (-1); + } + + packet_size = ntohs(packet_size); + if (packet_size > buflen) { + ERROR("apcups plugin: Received %" PRIu16 " bytes of payload " + "but have only %i bytes of buffer available.", + packet_size, buflen); + close(*sockfd); + *sockfd = -1; + return (-2); + } + + if (packet_size == 0) + return (0); + + /* now read the actual data */ + if (sread(*sockfd, (void *)buf, packet_size) != 0) { + close(*sockfd); + *sockfd = -1; + return (-1); + } + + return ((int)packet_size); } /* static int net_recv (int *sockfd, char *buf, int buflen) */ /* @@ -234,265 +208,242 @@ static int net_recv (int *sockfd, char *buf, int buflen) * Returns zero on success * Returns non-zero on error */ -static int net_send (int *sockfd, char *buff, int len) -{ - uint16_t packet_size; - - assert (len > 0); - assert (*sockfd >= 0); - - /* send short containing size of data packet */ - packet_size = htons ((uint16_t) len); - - if (swrite (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0) - { - close (*sockfd); - *sockfd = -1; - return (-1); - } - - /* send data packet */ - if (swrite (*sockfd, (void *) buff, len) != 0) - { - close (*sockfd); - *sockfd = -1; - return (-2); - } - - return (0); +static int net_send(int *sockfd, const char *buff, int len) { + uint16_t packet_size; + + assert(len > 0); + assert(*sockfd >= 0); + + /* send short containing size of data packet */ + packet_size = htons((uint16_t)len); + + if (swrite(*sockfd, (void *)&packet_size, sizeof(packet_size)) != 0) { + close(*sockfd); + *sockfd = -1; + return (-1); + } + + /* send data packet */ + if (swrite(*sockfd, (void *)buff, len) != 0) { + close(*sockfd); + *sockfd = -1; + return (-2); + } + + return (0); } /* Get and print status from apcupsd NIS server */ -static int apc_query_server (char *host, int port, - apc_detail_t *apcups_detail) -{ - int n; - char recvline[1024]; - char *tokptr; - char *toksaveptr; - _Bool retry = 1; - int status; +static int apc_query_server(char const *node, char const *service, + apc_detail_t *apcups_detail) { + int n; + char recvline[1024]; + char *tokptr; + char *toksaveptr; + _Bool retry = 1; + int status; #if APCMAIN -# define PRINT_VALUE(name, val) printf(" Found property: name = %s; value = %f;\n", name, val) +#define PRINT_VALUE(name, val) \ + printf(" Found property: name = %s; value = %f;\n", name, val) #else -# define PRINT_VALUE(name, val) /**/ +#define PRINT_VALUE(name, val) /**/ #endif - while (retry) - { - if (global_sockfd < 0) - { - global_sockfd = net_open (host, port); - if (global_sockfd < 0) - { - ERROR ("apcups plugin: Connecting to the " - "apcupsd failed."); - return (-1); - } - } - - - status = net_send (&global_sockfd, "status", strlen ("status")); - if (status != 0) - { - /* net_send is closing the socket on error. */ - assert (global_sockfd < 0); - if (retry) - { - retry = 0; - count_retries++; - continue; - } - - ERROR ("apcups plugin: Writing to the socket failed."); - return (-1); - } - - break; - } /* while (retry) */ - - /* When collectd's collection interval is larger than apcupsd's - * timeout, we would have to retry / re-connect each iteration. Try to - * detect this situation and shut down the socket gracefully in that - * case. Otherwise, keep the socket open to avoid overhead. */ - count_iterations++; - if ((count_iterations == 10) && (count_retries > 2)) - { - NOTICE ("apcups plugin: There have been %i retries in the " - "first %i iterations. Will close the socket " - "in future iterations.", - count_retries, count_iterations); - close_socket = 1; - } - - while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0) - { - assert ((unsigned int)n < sizeof (recvline)); - recvline[n] = '\0'; + while (retry) { + if (global_sockfd < 0) { + global_sockfd = net_open(node, service); + if (global_sockfd < 0) { + ERROR("apcups plugin: Connecting to the " + "apcupsd failed."); + return (-1); + } + } + + status = net_send(&global_sockfd, "status", strlen("status")); + if (status != 0) { + /* net_send is closing the socket on error. */ + assert(global_sockfd < 0); + if (retry) { + retry = 0; + count_retries++; + continue; + } + + ERROR("apcups plugin: Writing to the socket failed."); + return (-1); + } + + break; + } /* while (retry) */ + + /* When collectd's collection interval is larger than apcupsd's + * timeout, we would have to retry / re-connect each iteration. Try to + * detect this situation and shut down the socket gracefully in that + * case. Otherwise, keep the socket open to avoid overhead. */ + count_iterations++; + if ((count_iterations == 10) && (count_retries > 2)) { + NOTICE("apcups plugin: There have been %i retries in the " + "first %i iterations. Will close the socket " + "in future iterations.", + count_retries, count_iterations); + conf_persistent_conn = 0; + } + + while ((n = net_recv(&global_sockfd, recvline, sizeof(recvline) - 1)) > 0) { + assert((size_t)n < sizeof(recvline)); + recvline[n] = 0; #if APCMAIN - printf ("net_recv = `%s';\n", recvline); + printf("net_recv = `%s';\n", recvline); #endif /* if APCMAIN */ - toksaveptr = NULL; - tokptr = strtok_r (recvline, " :\t", &toksaveptr); - while (tokptr != NULL) - { - char *key = tokptr; - if ((tokptr = strtok_r (NULL, " :\t", &toksaveptr)) == NULL) - continue; - - gauge_t value; - if (strtogauge (tokptr, &value) != 0) - continue; - - PRINT_VALUE (key, value); - - if (strcmp ("LINEV", key) == 0) - apcups_detail->linev = value; - else if (strcmp ("BATTV", key) == 0) - apcups_detail->battv = value; - else if (strcmp ("ITEMP", key) == 0) - apcups_detail->itemp = value; - else if (strcmp ("LOADPCT", key) == 0) - apcups_detail->loadpct = value; - else if (strcmp ("BCHARGE", key) == 0) - apcups_detail->bcharge = value; - else if (strcmp ("OUTPUTV", key) == 0) - apcups_detail->outputv = value; - else if (strcmp ("LINEFREQ", key) == 0) - apcups_detail->linefreq = value; - else if (strcmp ("TIMELEFT", key) == 0) - { - /* Convert minutes to seconds if requested by - * the user. */ - if (conf_report_seconds) - value *= 60.0; - apcups_detail->timeleft = value; - } - - tokptr = strtok_r (NULL, ":", &toksaveptr); - } /* while (tokptr != NULL) */ - } - status = errno; /* save errno, net_shutdown() may re-set it. */ - - if (close_socket) - net_shutdown (&global_sockfd); - - if (n < 0) - { - char errbuf[1024]; - ERROR ("apcups plugin: Reading from socket failed: %s", - sstrerror (status, errbuf, sizeof (errbuf))); - return (-1); - } - - return (0); -} - -static int apcups_config (const char *key, const char *value) -{ - 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) - { - int port_tmp = atoi (value); - if (port_tmp < 1 || port_tmp > 65535) - { - WARNING ("apcups plugin: Invalid port: %i", port_tmp); - return (1); - } - conf_port = port_tmp; - } - else if (strcasecmp (key, "ReportSeconds") == 0) - { - if (IS_TRUE (value)) - conf_report_seconds = 1; - else - conf_report_seconds = 0; - } - else - { - return (-1); - } - return (0); + toksaveptr = NULL; + tokptr = strtok_r(recvline, " :\t", &toksaveptr); + while (tokptr != NULL) { + char *key = tokptr; + if ((tokptr = strtok_r(NULL, " :\t", &toksaveptr)) == NULL) + continue; + + gauge_t value; + if (strtogauge(tokptr, &value) != 0) + continue; + + PRINT_VALUE(key, value); + + if (strcmp("LINEV", key) == 0) + apcups_detail->linev = value; + else if (strcmp("BATTV", key) == 0) + apcups_detail->battv = value; + else if (strcmp("ITEMP", key) == 0) + apcups_detail->itemp = value; + else if (strcmp("LOADPCT", key) == 0) + apcups_detail->loadpct = value; + else if (strcmp("BCHARGE", key) == 0) + apcups_detail->bcharge = value; + else if (strcmp("OUTPUTV", key) == 0) + apcups_detail->outputv = value; + else if (strcmp("LINEFREQ", key) == 0) + apcups_detail->linefreq = value; + else if (strcmp("TIMELEFT", key) == 0) { + /* Convert minutes to seconds if requested by + * the user. */ + if (conf_report_seconds) + value *= 60.0; + apcups_detail->timeleft = value; + } + + tokptr = strtok_r(NULL, ":", &toksaveptr); + } /* while (tokptr != NULL) */ + } + status = errno; /* save errno, net_shutdown() may re-set it. */ + + if (!conf_persistent_conn) + net_shutdown(&global_sockfd); + + if (n < 0) { + char errbuf[1024]; + ERROR("apcups plugin: Reading from socket failed: %s", + sstrerror(status, errbuf, sizeof(errbuf))); + return (-1); + } + + return (0); } -static void apc_submit_generic (char *type, char *type_inst, gauge_t value) -{ - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; - - if (isnan (value)) - return; - - values[0].gauge = value; - - vl.values = values; - vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); +static int apcups_config(oconfig_item_t *ci) { + _Bool persistent_conn_set = 0; + + for (int i = 0; i < ci->children_num; i++) { + 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; + } else + ERROR("apcups plugin: Unknown config option \"%s\".", child->key); + } + + 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(const char *type, const char *type_inst, + gauge_t value) { + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + if (isnan(value)) + return; + + values[0].gauge = value; + + vl.values = values; + vl.values_len = 1; + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "apcups", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, "", sizeof(vl.plugin_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + sstrncpy(vl.type_instance, type_inst, sizeof(vl.type_instance)); + + plugin_dispatch_values(&vl); } -static void apc_submit (apc_detail_t const *apcups_detail) -{ - apc_submit_generic ("voltage", "input", apcups_detail->linev); - apc_submit_generic ("voltage", "output", apcups_detail->outputv); - apc_submit_generic ("voltage", "battery", apcups_detail->battv); - apc_submit_generic ("charge", "", apcups_detail->bcharge); - apc_submit_generic ("percent", "load", apcups_detail->loadpct); - apc_submit_generic ("timeleft", "", apcups_detail->timeleft); - apc_submit_generic ("temperature", "", apcups_detail->itemp); - apc_submit_generic ("frequency", "input", apcups_detail->linefreq); +static void apc_submit(apc_detail_t const *apcups_detail) { + apc_submit_generic("voltage", "input", apcups_detail->linev); + apc_submit_generic("voltage", "output", apcups_detail->outputv); + apc_submit_generic("voltage", "battery", apcups_detail->battv); + apc_submit_generic("charge", "", apcups_detail->bcharge); + apc_submit_generic("percent", "load", apcups_detail->loadpct); + apc_submit_generic("timeleft", "", apcups_detail->timeleft); + apc_submit_generic("temperature", "", apcups_detail->itemp); + apc_submit_generic("frequency", "input", apcups_detail->linefreq); } -static int apcups_read (void) -{ - apc_detail_t apcups_detail = { - .linev = NAN, - .outputv = NAN, - .battv = NAN, - .loadpct = NAN, - .bcharge = NAN, - .timeleft = NAN, - .itemp = NAN, - .linefreq = NAN, - }; - - int status = apc_query_server (conf_host == NULL - ? APCUPS_DEFAULT_HOST - : conf_host, - conf_port, &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); - return (status); - } - - apc_submit (&apcups_detail); - - return (0); +static int apcups_read(void) { + apc_detail_t apcups_detail = { + .linev = NAN, + .outputv = NAN, + .battv = NAN, + .loadpct = NAN, + .bcharge = NAN, + .timeleft = NAN, + .itemp = NAN, + .linefreq = NAN, + }; + + 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\", \"%s\") = %d", + conf_node == NULL ? APCUPS_DEFAULT_NODE : conf_node, conf_service, + status); + return (status); + } + + apc_submit(&apcups_detail); + + return (0); } /* apcups_read */ -void module_register (void) -{ - plugin_register_config ("apcups", apcups_config, config_keys, - config_keys_num); - plugin_register_read ("apcups", apcups_read); - plugin_register_shutdown ("apcups", apcups_shutdown); +void module_register(void) { + 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 19d5a49f..d15bec42 100644 --- a/src/apple_sensors.c +++ b/src/apple_sensors.c @@ -25,220 +25,180 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" #if HAVE_CTYPE_H -# include +#include #endif #if HAVE_MACH_MACH_TYPES_H -# include +#include #endif #if HAVE_MACH_MACH_INIT_H -# include +#include #endif #if HAVE_MACH_MACH_ERROR_H -# include +#include #endif #if HAVE_MACH_MACH_PORT_H -# include +#include #endif #if HAVE_COREFOUNDATION_COREFOUNDATION_H -# include +#include #endif #if HAVE_IOKIT_IOKITLIB_H -# include +#include #endif #if HAVE_IOKIT_IOTYPES_H -# include +#include #endif static mach_port_t io_master_port = MACH_PORT_NULL; -static int as_init (void) -{ - kern_return_t status; - - if (io_master_port != MACH_PORT_NULL) - { - mach_port_deallocate (mach_task_self (), - io_master_port); - io_master_port = MACH_PORT_NULL; - } - - status = IOMasterPort (MACH_PORT_NULL, &io_master_port); - if (status != kIOReturnSuccess) - { - ERROR ("IOMasterPort failed: %s", - mach_error_string (status)); - io_master_port = MACH_PORT_NULL; - return (-1); - } - - return (0); +static int as_init(void) { + kern_return_t status; + + if (io_master_port != MACH_PORT_NULL) { + mach_port_deallocate(mach_task_self(), io_master_port); + io_master_port = MACH_PORT_NULL; + } + + status = IOMasterPort(MACH_PORT_NULL, &io_master_port); + if (status != kIOReturnSuccess) { + ERROR("IOMasterPort failed: %s", mach_error_string(status)); + io_master_port = MACH_PORT_NULL; + return (-1); + } + + return (0); } -static void as_submit (const char *type, const char *type_instance, - double val) -{ - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; +static void as_submit(const char *type, const char *type_instance, double val) { + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; - DEBUG ("type = %s; type_instance = %s; val = %f;", - type, type_instance, val); + DEBUG("type = %s; type_instance = %s; val = %f;", type, type_instance, val); - values[0].gauge = val; + values[0].gauge = val; - vl.values = values; - vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + vl.values = values; + vl.values_len = 1; + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "apple_sensors", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, "", sizeof(vl.plugin_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } -static int as_read (void) -{ - kern_return_t status; - io_iterator_t iterator; - io_object_t io_obj; - CFMutableDictionaryRef prop_dict; - CFTypeRef property; - - char type[128]; - char inst[128]; - int value_int; - double value_double; - int i; - - if (!io_master_port || (io_master_port == MACH_PORT_NULL)) - return (-1); - - status = IOServiceGetMatchingServices (io_master_port, - IOServiceNameMatching("IOHWSensor"), - &iterator); - if (status != kIOReturnSuccess) - { - ERROR ("IOServiceGetMatchingServices failed: %s", - mach_error_string (status)); - return (-1); - } - - while ((io_obj = IOIteratorNext (iterator))) - { - prop_dict = NULL; - status = IORegistryEntryCreateCFProperties (io_obj, - &prop_dict, - kCFAllocatorDefault, - kNilOptions); - if (status != kIOReturnSuccess) - { - DEBUG ("IORegistryEntryCreateCFProperties failed: %s", - mach_error_string (status)); - continue; - } - - /* Copy the sensor type. */ - property = NULL; - if (!CFDictionaryGetValueIfPresent (prop_dict, - CFSTR ("type"), - &property)) - continue; - if (CFGetTypeID (property) != CFStringGetTypeID ()) - continue; - if (!CFStringGetCString (property, - type, sizeof (type), - kCFStringEncodingASCII)) - continue; - type[sizeof (type) - 1] = '\0'; - - /* Copy the sensor location. This will be used as `instance'. */ - property = NULL; - if (!CFDictionaryGetValueIfPresent (prop_dict, - CFSTR ("location"), - &property)) - continue; - if (CFGetTypeID (property) != CFStringGetTypeID ()) - continue; - if (!CFStringGetCString (property, - inst, sizeof (inst), - kCFStringEncodingASCII)) - continue; - inst[sizeof (inst) - 1] = '\0'; - for (i = 0; i < 128; i++) - { - if (inst[i] == '\0') - break; - else if (isalnum (inst[i])) - inst[i] = (char) tolower (inst[i]); - else - inst[i] = '_'; - } - - /* Get the actual value. Some computation, based on the `type' - * is neccessary. */ - property = NULL; - if (!CFDictionaryGetValueIfPresent (prop_dict, - CFSTR ("current-value"), - &property)) - continue; - if (CFGetTypeID (property) != CFNumberGetTypeID ()) - continue; - if (!CFNumberGetValue (property, - kCFNumberIntType, - &value_int)) - continue; - - /* Found e.g. in the 1.5GHz PowerBooks */ - if (strcmp (type, "temperature") == 0) - { - value_double = ((double) value_int) / 65536.0; - sstrncpy (type, "temperature", sizeof (type)); - } - else if (strcmp (type, "temp") == 0) - { - value_double = ((double) value_int) / 10.0; - sstrncpy (type, "temperature", sizeof (type)); - } - else if (strcmp (type, "fanspeed") == 0) - { - value_double = ((double) value_int) / 65536.0; - sstrncpy (type, "fanspeed", sizeof (type)); - } - else if (strcmp (type, "voltage") == 0) - { - /* Leave this to the battery plugin. */ - continue; - } - else if (strcmp (type, "adc") == 0) - { - value_double = ((double) value_int) / 10.0; - sstrncpy (type, "fanspeed", sizeof (type)); - } - else - { - DEBUG ("apple_sensors: Read unknown sensor type: %s", - type); - value_double = (double) value_int; - } - - as_submit (type, inst, value_double); - - CFRelease (prop_dict); - IOObjectRelease (io_obj); - } /* while (iterator) */ - - IOObjectRelease (iterator); - - return (0); +static int as_read(void) { + kern_return_t status; + io_iterator_t iterator; + io_object_t io_obj; + CFMutableDictionaryRef prop_dict; + CFTypeRef property; + + char type[128]; + char inst[128]; + int value_int; + double value_double; + if (!io_master_port || (io_master_port == MACH_PORT_NULL)) + return (-1); + + status = IOServiceGetMatchingServices( + io_master_port, IOServiceNameMatching("IOHWSensor"), &iterator); + if (status != kIOReturnSuccess) { + ERROR("IOServiceGetMatchingServices failed: %s", mach_error_string(status)); + return (-1); + } + + while ((io_obj = IOIteratorNext(iterator))) { + prop_dict = NULL; + status = IORegistryEntryCreateCFProperties( + io_obj, &prop_dict, kCFAllocatorDefault, kNilOptions); + if (status != kIOReturnSuccess) { + DEBUG("IORegistryEntryCreateCFProperties failed: %s", + mach_error_string(status)); + continue; + } + + /* Copy the sensor type. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent(prop_dict, CFSTR("type"), &property)) + continue; + if (CFGetTypeID(property) != CFStringGetTypeID()) + continue; + if (!CFStringGetCString(property, type, sizeof(type), + kCFStringEncodingASCII)) + continue; + type[sizeof(type) - 1] = '\0'; + + /* Copy the sensor location. This will be used as `instance'. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent(prop_dict, CFSTR("location"), &property)) + continue; + if (CFGetTypeID(property) != CFStringGetTypeID()) + continue; + if (!CFStringGetCString(property, inst, sizeof(inst), + kCFStringEncodingASCII)) + continue; + inst[sizeof(inst) - 1] = '\0'; + for (int i = 0; i < 128; i++) { + if (inst[i] == '\0') + break; + else if (isalnum(inst[i])) + inst[i] = (char)tolower(inst[i]); + else + inst[i] = '_'; + } + + /* Get the actual value. Some computation, based on the `type' + * is neccessary. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent(prop_dict, CFSTR("current-value"), + &property)) + continue; + if (CFGetTypeID(property) != CFNumberGetTypeID()) + continue; + if (!CFNumberGetValue(property, kCFNumberIntType, &value_int)) + continue; + + /* Found e.g. in the 1.5GHz PowerBooks */ + if (strcmp(type, "temperature") == 0) { + value_double = ((double)value_int) / 65536.0; + sstrncpy(type, "temperature", sizeof(type)); + } else if (strcmp(type, "temp") == 0) { + value_double = ((double)value_int) / 10.0; + sstrncpy(type, "temperature", sizeof(type)); + } else if (strcmp(type, "fanspeed") == 0) { + value_double = ((double)value_int) / 65536.0; + sstrncpy(type, "fanspeed", sizeof(type)); + } else if (strcmp(type, "voltage") == 0) { + /* Leave this to the battery plugin. */ + continue; + } else if (strcmp(type, "adc") == 0) { + value_double = ((double)value_int) / 10.0; + sstrncpy(type, "fanspeed", sizeof(type)); + } else { + DEBUG("apple_sensors: Read unknown sensor type: %s", type); + value_double = (double)value_int; + } + + as_submit(type, inst, value_double); + + CFRelease(prop_dict); + IOObjectRelease(io_obj); + } /* while (iterator) */ + + IOObjectRelease(iterator); + + return (0); } /* int as_read */ -void module_register (void) -{ - plugin_register_init ("apple_sensors", as_init); - plugin_register_read ("apple_sensors", as_read); +void module_register(void) { + plugin_register_init("apple_sensors", as_init); + plugin_register_read("apple_sensors", as_read); } /* void module_register */ diff --git a/src/aquaero.c b/src/aquaero.c index 5db988e6..412f3000 100644 --- a/src/aquaero.c +++ b/src/aquaero.c @@ -20,6 +20,7 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" @@ -31,163 +32,138 @@ /* Default values for contacting daemon */ static char *conf_device = NULL; -static int aquaero_config (oconfig_item_t *ci) -{ - int i; - - for (i = 0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; +static int aquaero_config(oconfig_item_t *ci) { + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; - if (strcasecmp ("Device", child->key)) - cf_util_get_string (child, &conf_device); - else - { - ERROR ("aquaero plugin: Unknown config option \"%s\".", - child->key); - } - } + if (strcasecmp("Device", child->key)) + cf_util_get_string(child, &conf_device); + else { + ERROR("aquaero plugin: Unknown config option \"%s\".", child->key); + } + } - return (0); + return (0); } -static int aquaero_shutdown (void) -{ - libaquaero5_exit(); - return (0); +static int aquaero_shutdown(void) { + libaquaero5_exit(); + return (0); } /* int aquaero_shutdown */ -static void aquaero_submit (const char *type, const char *type_instance, - double value) -{ - const char *instance = conf_device?conf_device:"default"; - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; +static void aquaero_submit(const char *type, const char *type_instance, + double value) { + const char *instance = conf_device ? conf_device : "default"; + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; - /* Don't report undefined values. */ - if (value == AQ5_FLOAT_UNDEF) - return; + /* Don't report undefined values. */ + if (value == AQ5_FLOAT_UNDEF) + return; - values[0].gauge = value; + values[0].gauge = value; - vl.values = values; - vl.values_len = 1; + vl.values = values; + vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "aquaero", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, instance, sizeof (vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "aquaero", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, instance, sizeof(vl.plugin_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } /* int aquaero_submit */ /* aquaero_submit_array submits every value of a given array of values */ -static void aquaero_submit_array (const char *type, - 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++) - { - if (value_array[i] == AQ5_FLOAT_UNDEF) - continue; - - snprintf (type_instance, sizeof (type_instance), "%s%d", - type_instance_prefix, i + 1); - aquaero_submit (type, type_instance, value_array[i]); - } +static void aquaero_submit_array(const char *type, + const char *type_instance_prefix, + double *value_array, int len) { + char type_instance[DATA_MAX_NAME_LEN]; + + for (int i = 0; i < len; i++) { + if (value_array[i] == AQ5_FLOAT_UNDEF) + continue; + + snprintf(type_instance, sizeof(type_instance), "%s%d", type_instance_prefix, + i + 1); + aquaero_submit(type, type_instance, value_array[i]); + } } -static int aquaero_read (void) -{ - aq5_data_t aq_data; - 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) - { - char errbuf[1024]; - ERROR ("aquaero plugin: Failed to poll device \"%s\": %s (%s)", - conf_device ? conf_device : "default", err_msg, - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); - } - - if (libaquaero5_getsettings(conf_device, &aq_sett, &err_msg) < 0) - { - char errbuf[1024]; - ERROR ("aquaero plugin: Failed to get settings " - "for device \"%s\": %s (%s)", - conf_device ? conf_device : "default", err_msg, - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); - } - - /* CPU Temperature sensor */ - aquaero_submit("temperature", "cpu", aq_data.cpu_temp[0]); - - /* Temperature sensors */ - aquaero_submit_array("temperature", "sensor", aq_data.temp, - AQ5_NUM_TEMP); - - /* Virtual temperature sensors */ - aquaero_submit_array("temperature", "virtual", aq_data.vtemp, - AQ5_NUM_VIRT_SENSORS); - - /* Software temperature sensors */ - aquaero_submit_array("temperature", "software", aq_data.stemp, - AQ5_NUM_SOFT_SENSORS); - - /* Other temperature sensors */ - aquaero_submit_array("temperature", "other", aq_data.otemp, - AQ5_NUM_OTHER_SENSORS); - - /* Fans */ - for (i = 0; i < AQ5_NUM_FAN; i++) - { - if ((aq_sett.fan_data_source[i] == NONE) - || (aq_data.fan_vrm_temp[i] != AQ5_FLOAT_UNDEF)) - continue; - - snprintf (type_instance, sizeof (type_instance), - "fan%d", i + 1); - - aquaero_submit ("fanspeed", type_instance, - aq_data.fan_rpm[i]); - aquaero_submit ("percent", type_instance, - aq_data.fan_duty[i]); - aquaero_submit ("voltage", type_instance, - aq_data.fan_voltage[i]); - aquaero_submit ("current", type_instance, - aq_data.fan_current[i]); - - /* Report the voltage reglator module (VRM) temperature with a - * different type instance. */ - snprintf (type_instance, sizeof (type_instance), - "fan%d-vrm", i + 1); - aquaero_submit ("temperature", type_instance, - aq_data.fan_vrm_temp[i]); - } - - /* Flow sensors */ - aquaero_submit_array("flow", "sensor", aq_data.flow, AQ5_NUM_FLOW); - - /* Liquid level */ - aquaero_submit_array("percent", "waterlevel", - aq_data.level, AQ5_NUM_LEVEL); - - return (0); +static int aquaero_read(void) { + aq5_data_t aq_data; + aq5_settings_t aq_sett; + char *err_msg = NULL; + char type_instance[DATA_MAX_NAME_LEN]; + + if (libaquaero5_poll(conf_device, &aq_data, &err_msg) < 0) { + char errbuf[1024]; + ERROR("aquaero plugin: Failed to poll device \"%s\": %s (%s)", + conf_device ? conf_device : "default", err_msg, + sstrerror(errno, errbuf, sizeof(errbuf))); + return (-1); + } + + if (libaquaero5_getsettings(conf_device, &aq_sett, &err_msg) < 0) { + char errbuf[1024]; + ERROR("aquaero plugin: Failed to get settings " + "for device \"%s\": %s (%s)", + conf_device ? conf_device : "default", err_msg, + sstrerror(errno, errbuf, sizeof(errbuf))); + return (-1); + } + + /* CPU Temperature sensor */ + aquaero_submit("temperature", "cpu", aq_data.cpu_temp[0]); + + /* Temperature sensors */ + aquaero_submit_array("temperature", "sensor", aq_data.temp, AQ5_NUM_TEMP); + + /* Virtual temperature sensors */ + aquaero_submit_array("temperature", "virtual", aq_data.vtemp, + AQ5_NUM_VIRT_SENSORS); + + /* Software temperature sensors */ + aquaero_submit_array("temperature", "software", aq_data.stemp, + AQ5_NUM_SOFT_SENSORS); + + /* Other temperature sensors */ + aquaero_submit_array("temperature", "other", aq_data.otemp, + AQ5_NUM_OTHER_SENSORS); + + /* Fans */ + 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)) + continue; + + snprintf(type_instance, sizeof(type_instance), "fan%d", i + 1); + + aquaero_submit("fanspeed", type_instance, aq_data.fan_rpm[i]); + aquaero_submit("percent", type_instance, aq_data.fan_duty[i]); + aquaero_submit("voltage", type_instance, aq_data.fan_voltage[i]); + aquaero_submit("current", type_instance, aq_data.fan_current[i]); + + /* Report the voltage reglator module (VRM) temperature with a + * different type instance. */ + snprintf(type_instance, sizeof(type_instance), "fan%d-vrm", i + 1); + aquaero_submit("temperature", type_instance, aq_data.fan_vrm_temp[i]); + } + + /* Flow sensors */ + aquaero_submit_array("flow", "sensor", aq_data.flow, AQ5_NUM_FLOW); + + /* Liquid level */ + aquaero_submit_array("percent", "waterlevel", aq_data.level, AQ5_NUM_LEVEL); + + return (0); } -void module_register (void) -{ - plugin_register_complex_config ("aquaero", aquaero_config); - plugin_register_read ("aquaero", aquaero_read); - plugin_register_shutdown ("aquaero", aquaero_shutdown); +void module_register(void) { + plugin_register_complex_config("aquaero", aquaero_config); + plugin_register_read("aquaero", aquaero_read); + plugin_register_shutdown("aquaero", aquaero_shutdown); } /* void module_register */ /* vim: set sw=8 sts=8 noet : */ diff --git a/src/ascent.c b/src/ascent.c index 11175af5..f5c3071a 100644 --- a/src/ascent.c +++ b/src/ascent.c @@ -25,56 +25,47 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" -#include "configfile.h" #include #include -static char *races_list[] = /* {{{ */ -{ - NULL, - "Human", /* 1 */ - "Orc", /* 2 */ - "Dwarf", /* 3 */ - "Nightelf", /* 4 */ - "Undead", /* 5 */ - "Tauren", /* 6 */ - "Gnome", /* 7 */ - "Troll", /* 8 */ - NULL, - "Bloodelf", /* 10 */ - "Draenei" /* 11 */ -}; /* }}} */ -#define RACES_LIST_LENGTH STATIC_ARRAY_SIZE (races_list) - -static char *classes_list[] = /* {{{ */ -{ - NULL, - "Warrior", /* 1 */ - "Paladin", /* 2 */ - "Hunter", /* 3 */ - "Rogue", /* 4 */ - "Priest", /* 5 */ - NULL, - "Shaman", /* 7 */ - "Mage", /* 8 */ - "Warlock", /* 9 */ - NULL, - "Druid" /* 11 */ -}; /* }}} */ -#define CLASSES_LIST_LENGTH STATIC_ARRAY_SIZE (classes_list) - -static char *genders_list[] = /* {{{ */ -{ - "Male", - "Female" -}; /* }}} */ -#define GENDERS_LIST_LENGTH STATIC_ARRAY_SIZE (genders_list) - -struct player_stats_s -{ +static const char *races_list[] = /* {{{ */ + { + NULL, "Human", /* 1 */ + "Orc", /* 2 */ + "Dwarf", /* 3 */ + "Nightelf", /* 4 */ + "Undead", /* 5 */ + "Tauren", /* 6 */ + "Gnome", /* 7 */ + "Troll", /* 8 */ + NULL, "Bloodelf", /* 10 */ + "Draenei" /* 11 */ +}; /* }}} */ +#define RACES_LIST_LENGTH STATIC_ARRAY_SIZE(races_list) + +static const char *classes_list[] = /* {{{ */ + { + NULL, "Warrior", /* 1 */ + "Paladin", /* 2 */ + "Hunter", /* 3 */ + "Rogue", /* 4 */ + "Priest", /* 5 */ + NULL, "Shaman", /* 7 */ + "Mage", /* 8 */ + "Warlock", /* 9 */ + NULL, "Druid" /* 11 */ +}; /* }}} */ +#define CLASSES_LIST_LENGTH STATIC_ARRAY_SIZE(classes_list) + +static const char *genders_list[] = /* {{{ */ + {"Male", "Female"}; /* }}} */ +#define GENDERS_LIST_LENGTH STATIC_ARRAY_SIZE(genders_list) + +struct player_stats_s { int races[RACES_LIST_LENGTH]; int classes[CLASSES_LIST_LENGTH]; int genders[GENDERS_LIST_LENGTH]; @@ -85,8 +76,7 @@ struct player_stats_s }; typedef struct player_stats_s player_stats_t; -struct player_info_s -{ +struct player_info_s { int race; int class; int gender; @@ -94,38 +84,32 @@ struct player_info_s int latency; }; typedef struct player_info_s player_info_t; -#define PLAYER_INFO_STATIC_INIT { -1, -1, -1, -1, -1 } +#define PLAYER_INFO_STATIC_INIT \ + { -1, -1, -1, -1, -1 } -static char *url = NULL; -static char *user = NULL; -static char *pass = NULL; +static char *url = NULL; +static char *user = NULL; +static char *pass = NULL; static char *verify_peer = NULL; static char *verify_host = NULL; -static char *cacert = NULL; -static char *timeout = NULL; +static char *cacert = NULL; +static char *timeout = NULL; static CURL *curl = NULL; -static char *ascent_buffer = NULL; +static char *ascent_buffer = NULL; static size_t ascent_buffer_size = 0; static size_t ascent_buffer_fill = 0; -static char ascent_curl_error[CURL_ERROR_SIZE]; +static char ascent_curl_error[CURL_ERROR_SIZE]; -static const char *config_keys[] = -{ - "URL", - "User", - "Password", - "VerifyPeer", - "VerifyHost", - "CACert", - "Timeout", +static const char *config_keys[] = { + "URL", "User", "Password", "VerifyPeer", "VerifyHost", "CACert", "Timeout", }; -static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); +static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */ - const char *type, const char *type_instance, gauge_t value) -{ +static int ascent_submit_gauge(const char *plugin_instance, /* {{{ */ + const char *type, const char *type_instance, + gauge_t value) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; @@ -133,128 +117,115 @@ static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */ vl.values = values; vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "ascent", sizeof (vl.plugin)); + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "ascent", sizeof(vl.plugin)); if (plugin_instance != NULL) - sstrncpy (vl.plugin_instance, plugin_instance, - sizeof (vl.plugin_instance)); + sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); + sstrncpy(vl.type, type, sizeof(vl.type)); if (type_instance != NULL) - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); return (0); } /* }}} int ascent_submit_gauge */ -static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{ */ - void __attribute__((unused)) *stream) -{ +static size_t ascent_curl_callback(void *buf, size_t size, + size_t nmemb, /* {{{ */ + void __attribute__((unused)) * stream) { size_t len = size * nmemb; - if (len <= 0) + if (len == 0) return (len); - if ((ascent_buffer_fill + len) >= ascent_buffer_size) - { + if ((ascent_buffer_fill + len) >= ascent_buffer_size) { char *temp; - temp = (char *) realloc (ascent_buffer, - ascent_buffer_fill + len + 1); - if (temp == NULL) - { - ERROR ("ascent plugin: realloc failed."); + temp = realloc(ascent_buffer, ascent_buffer_fill + len + 1); + if (temp == NULL) { + ERROR("ascent plugin: realloc failed."); return (0); } ascent_buffer = temp; ascent_buffer_size = ascent_buffer_fill + len + 1; } - memcpy (ascent_buffer + ascent_buffer_fill, (char *) buf, len); + memcpy(ascent_buffer + ascent_buffer_fill, (char *)buf, len); ascent_buffer_fill += len; ascent_buffer[ascent_buffer_fill] = 0; return (len); } /* }}} size_t ascent_curl_callback */ -static int ascent_submit_players (player_stats_t *ps) /* {{{ */ +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]); + 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]); + 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]); + ascent_submit_gauge("by-gender", "players", genders_list[i], + (gauge_t)ps->genders[i]); if (ps->level_num <= 0) value = NAN; else - value = ((double) ps->level_sum) / ((double) ps->level_num); - ascent_submit_gauge (NULL, "gauge", "avg-level", value); + value = ((double)ps->level_sum) / ((double)ps->level_num); + ascent_submit_gauge(NULL, "gauge", "avg-level", value); /* Latency is in ms, but we store seconds. */ if (ps->latency_num <= 0) value = NAN; else - value = ((double) ps->latency_sum) / (1000.0 * ((double) ps->latency_num)); - ascent_submit_gauge (NULL, "latency", "average", value); + value = ((double)ps->latency_sum) / (1000.0 * ((double)ps->latency_num)); + ascent_submit_gauge(NULL, "latency", "average", value); return (0); } /* }}} int ascent_submit_players */ -static int ascent_account_player (player_stats_t *ps, /* {{{ */ - player_info_t *pi) -{ - if (pi->race >= 0) - { - if (((size_t) pi->race >= RACES_LIST_LENGTH) - || (races_list[pi->race] == NULL)) - ERROR ("ascent plugin: Ignoring invalid numeric race %i.", pi->race); +static int ascent_account_player(player_stats_t *ps, /* {{{ */ + player_info_t *pi) { + if (pi->race >= 0) { + if (((size_t)pi->race >= RACES_LIST_LENGTH) || + (races_list[pi->race] == NULL)) + ERROR("ascent plugin: Ignoring invalid numeric race %i.", pi->race); else ps->races[pi->race]++; } - if (pi->class >= 0) - { - if (((size_t) pi->class >= CLASSES_LIST_LENGTH) - || (classes_list[pi->class] == NULL)) - ERROR ("ascent plugin: Ignoring invalid numeric class %i.", pi->class); + if (pi->class >= 0) { + if (((size_t)pi->class >= CLASSES_LIST_LENGTH) || + (classes_list[pi->class] == NULL)) + ERROR("ascent plugin: Ignoring invalid numeric class %i.", pi->class); else ps->classes[pi->class]++; } - if (pi->gender >= 0) - { - if (((size_t) pi->gender >= GENDERS_LIST_LENGTH) - || (genders_list[pi->gender] == NULL)) - ERROR ("ascent plugin: Ignoring invalid numeric gender %i.", - pi->gender); + if (pi->gender >= 0) { + if (((size_t)pi->gender >= GENDERS_LIST_LENGTH) || + (genders_list[pi->gender] == NULL)) + ERROR("ascent plugin: Ignoring invalid numeric gender %i.", pi->gender); else ps->genders[pi->gender]++; } - - if (pi->level > 0) - { + if (pi->level > 0) { ps->level_sum += pi->level; ps->level_num++; } - if (pi->latency >= 0) - { + if (pi->latency >= 0) { ps->latency_sum += pi->latency; ps->latency_num++; } @@ -262,60 +233,55 @@ static int ascent_account_player (player_stats_t *ps, /* {{{ */ return (0); } /* }}} int ascent_account_player */ -static int ascent_xml_submit_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */ - const char *plugin_instance, const char *type, const char *type_instance) -{ +static int ascent_xml_submit_gauge(xmlDoc *doc, xmlNode *node, /* {{{ */ + const char *plugin_instance, + const char *type, + const char *type_instance) { char *str_ptr; gauge_t value; - str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); - if (str_ptr == NULL) - { - ERROR ("ascent plugin: ascent_xml_submit_gauge: xmlNodeListGetString failed."); + str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + ERROR( + "ascent plugin: ascent_xml_submit_gauge: xmlNodeListGetString failed."); return (-1); } - if (strcasecmp ("N/A", str_ptr) == 0) + if (strcasecmp("N/A", str_ptr) == 0) value = NAN; - else - { + else { char *end_ptr = NULL; - value = strtod (str_ptr, &end_ptr); - if (str_ptr == end_ptr) - { + value = strtod(str_ptr, &end_ptr); + if (str_ptr == end_ptr) { xmlFree(str_ptr); - ERROR ("ascent plugin: ascent_xml_submit_gauge: strtod failed."); + ERROR("ascent plugin: ascent_xml_submit_gauge: strtod failed."); return (-1); } } xmlFree(str_ptr); - return (ascent_submit_gauge (plugin_instance, type, type_instance, value)); + return (ascent_submit_gauge(plugin_instance, type, type_instance, value)); } /* }}} int ascent_xml_submit_gauge */ -static int ascent_xml_read_int (xmlDoc *doc, xmlNode *node, /* {{{ */ - int *ret_value) -{ +static int ascent_xml_read_int(xmlDoc *doc, xmlNode *node, /* {{{ */ + int *ret_value) { char *str_ptr; int value; - str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); - if (str_ptr == NULL) - { - ERROR ("ascent plugin: ascent_xml_read_int: xmlNodeListGetString failed."); + str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + ERROR("ascent plugin: ascent_xml_read_int: xmlNodeListGetString failed."); return (-1); } - if (strcasecmp ("N/A", str_ptr) == 0) + if (strcasecmp("N/A", str_ptr) == 0) value = -1; - else - { + else { char *end_ptr = NULL; - value = strtol (str_ptr, &end_ptr, 0); - if (str_ptr == end_ptr) - { + value = strtol(str_ptr, &end_ptr, 0); + if (str_ptr == end_ptr) { xmlFree(str_ptr); - ERROR ("ascent plugin: ascent_xml_read_int: strtol failed."); + ERROR("ascent plugin: ascent_xml_read_int: strtol failed."); return (-1); } } @@ -325,120 +291,106 @@ static int ascent_xml_read_int (xmlDoc *doc, xmlNode *node, /* {{{ */ return (0); } /* }}} int ascent_xml_read_int */ -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) - { - if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0)) +static int ascent_xml_sessions_plr(xmlDoc *doc, xmlNode *node, /* {{{ */ + player_info_t *pi) { + 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)) /* ignore */; - else if (xmlStrcmp ((const xmlChar *) "race", child->name) == 0) - ascent_xml_read_int (doc, child, &pi->race); - else if (xmlStrcmp ((const xmlChar *) "class", child->name) == 0) - ascent_xml_read_int (doc, child, &pi->class); - else if (xmlStrcmp ((const xmlChar *) "gender", child->name) == 0) - ascent_xml_read_int (doc, child, &pi->gender); - else if (xmlStrcmp ((const xmlChar *) "level", child->name) == 0) - ascent_xml_read_int (doc, child, &pi->level); - else if (xmlStrcmp ((const xmlChar *) "latency", child->name) == 0) - ascent_xml_read_int (doc, child, &pi->latency); - else if ((xmlStrcmp ((const xmlChar *) "name", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "pvprank", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "map", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "areaid", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "xpos", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "ypos", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "onime", child->name) == 0)) + else if (xmlStrcmp((const xmlChar *)"race", child->name) == 0) + ascent_xml_read_int(doc, child, &pi->race); + else if (xmlStrcmp((const xmlChar *)"class", child->name) == 0) + ascent_xml_read_int(doc, child, &pi->class); + else if (xmlStrcmp((const xmlChar *)"gender", child->name) == 0) + ascent_xml_read_int(doc, child, &pi->gender); + else if (xmlStrcmp((const xmlChar *)"level", child->name) == 0) + ascent_xml_read_int(doc, child, &pi->level); + else if (xmlStrcmp((const xmlChar *)"latency", child->name) == 0) + ascent_xml_read_int(doc, child, &pi->latency); + else if ((xmlStrcmp((const xmlChar *)"name", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"pvprank", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"map", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"areaid", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"xpos", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"ypos", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"onime", child->name) == 0)) /* ignore */; - else - { - WARNING ("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name); + else { + WARNING("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name); } } /* for (child) */ return (0); } /* }}} int ascent_xml_sessions_plr */ -static int ascent_xml_sessions (xmlDoc *doc, xmlNode *node) /* {{{ */ +static int ascent_xml_sessions(xmlDoc *doc, xmlNode *node) /* {{{ */ { - xmlNode *child; - player_stats_t ps; - - memset (&ps, 0, sizeof (ps)); + player_stats_t ps = {.level_sum = 0}; - for (child = node->xmlChildrenNode; child != NULL; child = child->next) - { - if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0)) + 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)) /* ignore */; - else if (xmlStrcmp ((const xmlChar *) "plr", child->name) == 0) - { + else if (xmlStrcmp((const xmlChar *)"plr", child->name) == 0) { int status; player_info_t pi = PLAYER_INFO_STATIC_INIT; - status = ascent_xml_sessions_plr (doc, child, &pi); + status = ascent_xml_sessions_plr(doc, child, &pi); if (status == 0) - ascent_account_player (&ps, &pi); - } - else - { - WARNING ("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name); + ascent_account_player(&ps, &pi); + } else { + WARNING("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name); } } /* for (child) */ - ascent_submit_players (&ps); + ascent_submit_players(&ps); return (0); } /* }}} int ascent_xml_sessions */ -static int ascent_xml_status (xmlDoc *doc, xmlNode *node) /* {{{ */ +static int ascent_xml_status(xmlDoc *doc, xmlNode *node) /* {{{ */ { - xmlNode *child; - - for (child = node->xmlChildrenNode; child != NULL; child = child->next) - { - if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0)) + 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)) /* ignore */; - else if (xmlStrcmp ((const xmlChar *) "alliance", child->name) == 0) - ascent_xml_submit_gauge (doc, child, NULL, "players", "alliance"); - else if (xmlStrcmp ((const xmlChar *) "horde", child->name) == 0) - ascent_xml_submit_gauge (doc, child, NULL, "players", "horde"); - else if (xmlStrcmp ((const xmlChar *) "qplayers", child->name) == 0) - ascent_xml_submit_gauge (doc, child, NULL, "players", "queued"); - else if ((xmlStrcmp ((const xmlChar *) "acceptedconns", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "avglat", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "cdbquerysize", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "cpu", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "fthreads", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "gmcount", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "lastupdate", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "ontime", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "oplayers", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "peakcount", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "platform", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "ram", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "threads", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "uptime", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "wdbquerysize", child->name) == 0)) + else if (xmlStrcmp((const xmlChar *)"alliance", child->name) == 0) + ascent_xml_submit_gauge(doc, child, NULL, "players", "alliance"); + else if (xmlStrcmp((const xmlChar *)"horde", child->name) == 0) + ascent_xml_submit_gauge(doc, child, NULL, "players", "horde"); + else if (xmlStrcmp((const xmlChar *)"qplayers", child->name) == 0) + ascent_xml_submit_gauge(doc, child, NULL, "players", "queued"); + else if ((xmlStrcmp((const xmlChar *)"acceptedconns", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"avglat", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"cdbquerysize", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"cpu", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"fthreads", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"gmcount", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"lastupdate", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"ontime", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"oplayers", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"peakcount", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"platform", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"ram", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"threads", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"uptime", child->name) == 0) || + (xmlStrcmp((const xmlChar *)"wdbquerysize", child->name) == 0)) /* ignore */; - else - { - WARNING ("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name); + else { + WARNING("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name); } } /* for (child) */ return (0); } /* }}} int ascent_xml_status */ -static int ascent_xml (const char *data) /* {{{ */ +static int ascent_xml(const char *data) /* {{{ */ { xmlDoc *doc; xmlNode *cur; - xmlNode *child; #if 0 doc = xmlParseMemory (data, strlen (data), @@ -446,197 +398,182 @@ static int ascent_xml (const char *data) /* {{{ */ /* encoding = */ NULL, /* options = */ 0); #else - doc = xmlParseMemory (data, strlen (data)); + doc = xmlParseMemory(data, strlen(data)); #endif - if (doc == NULL) - { - ERROR ("ascent plugin: xmlParseMemory failed."); + if (doc == NULL) { + ERROR("ascent plugin: xmlParseMemory failed."); return (-1); } - cur = xmlDocGetRootElement (doc); - if (cur == NULL) - { - ERROR ("ascent plugin: XML document is empty."); - xmlFreeDoc (doc); + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + ERROR("ascent plugin: XML document is empty."); + xmlFreeDoc(doc); return (-1); } - if (xmlStrcmp ((const xmlChar *) "serverpage", cur->name) != 0) - { - ERROR ("ascent plugin: XML root element is not \"serverpage\"."); - xmlFreeDoc (doc); + if (xmlStrcmp((const xmlChar *)"serverpage", cur->name) != 0) { + ERROR("ascent plugin: XML root element is not \"serverpage\"."); + xmlFreeDoc(doc); return (-1); } - for (child = cur->xmlChildrenNode; child != NULL; child = child->next) - { - if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0) - || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0)) + 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)) /* ignore */; - else if (xmlStrcmp ((const xmlChar *) "status", child->name) == 0) - ascent_xml_status (doc, child); - else if (xmlStrcmp ((const xmlChar *) "instances", child->name) == 0) + else if (xmlStrcmp((const xmlChar *)"status", child->name) == 0) + ascent_xml_status(doc, child); + else if (xmlStrcmp((const xmlChar *)"instances", child->name) == 0) /* ignore for now */; - else if (xmlStrcmp ((const xmlChar *) "gms", child->name) == 0) + else if (xmlStrcmp((const xmlChar *)"gms", child->name) == 0) /* ignore for now */; - else if (xmlStrcmp ((const xmlChar *) "sessions", child->name) == 0) - ascent_xml_sessions (doc, child); - else - { - WARNING ("ascent plugin: ascent_xml: Unknown tag: %s", child->name); + else if (xmlStrcmp((const xmlChar *)"sessions", child->name) == 0) + ascent_xml_sessions(doc, child); + else { + WARNING("ascent plugin: ascent_xml: Unknown tag: %s", child->name); } } /* for (child) */ - xmlFreeDoc (doc); + xmlFreeDoc(doc); return (0); } /* }}} int ascent_xml */ -static int config_set (char **var, const char *value) /* {{{ */ +static int config_set(char **var, const char *value) /* {{{ */ { - if (*var != NULL) - { - free (*var); + if (*var != NULL) { + free(*var); *var = NULL; } - if ((*var = strdup (value)) == NULL) + if ((*var = strdup(value)) == NULL) return (1); else return (0); } /* }}} int config_set */ -static int ascent_config (const char *key, const char *value) /* {{{ */ +static int ascent_config(const char *key, const char *value) /* {{{ */ { - if (strcasecmp (key, "URL") == 0) - return (config_set (&url, value)); - else if (strcasecmp (key, "User") == 0) - return (config_set (&user, value)); - else if (strcasecmp (key, "Password") == 0) - return (config_set (&pass, value)); - else if (strcasecmp (key, "VerifyPeer") == 0) - return (config_set (&verify_peer, value)); - else if (strcasecmp (key, "VerifyHost") == 0) - return (config_set (&verify_host, value)); - else if (strcasecmp (key, "CACert") == 0) - return (config_set (&cacert, value)); - else if (strcasecmp (key, "Timeout") == 0) - return (config_set (&timeout, value)); + if (strcasecmp(key, "URL") == 0) + return (config_set(&url, value)); + else if (strcasecmp(key, "User") == 0) + return (config_set(&user, value)); + else if (strcasecmp(key, "Password") == 0) + return (config_set(&pass, value)); + else if (strcasecmp(key, "VerifyPeer") == 0) + return (config_set(&verify_peer, value)); + else if (strcasecmp(key, "VerifyHost") == 0) + return (config_set(&verify_host, value)); + else if (strcasecmp(key, "CACert") == 0) + return (config_set(&cacert, value)); + else if (strcasecmp(key, "Timeout") == 0) + return (config_set(&timeout, value)); else return (-1); } /* }}} int ascent_config */ -static int ascent_init (void) /* {{{ */ +static int ascent_init(void) /* {{{ */ { - if (url == NULL) - { - WARNING ("ascent plugin: ascent_init: No URL configured, " - "returning an error."); + if (url == NULL) { + WARNING("ascent plugin: ascent_init: No URL configured, " + "returning an error."); return (-1); } - if (curl != NULL) - { - curl_easy_cleanup (curl); + if (curl != NULL) { + curl_easy_cleanup(curl); } - if ((curl = curl_easy_init ()) == NULL) - { - ERROR ("ascent plugin: ascent_init: curl_easy_init failed."); + if ((curl = curl_easy_init()) == NULL) { + ERROR("ascent plugin: ascent_init: curl_easy_init failed."); return (-1); } - curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ascent_curl_callback); - curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); - curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, ascent_curl_error); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ascent_curl_callback); + curl_easy_setopt(curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, ascent_curl_error); - if (user != NULL) - { + if (user != NULL) { #ifdef HAVE_CURLOPT_USERNAME - curl_easy_setopt (curl, CURLOPT_USERNAME, user); - curl_easy_setopt (curl, CURLOPT_PASSWORD, (pass == NULL) ? "" : pass); + curl_easy_setopt(curl, CURLOPT_USERNAME, user); + curl_easy_setopt(curl, CURLOPT_PASSWORD, (pass == NULL) ? "" : pass); #else static char credentials[1024]; int status; - status = ssnprintf (credentials, sizeof (credentials), "%s:%s", - user, (pass == NULL) ? "" : pass); - if ((status < 0) || ((size_t) status >= sizeof (credentials))) - { - ERROR ("ascent plugin: ascent_init: Returning an error because the " - "credentials have been truncated."); + status = ssnprintf(credentials, sizeof(credentials), "%s:%s", user, + (pass == NULL) ? "" : pass); + if ((status < 0) || ((size_t)status >= sizeof(credentials))) { + ERROR("ascent plugin: ascent_init: Returning an error because the " + "credentials have been truncated."); return (-1); } - curl_easy_setopt (curl, CURLOPT_USERPWD, credentials); + curl_easy_setopt(curl, CURLOPT_USERPWD, credentials); #endif } - curl_easy_setopt (curl, CURLOPT_URL, url); - curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L); - if ((verify_peer == NULL) || IS_TRUE (verify_peer)) - curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1L); + if ((verify_peer == NULL) || IS_TRUE(verify_peer)) + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); else - curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - if ((verify_host == NULL) || IS_TRUE (verify_host)) - curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2L); + if ((verify_host == NULL) || IS_TRUE(verify_host)) + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); else - curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); if (cacert != NULL) - curl_easy_setopt (curl, CURLOPT_CAINFO, cacert); + curl_easy_setopt(curl, CURLOPT_CAINFO, cacert); #ifdef HAVE_CURLOPT_TIMEOUT_MS if (timeout != NULL) - curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout)); + 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); } /* }}} int ascent_init */ -static int ascent_read (void) /* {{{ */ +static int ascent_read(void) /* {{{ */ { int status; - if (curl == NULL) - { - ERROR ("ascent plugin: I don't have a CURL object."); + if (curl == NULL) { + ERROR("ascent plugin: I don't have a CURL object."); return (-1); } - if (url == NULL) - { - ERROR ("ascent plugin: No URL has been configured."); + if (url == NULL) { + ERROR("ascent plugin: No URL has been configured."); return (-1); } ascent_buffer_fill = 0; - if (curl_easy_perform (curl) != CURLE_OK) - { - ERROR ("ascent plugin: curl_easy_perform failed: %s", - ascent_curl_error); + if (curl_easy_perform(curl) != CURLE_OK) { + ERROR("ascent plugin: curl_easy_perform failed: %s", ascent_curl_error); return (-1); } - status = ascent_xml (ascent_buffer); + status = ascent_xml(ascent_buffer); if (status != 0) return (-1); else return (0); } /* }}} int ascent_read */ -void module_register (void) -{ - plugin_register_config ("ascent", ascent_config, config_keys, config_keys_num); - plugin_register_init ("ascent", ascent_init); - plugin_register_read ("ascent", ascent_read); +void module_register(void) { + plugin_register_config("ascent", ascent_config, config_keys, config_keys_num); + plugin_register_init("ascent", ascent_init); + plugin_register_read("ascent", ascent_read); } /* void module_register */ /* vim: set sw=2 sts=2 ts=8 et fdm=marker : */ diff --git a/src/barometer.c b/src/barometer.c index aaedd70a..29837790 100644 --- a/src/barometer.c +++ b/src/barometer.c @@ -20,187 +20,186 @@ **/ #include "collectd.h" + #include "common.h" -#include "utils_cache.h" #include "plugin.h" +#include "utils_cache.h" -#include #include -#include #include #include +#include +#include +#include /* ------------ MPL115 defines ------------ */ /* I2C address of the MPL115 sensor */ -#define MPL115_I2C_ADDRESS 0x60 +#define MPL115_I2C_ADDRESS 0x60 /* register addresses */ -#define MPL115_ADDR_CONV 0x00 -#define MPL115_ADDR_COEFFS 0x04 +#define MPL115_ADDR_CONV 0x00 +#define MPL115_ADDR_COEFFS 0x04 /* register sizes */ -#define MPL115_NUM_CONV 4 -#define MPL115_NUM_COEFFS 12 +#define MPL115_NUM_CONV 4 +#define MPL115_NUM_COEFFS 12 /* commands / addresses */ -#define MPL115_CMD_CONVERT_PRESS 0x10 -#define MPL115_CMD_CONVERT_TEMP 0x11 -#define MPL115_CMD_CONVERT_BOTH 0x12 - -#define MPL115_CONVERSION_RETRIES 5 +#define MPL115_CMD_CONVERT_PRESS 0x10 +#define MPL115_CMD_CONVERT_TEMP 0x11 +#define MPL115_CMD_CONVERT_BOTH 0x12 +#define MPL115_CONVERSION_RETRIES 5 /* ------------ MPL3115 defines ------------ */ /* MPL3115 I2C address */ -#define MPL3115_I2C_ADDRESS 0x60 +#define MPL3115_I2C_ADDRESS 0x60 /* register addresses (only the interesting ones) */ -#define MPL3115_REG_STATUS 0x00 -#define MPL3115_REG_OUT_P_MSB 0x01 -#define MPL3115_REG_OUT_P_CSB 0x02 -#define MPL3115_REG_OUT_P_LSB 0x03 -#define MPL3115_REG_OUT_T_MSB 0x04 -#define MPL3115_REG_OUT_T_LSB 0x05 -#define MPL3115_REG_DR_STATUS 0x06 -#define MPL3115_REG_WHO_AM_I 0x0C -#define MPL3115_REG_SYSMOD 0x11 -#define MPL3115_REG_PT_DATA_CFG 0x13 -#define MPL3115_REG_BAR_IN_MSB 0x14 -#define MPL3115_REG_BAR_IN_LSB 0x15 -#define MPL3115_REG_CTRL_REG1 0x26 -#define MPL3115_REG_CTRL_REG2 0x27 -#define MPL3115_REG_CTRL_REG3 0x28 -#define MPL3115_REG_CTRL_REG4 0x29 -#define MPL3115_REG_CTRL_REG5 0x2A -#define MPL3115_REG_OFF_P 0x2B -#define MPL3115_REG_OFF_T 0x2C -#define MPL3115_REG_OFF_H 0x2D +#define MPL3115_REG_STATUS 0x00 +#define MPL3115_REG_OUT_P_MSB 0x01 +#define MPL3115_REG_OUT_P_CSB 0x02 +#define MPL3115_REG_OUT_P_LSB 0x03 +#define MPL3115_REG_OUT_T_MSB 0x04 +#define MPL3115_REG_OUT_T_LSB 0x05 +#define MPL3115_REG_DR_STATUS 0x06 +#define MPL3115_REG_WHO_AM_I 0x0C +#define MPL3115_REG_SYSMOD 0x11 +#define MPL3115_REG_PT_DATA_CFG 0x13 +#define MPL3115_REG_BAR_IN_MSB 0x14 +#define MPL3115_REG_BAR_IN_LSB 0x15 +#define MPL3115_REG_CTRL_REG1 0x26 +#define MPL3115_REG_CTRL_REG2 0x27 +#define MPL3115_REG_CTRL_REG3 0x28 +#define MPL3115_REG_CTRL_REG4 0x29 +#define MPL3115_REG_CTRL_REG5 0x2A +#define MPL3115_REG_OFF_P 0x2B +#define MPL3115_REG_OFF_T 0x2C +#define MPL3115_REG_OFF_H 0x2D /* Register values, masks */ -#define MPL3115_WHO_AM_I_RESP 0xC4 - -#define MPL3115_PT_DATA_DREM 0x04 -#define MPL3115_PT_DATA_PDEF 0x02 -#define MPL3115_PT_DATA_TDEF 0x01 - -#define MPL3115_DR_STATUS_TDR 0x02 -#define MPL3115_DR_STATUS_PDR 0x04 -#define MPL3115_DR_STATUS_PTDR 0x08 -#define MPL3115_DR_STATUS_DR (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR) - -#define MPL3115_DR_STATUS_TOW 0x20 -#define MPL3115_DR_STATUS_POW 0x40 -#define MPL3115_DR_STATUS_PTOW 0x80 - -#define MPL3115_CTRL_REG1_ALT 0x80 -#define MPL3115_CTRL_REG1_RAW 0x40 -#define MPL3115_CTRL_REG1_OST_MASK 0x38 -#define MPL3115_CTRL_REG1_OST_1 0x00 -#define MPL3115_CTRL_REG1_OST_2 0x08 -#define MPL3115_CTRL_REG1_OST_4 0x10 -#define MPL3115_CTRL_REG1_OST_8 0x18 -#define MPL3115_CTRL_REG1_OST_16 0x20 -#define MPL3115_CTRL_REG1_OST_32 0x28 -#define MPL3115_CTRL_REG1_OST_64 0x30 -#define MPL3115_CTRL_REG1_OST_128 0x38 -#define MPL3115_CTRL_REG1_RST 0x04 -#define MPL3115_CTRL_REG1_OST 0x02 -#define MPL3115_CTRL_REG1_SBYB 0x01 +#define MPL3115_WHO_AM_I_RESP 0xC4 + +#define MPL3115_PT_DATA_DREM 0x04 +#define MPL3115_PT_DATA_PDEF 0x02 +#define MPL3115_PT_DATA_TDEF 0x01 + +#define MPL3115_DR_STATUS_TDR 0x02 +#define MPL3115_DR_STATUS_PDR 0x04 +#define MPL3115_DR_STATUS_PTDR 0x08 +#define MPL3115_DR_STATUS_DR \ + (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR) + +#define MPL3115_DR_STATUS_TOW 0x20 +#define MPL3115_DR_STATUS_POW 0x40 +#define MPL3115_DR_STATUS_PTOW 0x80 + +#define MPL3115_CTRL_REG1_ALT 0x80 +#define MPL3115_CTRL_REG1_RAW 0x40 +#define MPL3115_CTRL_REG1_OST_MASK 0x38 +#define MPL3115_CTRL_REG1_OST_1 0x00 +#define MPL3115_CTRL_REG1_OST_2 0x08 +#define MPL3115_CTRL_REG1_OST_4 0x10 +#define MPL3115_CTRL_REG1_OST_8 0x18 +#define MPL3115_CTRL_REG1_OST_16 0x20 +#define MPL3115_CTRL_REG1_OST_32 0x28 +#define MPL3115_CTRL_REG1_OST_64 0x30 +#define MPL3115_CTRL_REG1_OST_128 0x38 +#define MPL3115_CTRL_REG1_RST 0x04 +#define MPL3115_CTRL_REG1_OST 0x02 +#define MPL3115_CTRL_REG1_SBYB 0x01 #define MPL3115_CTRL_REG1_SBYB_MASK 0xFE -#define MPL3115_NUM_CONV_VALS 5 - +#define MPL3115_NUM_CONV_VALS 5 /* ------------ BMP085 defines ------------ */ /* I2C address of the BMP085 sensor */ -#define BMP085_I2C_ADDRESS 0x77 +#define BMP085_I2C_ADDRESS 0x77 /* register addresses */ -#define BMP085_ADDR_ID_REG 0xD0 -#define BMP085_ADDR_VERSION 0xD1 +#define BMP085_ADDR_ID_REG 0xD0 +#define BMP085_ADDR_VERSION 0xD1 -#define BMP085_ADDR_CONV 0xF6 +#define BMP085_ADDR_CONV 0xF6 -#define BMP085_ADDR_CTRL_REG 0xF4 -#define BMP085_ADDR_COEFFS 0xAA +#define BMP085_ADDR_CTRL_REG 0xF4 +#define BMP085_ADDR_COEFFS 0xAA /* register sizes */ -#define BMP085_NUM_COEFFS 22 +#define BMP085_NUM_COEFFS 22 /* commands, values */ -#define BMP085_CHIP_ID 0x55 +#define BMP085_CHIP_ID 0x55 -#define BMP085_CMD_CONVERT_TEMP 0x2E +#define BMP085_CMD_CONVERT_TEMP 0x2E -#define BMP085_CMD_CONVERT_PRESS_0 0x34 -#define BMP085_CMD_CONVERT_PRESS_1 0x74 -#define BMP085_CMD_CONVERT_PRESS_2 0xB4 -#define BMP085_CMD_CONVERT_PRESS_3 0xF4 +#define BMP085_CMD_CONVERT_PRESS_0 0x34 +#define BMP085_CMD_CONVERT_PRESS_1 0x74 +#define BMP085_CMD_CONVERT_PRESS_2 0xB4 +#define BMP085_CMD_CONVERT_PRESS_3 0xF4 /* in us */ -#define BMP085_TIME_CNV_TEMP 4500 - -#define BMP085_TIME_CNV_PRESS_0 4500 -#define BMP085_TIME_CNV_PRESS_1 7500 -#define BMP085_TIME_CNV_PRESS_2 13500 -#define BMP085_TIME_CNV_PRESS_3 25500 +#define BMP085_TIME_CNV_TEMP 4500 +#define BMP085_TIME_CNV_PRESS_0 4500 +#define BMP085_TIME_CNV_PRESS_1 7500 +#define BMP085_TIME_CNV_PRESS_2 13500 +#define BMP085_TIME_CNV_PRESS_3 25500 /* ------------ Normalization ------------ */ /* Mean sea level pressure normalization methods */ -#define MSLP_NONE 0 +#define MSLP_NONE 0 #define MSLP_INTERNATIONAL 1 -#define MSLP_DEU_WETT 2 - -/** Temperature reference history depth for averaging. See #get_reference_temperature */ -#define REF_TEMP_AVG_NUM 5 +#define MSLP_DEU_WETT 2 +/** Temperature reference history depth for averaging. See + * #get_reference_temperature */ +#define REF_TEMP_AVG_NUM 5 /* ------------------------------------------ */ /** Supported sensor types */ enum Sensor_type { - Sensor_none = 0, - Sensor_MPL115, - Sensor_MPL3115, - Sensor_BMP085 + Sensor_none = 0, + Sensor_MPL115, + Sensor_MPL3115, + Sensor_BMP085 }; -static const char *config_keys[] = -{ +static const char *config_keys[] = { "Device", "Oversampling", "PressureOffset", /**< only for MPL3115 */ "TemperatureOffset", /**< only for MPL3115 */ "Altitude", "Normalization", - "TemperatureSensor" -}; + "TemperatureSensor"}; -static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); +static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static char * config_device = NULL; /**< I2C bus device */ -static int config_oversample = 1; /**< averaging window */ +static char *config_device = NULL; /**< I2C bus device */ +static int config_oversample = 1; /**< averaging window */ -static double config_press_offset = 0.0; /**< pressure offset */ -static double config_temp_offset = 0.0; /**< temperature offset */ +static double config_press_offset = 0.0; /**< pressure offset */ +static double config_temp_offset = 0.0; /**< temperature offset */ -static double config_altitude = NAN; /**< altitude */ -static int config_normalize = 0; /**< normalization method */ +static double config_altitude = NAN; /**< altitude */ +static int config_normalize = 0; /**< normalization method */ -static _Bool configured = 0; /**< the whole plugin config status */ +static _Bool configured = 0; /**< the whole plugin config status */ -static int i2c_bus_fd = -1; /**< I2C bus device FD */ +static int i2c_bus_fd = -1; /**< I2C bus device FD */ -static enum Sensor_type sensor_type = Sensor_none; /**< detected/used sensor type */ +static enum Sensor_type sensor_type = + Sensor_none; /**< detected/used sensor type */ -static __s32 mpl3115_oversample = 0; /**< MPL3115 CTRL1 oversample setting */ +static __s32 mpl3115_oversample = 0; /**< MPL3115 CTRL1 oversample setting */ // BMP085 configuration -static unsigned bmp085_oversampling; /**< BMP085 oversampling (0-3) */ -static unsigned long bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */ -static __u8 bmp085_cmdCnvPress; /**< BMP085 pressure conversion command */ - +static unsigned bmp085_oversampling; /**< BMP085 oversampling (0-3) */ +static unsigned long + bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */ +static __u8 bmp085_cmdCnvPress; /**< BMP085 pressure conversion command */ /* MPL115 conversion coefficients */ static double mpl115_coeffA0; @@ -223,25 +222,21 @@ static short bmp085_MB; static short bmp085_MC; static short bmp085_MD; - - /* ------------------------ averaging ring buffer ------------------------ */ /* Used only for MPL115. MPL3115 supports real oversampling in the device so */ /* no need for any postprocessing. */ -static _Bool avg_initialized = 0; /**< already initialized by real values */ +static _Bool avg_initialized = 0; /**< already initialized by real values */ typedef struct averaging_s { - long int * ring_buffer; - int ring_buffer_size; - long int ring_buffer_sum; - int ring_buffer_head; + long int *ring_buffer; + int ring_buffer_size; + long int ring_buffer_sum; + int ring_buffer_head; } averaging_t; - -static averaging_t pressure_averaging = { NULL, 0, 0L, 0 }; -static averaging_t temperature_averaging = { NULL, 0, 0L, 0 }; - +static averaging_t pressure_averaging = {NULL, 0, 0L, 0}; +static averaging_t temperature_averaging = {NULL, 0, 0L, 0}; /** * Create / allocate averaging buffer @@ -253,42 +248,37 @@ static averaging_t temperature_averaging = { NULL, 0, 0L, 0 }; * * @return Zero when successful */ -static int averaging_create(averaging_t *avg, int size) -{ - avg->ring_buffer = calloc ((size_t) size, sizeof (*avg->ring_buffer)); - if (avg->ring_buffer == NULL) - { - ERROR ("barometer: averaging_create - ring buffer allocation of size %d failed", - size); - return -1; - } - - avg->ring_buffer_size = size; - avg->ring_buffer_sum = 0L; - avg->ring_buffer_head = 0; - - return 0; +static int averaging_create(averaging_t *avg, int size) { + avg->ring_buffer = calloc((size_t)size, sizeof(*avg->ring_buffer)); + if (avg->ring_buffer == NULL) { + ERROR("barometer: averaging_create - ring buffer allocation of size %d " + "failed", + size); + return -1; + } + + avg->ring_buffer_size = size; + avg->ring_buffer_sum = 0L; + avg->ring_buffer_head = 0; + + return 0; } - /** * Delete / free existing averaging buffer * * @param avg pointer to the ring buffer to be deleted */ -static void averaging_delete(averaging_t * avg) -{ - if (avg->ring_buffer != NULL) - { - free(avg->ring_buffer); - avg->ring_buffer = NULL; - } - avg->ring_buffer_size = 0; - avg->ring_buffer_sum = 0L; - avg->ring_buffer_head = 0; +static void averaging_delete(averaging_t *avg) { + if (avg->ring_buffer != NULL) { + free(avg->ring_buffer); + avg->ring_buffer = NULL; + } + avg->ring_buffer_size = 0; + avg->ring_buffer_sum = 0L; + avg->ring_buffer_head = 0; } - /* * Add new sample to the averaging buffer * @@ -301,37 +291,33 @@ static void averaging_delete(averaging_t * avg) * * @return Averaged sample value */ -static double averaging_add_sample(averaging_t * avg, long int sample) -{ - double result; +static double averaging_add_sample(averaging_t *avg, long int sample) { + double result; - avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head]; - avg->ring_buffer[avg->ring_buffer_head] = sample; - avg->ring_buffer_head = (avg->ring_buffer_head+1) % avg->ring_buffer_size; - result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size); + avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head]; + avg->ring_buffer[avg->ring_buffer_head] = sample; + avg->ring_buffer_head = (avg->ring_buffer_head + 1) % avg->ring_buffer_size; + result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size); - DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf", - sample, - result); + DEBUG("barometer: averaging_add_sample - added %ld, result = %lf", sample, + result); - return result; + return result; } - /* ------------------------ temperature refference ------------------------ */ /** * Linked list type of temperature sensor references */ typedef struct temperature_list_s { - char * sensor_name; /**< sensor name/reference */ - size_t num_values; /**< number of values (usually one) */ - _Bool initialized; /**< sensor already provides data */ - struct temperature_list_s * next; /**< next in the list */ + char *sensor_name; /**< sensor name/reference */ + size_t num_values; /**< number of values (usually one) */ + _Bool initialized; /**< sensor already provides data */ + struct temperature_list_s *next; /**< next in the list */ } temperature_list_t; -static temperature_list_t * temp_list = NULL; - +static temperature_list_t *temp_list = NULL; /* * Add new sensor to the temperature reference list @@ -341,209 +327,177 @@ static temperature_list_t * temp_list = NULL; * * @return Zero when successful */ -static int temp_list_add(temperature_list_t * list, const char * sensor) -{ - temperature_list_t * new_temp; - - new_temp = (temperature_list_t *) malloc(sizeof(*new_temp)); - if(new_temp == NULL) - return -1; - - new_temp->sensor_name = strdup(sensor); - new_temp->initialized = 0; - new_temp->num_values = 0; - if(new_temp->sensor_name == NULL) - { - free(new_temp); - return -1; - } - - new_temp->next = temp_list; - temp_list = new_temp; - return 0; +static int temp_list_add(temperature_list_t *list, const char *sensor) { + temperature_list_t *new_temp; + + new_temp = malloc(sizeof(*new_temp)); + if (new_temp == NULL) + return -1; + + new_temp->sensor_name = strdup(sensor); + new_temp->initialized = 0; + new_temp->num_values = 0; + if (new_temp->sensor_name == NULL) { + free(new_temp); + return -1; + } + + new_temp->next = temp_list; + temp_list = new_temp; + return 0; } - /* * Delete the whole temperature reference list * * @param list the list to be deleted */ -static void temp_list_delete(temperature_list_t ** list) -{ - temperature_list_t * tmp; - - while (*list != NULL) - { - tmp = (*list); - (*list) = (*list)->next; - free(tmp->sensor_name); - free(tmp); - tmp = NULL; - } +static void temp_list_delete(temperature_list_t **list) { + temperature_list_t *tmp; + + while (*list != NULL) { + tmp = (*list); + (*list) = (*list)->next; + free(tmp->sensor_name); + free(tmp); + tmp = NULL; + } } - /* * Get reference temperature value * - * First initially uc_get_rate_by_name is tried. At the startup due to nondeterministic - * order the temperature may not be read yet (then it fails and first measurment gives - * only absolute air pressure reading which is acceptable). Once it succedes (should be - * second measurement at the latest) we use average of few last readings from - * uc_get_history_by_name. It may take few readings to start filling so again we use - * uc_get_rate_by_name as a fallback. - * The idea is to use basic "noise" filtering (history averaging) across all the values - * which given sensor provides (up to given depth). Then we get minimum among - * the sensors. + * First initially uc_get_rate_by_name is tried. At the startup due to + * nondeterministic order the temperature may not be read yet (then it fails and + * first measurment gives only absolute air pressure reading which is + * acceptable). Once it succedes (should be second measurement at the latest) we + * use average of few last readings from uc_get_history_by_name. It may take few + * readings to start filling so again we use uc_get_rate_by_name as a fallback. + * The idea is to use basic "noise" filtering (history averaging) across all the + * values which given sensor provides (up to given depth). Then we get minimum + * among the sensors. * * @param result where the result is stored. When not available NAN is stored. * * @return Zero when successful */ -static int get_reference_temperature(double * result) -{ - temperature_list_t * list = temp_list; +static int get_reference_temperature(double *result) { + temperature_list_t *list = temp_list; - gauge_t * values = NULL; /**< rate values */ - size_t values_num = 0; /**< number of rate values */ - int i; + gauge_t *values = NULL; /**< rate values */ + size_t values_num = 0; /**< number of rate values */ - gauge_t values_history[REF_TEMP_AVG_NUM]; + gauge_t values_history[REF_TEMP_AVG_NUM]; - double avg_sum; /**< Value sum for computing average */ - int avg_num; /**< Number of values for computing average */ - double average; /**< Resulting value average */ + double avg_sum; /**< Value sum for computing average */ + int avg_num; /**< Number of values for computing average */ + double average; /**< Resulting value average */ - *result = NAN; + *result = NAN; - while(list != NULL) - { - avg_sum = 0.0; - avg_num = 0; - - /* First time need to read current rate to learn how many values are - there (typically for temperature it would be just one). - We do not expect dynamic changing of number of temperarure values - in runtime yet (are there any such cases?). */ - if(!list->initialized) - { - if(uc_get_rate_by_name(list->sensor_name, - &values, - &values_num)) - { - DEBUG ("barometer: get_reference_temperature - rate \"%s\" not found yet", - list->sensor_name); - list = list->next; - continue; - } - - DEBUG ("barometer: get_reference_temperature - initialize \"%s\", %zu vals", - list->sensor_name, - values_num); - - list->initialized = 1; - list->num_values = values_num; - - for(i=0; isensor_name, - values_history, - REF_TEMP_AVG_NUM, - list->num_values)) - { - ERROR ("barometer: get_reference_temperature - history \"%s\" lost", - list->sensor_name); - list->initialized = 0; - list->num_values = 0; - list = list->next; - continue; - } - - for(i=0; inum_values; ++i) - { - DEBUG ("barometer: get_reference_temperature - history %d: %lf", - i, - values_history[i]); - if(!isnan(values_history[i])) - { - avg_sum += values_history[i]; - ++avg_num; - } - } - - if(avg_num == 0) /* still no history? fallback to current */ - { - if(uc_get_rate_by_name(list->sensor_name, - &values, - &values_num)) - { - ERROR ("barometer: get_reference_temperature - rate \"%s\" lost", - list->sensor_name); - list->initialized = 0; - list->num_values = 0; - list = list->next; - continue; - } - - for(i=0; isensor_name); - list->initialized = 0; - list->num_values = 0; - } - else - { - average = avg_sum / (double) avg_num; - if(isnan(*result)) - *result=average; - else if(*result>average) - *result=average; + /* First time need to read current rate to learn how many values are + there (typically for temperature it would be just one). We do not expect + dynamic changing of number of temperarure values in runtime yet (are + there any such cases?). */ + if (!list->initialized) { + if (uc_get_rate_by_name(list->sensor_name, &values, &values_num)) { + DEBUG( + "barometer: get_reference_temperature - rate \"%s\" not found yet", + list->sensor_name); + list = list->next; + continue; + } + + DEBUG( + "barometer: get_reference_temperature - initialize \"%s\", %zu vals", + list->sensor_name, values_num); + + list->initialized = 1; + list->num_values = values_num; + + for (size_t i = 0; i < values_num; ++i) { + DEBUG("barometer: get_reference_temperature - rate %zu: %lf **", i, + values[i]); + if (!isnan(values[i])) { + avg_sum += values[i]; + ++avg_num; } + } + free(values); + values = NULL; + } + + /* It is OK to get here the first time as well, in the worst case + the history will full of NANs. */ + if (uc_get_history_by_name(list->sensor_name, values_history, + REF_TEMP_AVG_NUM, list->num_values)) { + ERROR("barometer: get_reference_temperature - history \"%s\" lost", + list->sensor_name); + list->initialized = 0; + list->num_values = 0; + list = list->next; + continue; + } + + for (size_t i = 0; i < REF_TEMP_AVG_NUM * list->num_values; ++i) { + DEBUG("barometer: get_reference_temperature - history %zu: %lf", i, + values_history[i]); + if (!isnan(values_history[i])) { + avg_sum += values_history[i]; + ++avg_num; + } + } + + if (avg_num == 0) /* still no history? fallback to current */ + { + if (uc_get_rate_by_name(list->sensor_name, &values, &values_num)) { + ERROR("barometer: get_reference_temperature - rate \"%s\" lost", + list->sensor_name); + list->initialized = 0; + list->num_values = 0; list = list->next; - } /* while sensor list */ - - if(*result == NAN) - { - ERROR("barometer: get_reference_temperature - no sensor available (yet?)"); - return -1; - } - DEBUG ("barometer: get_reference_temperature - temp is %lf", *result); - return 0; + continue; + } + + for (size_t i = 0; i < values_num; ++i) { + DEBUG("barometer: get_reference_temperature - rate last %zu: %lf **", i, + values[i]); + if (!isnan(values[i])) { + avg_sum += values[i]; + ++avg_num; + } + } + free(values); + values = NULL; + } + + if (avg_num == 0) { + ERROR("barometer: get_reference_temperature - could not read \"%s\"", + list->sensor_name); + list->initialized = 0; + list->num_values = 0; + } else { + average = avg_sum / (double)avg_num; + if (isnan(*result)) + *result = average; + else if (*result > average) + *result = average; + } + list = list->next; + } /* while sensor list */ + + if (*result == NAN) { + ERROR("barometer: get_reference_temperature - no sensor available (yet?)"); + return -1; + } + DEBUG("barometer: get_reference_temperature - temp is %lf", *result); + return 0; } - /* ------------------------ MPL115 access ------------------------ */ /** @@ -551,34 +505,32 @@ static int get_reference_temperature(double * result) * * Unfortunately there seems to be no ID register so we just try to read first * conversion coefficient from device at MPL115 address and hope it is really - * MPL115. We should use this check as the last resort (which would be the typical + * MPL115. We should use this check as the last resort (which would be the + * typical * case anyway since MPL115 is the least accurate sensor). * As a sideeffect will leave set I2C slave address. * * @return 1 if MPL115, 0 otherwise */ -static int MPL115_detect(void) -{ - __s32 res; - char errbuf[1024]; - - if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0) - { - ERROR("barometer: MPL115_detect problem setting i2c slave address to 0x%02X: %s", - MPL115_I2C_ADDRESS, - sstrerror (errno, errbuf, sizeof (errbuf))); - return 0 ; - } +static int MPL115_detect(void) { + __s32 res; + char errbuf[1024]; + + if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0) { + ERROR("barometer: MPL115_detect problem setting i2c slave address to " + "0x%02X: %s", + MPL115_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf))); + return 0; + } - res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS); - if(res >= 0) - { - DEBUG ("barometer: MPL115_detect - positive detection"); - return 1; - } + res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS); + if (res >= 0) { + DEBUG("barometer: MPL115_detect - positive detection"); + return 1; + } - DEBUG ("barometer: MPL115_detect - negative detection"); - return 0; + DEBUG("barometer: MPL115_detect - negative detection"); + return 0; } /** @@ -588,91 +540,84 @@ static int MPL115_detect(void) * * @return Zero when successful */ -static int MPL115_read_coeffs(void) -{ - uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = { 0 }; - int32_t res; - - int8_t sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB; - int8_t sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB; - int16_t sia0, sib1, sib2, sic12, sic11, sic22; - - char errbuf[1024]; - - res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, - MPL115_ADDR_COEFFS, - STATIC_ARRAY_SIZE (mpl115_coeffs), - mpl115_coeffs); - if (res < 0) - { - ERROR ("barometer: MPL115_read_coeffs - problem reading data: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - - /* Using perhaps less elegant/efficient code, but more readable. */ - /* a0: 16total 1sign 12int 4fract 0pad */ - sia0MSB = mpl115_coeffs[0]; - sia0LSB = mpl115_coeffs[1]; - sia0 = (int16_t) sia0MSB <<8; /* s16 type, Shift to MSB */ - sia0 += (int16_t) sia0LSB & 0x00FF; /* Add LSB to 16bit number */ - mpl115_coeffA0 = (double) (sia0); - mpl115_coeffA0 /= 8.0; /* 3 fract bits */ - - /* b1: 16total 1sign 2int 13fract 0pad */ - sib1MSB= mpl115_coeffs[2]; - sib1LSB= mpl115_coeffs[3]; - sib1 = sib1MSB <<8; /* Shift to MSB */ - sib1 += sib1LSB & 0x00FF; /* Add LSB to 16bit number */ - mpl115_coeffB1 = (double) (sib1); - mpl115_coeffB1 /= 8192.0; /* 13 fract */ - - /* b2: 16total 1sign 1int 14fract 0pad */ - sib2MSB= mpl115_coeffs[4]; - sib2LSB= mpl115_coeffs[5]; - sib2 = sib2MSB <<8; /* Shift to MSB */ - sib2 += sib2LSB & 0x00FF; /* Add LSB to 16bit number */ - mpl115_coeffB2 = (double) (sib2); - mpl115_coeffB2 /= 16384.0; /* 14 fract */ - - /* c12: 14total 1sign 0int 13fract 9pad */ - sic12MSB= mpl115_coeffs[6]; - sic12LSB= mpl115_coeffs[7]; - sic12 = sic12MSB <<8; /* Shift to MSB only by 8 for MSB */ - sic12 += sic12LSB & 0x00FF; - mpl115_coeffC12 = (double) (sic12); - mpl115_coeffC12 /= 4.0; /* 16-14=2 */ - mpl115_coeffC12 /= 4194304.0; /* 13+9=22 fract */ - - /* c11: 11total 1sign 0int 11fract 11pad */ - sic11MSB= mpl115_coeffs[8]; - sic11LSB= mpl115_coeffs[9]; - sic11 = sic11MSB <<8; /* Shift to MSB only by 8 for MSB */ - sic11 += sic11LSB & 0x00FF; - mpl115_coeffC11 = (double) (sic11); - mpl115_coeffC11 /= 32.0; /* 16-11=5 */ - mpl115_coeffC11 /= 4194304.0; /* 11+11=22 fract */ - - /* c12: 11total 1sign 0int 10fract 15pad */ - sic22MSB= mpl115_coeffs[10]; - sic22LSB= mpl115_coeffs[11]; - sic22 = sic22MSB <<8; /* Shift to MSB only by 8 for MSB */ - sic22 += sic22LSB & 0x00FF; - mpl115_coeffC22 = (double) (sic22); - mpl115_coeffC22 /= 32.0; //16-11=5 - mpl115_coeffC22 /= 33554432.0; /* 10+15=25 fract */ - - DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf", - mpl115_coeffA0, - mpl115_coeffB1, - mpl115_coeffB2, - mpl115_coeffC12, - mpl115_coeffC11, - mpl115_coeffC22); - return 0; +static int MPL115_read_coeffs(void) { + uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = {0}; + int32_t res; + + int8_t sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB; + int8_t sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB; + int16_t sia0, sib1, sib2, sic12, sic11, sic22; + + char errbuf[1024]; + + res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL115_ADDR_COEFFS, + STATIC_ARRAY_SIZE(mpl115_coeffs), + mpl115_coeffs); + if (res < 0) { + ERROR("barometer: MPL115_read_coeffs - problem reading data: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + + /* Using perhaps less elegant/efficient code, but more readable. */ + /* a0: 16total 1sign 12int 4fract 0pad */ + sia0MSB = mpl115_coeffs[0]; + sia0LSB = mpl115_coeffs[1]; + sia0 = (int16_t)sia0MSB << 8; /* s16 type, Shift to MSB */ + sia0 += (int16_t)sia0LSB & 0x00FF; /* Add LSB to 16bit number */ + mpl115_coeffA0 = (double)(sia0); + mpl115_coeffA0 /= 8.0; /* 3 fract bits */ + + /* b1: 16total 1sign 2int 13fract 0pad */ + sib1MSB = mpl115_coeffs[2]; + sib1LSB = mpl115_coeffs[3]; + sib1 = sib1MSB << 8; /* Shift to MSB */ + sib1 += sib1LSB & 0x00FF; /* Add LSB to 16bit number */ + mpl115_coeffB1 = (double)(sib1); + mpl115_coeffB1 /= 8192.0; /* 13 fract */ + + /* b2: 16total 1sign 1int 14fract 0pad */ + sib2MSB = mpl115_coeffs[4]; + sib2LSB = mpl115_coeffs[5]; + sib2 = sib2MSB << 8; /* Shift to MSB */ + sib2 += sib2LSB & 0x00FF; /* Add LSB to 16bit number */ + mpl115_coeffB2 = (double)(sib2); + mpl115_coeffB2 /= 16384.0; /* 14 fract */ + + /* c12: 14total 1sign 0int 13fract 9pad */ + sic12MSB = mpl115_coeffs[6]; + sic12LSB = mpl115_coeffs[7]; + sic12 = sic12MSB << 8; /* Shift to MSB only by 8 for MSB */ + sic12 += sic12LSB & 0x00FF; + mpl115_coeffC12 = (double)(sic12); + mpl115_coeffC12 /= 4.0; /* 16-14=2 */ + mpl115_coeffC12 /= 4194304.0; /* 13+9=22 fract */ + + /* c11: 11total 1sign 0int 11fract 11pad */ + sic11MSB = mpl115_coeffs[8]; + sic11LSB = mpl115_coeffs[9]; + sic11 = sic11MSB << 8; /* Shift to MSB only by 8 for MSB */ + sic11 += sic11LSB & 0x00FF; + mpl115_coeffC11 = (double)(sic11); + mpl115_coeffC11 /= 32.0; /* 16-11=5 */ + mpl115_coeffC11 /= 4194304.0; /* 11+11=22 fract */ + + /* c12: 11total 1sign 0int 10fract 15pad */ + sic22MSB = mpl115_coeffs[10]; + sic22LSB = mpl115_coeffs[11]; + sic22 = sic22MSB << 8; /* Shift to MSB only by 8 for MSB */ + sic22 += sic22LSB & 0x00FF; + mpl115_coeffC22 = (double)(sic22); + mpl115_coeffC22 /= 32.0; // 16-11=5 + mpl115_coeffC22 /= 33554432.0; /* 10+15=25 fract */ + + DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, " + "c11=%lf, c22=%lf", + mpl115_coeffA0, mpl115_coeffB1, mpl115_coeffB2, mpl115_coeffC12, + mpl115_coeffC11, mpl115_coeffC22); + return 0; } - /** * Convert raw adc values to real data using the sensor coefficients. * @@ -681,24 +626,21 @@ static int MPL115_read_coeffs(void) * @param pressure computed real pressure * @param temperature computed real temperature */ -static void MPL115_convert_adc_to_real(double adc_pressure, - double adc_temp, - double * pressure, - double * temperature) -{ - double Pcomp; - Pcomp = mpl115_coeffA0 + \ - (mpl115_coeffB1 + mpl115_coeffC11*adc_pressure + mpl115_coeffC12*adc_temp) * adc_pressure + \ - (mpl115_coeffB2 + mpl115_coeffC22*adc_temp) * adc_temp; - - *pressure = ((1150.0-500.0) * Pcomp / 1023.0) + 500.0; - *temperature = (472.0 - adc_temp) / 5.35 + 25.0; - DEBUG ("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C", - *pressure, - *temperature); +static void MPL115_convert_adc_to_real(double adc_pressure, double adc_temp, + double *pressure, double *temperature) { + double Pcomp; + Pcomp = mpl115_coeffA0 + + (mpl115_coeffB1 + mpl115_coeffC11 * adc_pressure + + mpl115_coeffC12 * adc_temp) * + adc_pressure + + (mpl115_coeffB2 + mpl115_coeffC22 * adc_temp) * adc_temp; + + *pressure = ((1150.0 - 500.0) * Pcomp / 1023.0) + 500.0; + *temperature = (472.0 - adc_temp) / 5.35 + 25.0; + DEBUG("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C", *pressure, + *temperature); } - /** * Read sensor averegaed measurements * @@ -707,97 +649,82 @@ static void MPL115_convert_adc_to_real(double adc_pressure, * * @return Zero when successful */ -static int MPL115_read_averaged(double * pressure, double * temperature) -{ - uint8_t mpl115_conv[MPL115_NUM_CONV] = { 0 }; - int8_t res; - int retries; - int conv_pressure; - int conv_temperature; - double adc_pressure; - double adc_temperature; - char errbuf[1024]; - - *pressure = 0.0; - *temperature = 0.0; - - /* start conversion of both temp and presure */ - retries = MPL115_CONVERSION_RETRIES; - while (retries>0) - { - /* write 1 to start conversion */ - res = i2c_smbus_write_byte_data (i2c_bus_fd, - MPL115_CMD_CONVERT_BOTH, - 0x01); - if (res >= 0) - break; - - --retries; - if(retries>0) - { - ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, " \ - "will retry at most %d more times", - sstrerror (errno, errbuf, sizeof (errbuf)), - retries); - } - else - { - ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, "\ - "too many failed retries", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - } - - usleep (10000); /* wait 10ms for the conversion */ - - retries=MPL115_CONVERSION_RETRIES; - while (retries>0) - { - res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, - MPL115_ADDR_CONV, - STATIC_ARRAY_SIZE (mpl115_conv), - mpl115_conv); - if (res >= 0) - break; - - --retries; - if (retries>0) - { - ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \ - "will retry at most %d more times", - sstrerror (errno, errbuf, sizeof (errbuf)), - retries); - } - else - { - ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \ - "too many failed retries", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - } - - conv_pressure = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6; - conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6; - DEBUG ("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " \ - "raw temperature ADC value = %d", - conv_pressure, - conv_temperature); - - adc_pressure = averaging_add_sample (&pressure_averaging, conv_pressure); - adc_temperature = averaging_add_sample (&temperature_averaging, conv_temperature); - - MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature); - - DEBUG ("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / temperature = %lf, " \ - "real pressure = %lf hPa / temperature = %lf C", - adc_pressure, - adc_temperature, - *pressure, - *temperature); - - return 0; +static int MPL115_read_averaged(double *pressure, double *temperature) { + uint8_t mpl115_conv[MPL115_NUM_CONV] = {0}; + int8_t res; + int retries; + int conv_pressure; + int conv_temperature; + double adc_pressure; + double adc_temperature; + char errbuf[1024]; + + *pressure = 0.0; + *temperature = 0.0; + + /* start conversion of both temp and presure */ + retries = MPL115_CONVERSION_RETRIES; + while (retries > 0) { + /* write 1 to start conversion */ + res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL115_CMD_CONVERT_BOTH, 0x01); + if (res >= 0) + break; + + --retries; + if (retries > 0) { + ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, " + "will retry at most %d more times", + sstrerror(errno, errbuf, sizeof(errbuf)), retries); + } else { + ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, " + "too many failed retries", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + } + + usleep(10000); /* wait 10ms for the conversion */ + + retries = MPL115_CONVERSION_RETRIES; + while (retries > 0) { + res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL115_ADDR_CONV, + STATIC_ARRAY_SIZE(mpl115_conv), + mpl115_conv); + if (res >= 0) + break; + + --retries; + if (retries > 0) { + ERROR("barometer: MPL115_read_averaged - reading conversion: %s, " + "will retry at most %d more times", + sstrerror(errno, errbuf, sizeof(errbuf)), retries); + } else { + ERROR("barometer: MPL115_read_averaged - reading conversion: %s, " + "too many failed retries", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + } + + conv_pressure = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6; + conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6; + DEBUG("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " + "raw temperature ADC value = %d", + conv_pressure, conv_temperature); + + adc_pressure = averaging_add_sample(&pressure_averaging, conv_pressure); + adc_temperature = + averaging_add_sample(&temperature_averaging, conv_temperature); + + MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure, + temperature); + + DEBUG("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / " + "temperature = %lf, " + "real pressure = %lf hPa / temperature = %lf C", + adc_pressure, adc_temperature, *pressure, *temperature); + + return 0; } /* ------------------------ MPL3115 access ------------------------ */ @@ -809,28 +736,25 @@ static int MPL115_read_averaged(double * pressure, double * temperature) * * @return 1 if MPL3115, 0 otherwise */ -static int MPL3115_detect(void) -{ - __s32 res; - char errbuf[1024]; - - if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0) - { - ERROR("barometer: MPL3115_detect problem setting i2c slave address to 0x%02X: %s", - MPL3115_I2C_ADDRESS, - sstrerror (errno, errbuf, sizeof (errbuf))); - return 0 ; - } +static int MPL3115_detect(void) { + __s32 res; + char errbuf[1024]; + + if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0) { + ERROR("barometer: MPL3115_detect problem setting i2c slave address to " + "0x%02X: %s", + MPL3115_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf))); + return 0; + } - res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I); - if(res == MPL3115_WHO_AM_I_RESP) - { - DEBUG ("barometer: MPL3115_detect - positive detection"); - return 1; - } + res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I); + if (res == MPL3115_WHO_AM_I_RESP) { + DEBUG("barometer: MPL3115_detect - positive detection"); + return 1; + } - DEBUG ("barometer: MPL3115_detect - negative detection"); - return 0; + DEBUG("barometer: MPL3115_detect - negative detection"); + return 0; } /** @@ -838,55 +762,39 @@ static int MPL3115_detect(void) * * MPL3115 supports only power of 2 in the range 1 to 128. */ -static void MPL3115_adjust_oversampling(void) -{ - int new_val = 0; - - if(config_oversample > 100) - { - new_val = 128; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_128; - } - else if(config_oversample > 48) - { - new_val = 64; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_64; - } - else if(config_oversample > 24) - { - new_val = 32; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_32; - } - else if(config_oversample > 12) - { - new_val = 16; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_16; - } - else if(config_oversample > 6) - { - new_val = 8; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_8; - } - else if(config_oversample > 3) - { - new_val = 4; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_4; - } - else if(config_oversample > 1) - { - new_val = 2; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_2; - } - else - { - new_val = 1; - mpl3115_oversample = MPL3115_CTRL_REG1_OST_1; - } - - DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from %d to %d", - config_oversample, - new_val); - config_oversample = new_val; +static void MPL3115_adjust_oversampling(void) { + int new_val = 0; + + if (config_oversample > 100) { + new_val = 128; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_128; + } else if (config_oversample > 48) { + new_val = 64; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_64; + } else if (config_oversample > 24) { + new_val = 32; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_32; + } else if (config_oversample > 12) { + new_val = 16; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_16; + } else if (config_oversample > 6) { + new_val = 8; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_8; + } else if (config_oversample > 3) { + new_val = 4; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_4; + } else if (config_oversample > 1) { + new_val = 2; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_2; + } else { + new_val = 1; + mpl3115_oversample = MPL3115_CTRL_REG1_OST_1; + } + + DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from " + "%d to %d", + config_oversample, new_val); + config_oversample = new_val; } /** @@ -897,91 +805,79 @@ static void MPL3115_adjust_oversampling(void) * * @return Zero when successful */ -static int MPL3115_read(double * pressure, double * temperature) -{ - __s32 res; - __s32 ctrl ; - __u8 data[MPL3115_NUM_CONV_VALS]; - long int tmp_value = 0; - char errbuf[1024]; - - /* Set Active - activate the device from standby */ - res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1); - if (res < 0) - { - ERROR ("barometer: MPL3115_read - cannot read CTRL_REG1: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - ctrl = res; - res = i2c_smbus_write_byte_data(i2c_bus_fd, - MPL3115_REG_CTRL_REG1, - ctrl | MPL3115_CTRL_REG1_SBYB); - if (res < 0) - { - ERROR ("barometer: MPL3115_read - problem activating: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - /* base sleep is 5ms x OST */ - usleep(5000 * config_oversample); - - /* check the flags/status if ready */ +static int MPL3115_read(double *pressure, double *temperature) { + __s32 res; + __s32 ctrl; + __u8 data[MPL3115_NUM_CONV_VALS]; + long int tmp_value = 0; + char errbuf[1024]; + + /* Set Active - activate the device from standby */ + res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1); + if (res < 0) { + ERROR("barometer: MPL3115_read - cannot read CTRL_REG1: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + ctrl = res; + res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1, + ctrl | MPL3115_CTRL_REG1_SBYB); + if (res < 0) { + ERROR("barometer: MPL3115_read - problem activating: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + /* base sleep is 5ms x OST */ + usleep(5000 * config_oversample); + + /* check the flags/status if ready */ + res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS); + if (res < 0) { + ERROR("barometer: MPL3115_read - cannot read status register: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR) { + /* try some extra sleep... */ + usleep(10000); + + /* ... and repeat the check. The conversion has to finish sooner or later. + */ res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS); - if (res < 0) - { - ERROR ("barometer: MPL3115_read - cannot read status register: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR) - { - /* try some extra sleep... */ - usleep(10000); - - /* ... and repeat the check. The conversion has to finish sooner or later. */ - res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS); - if (res < 0) - { - ERROR ("barometer: MPL3115_read - cannot read status register: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - } - - /* Now read all the data in one block. There is address autoincrement. */ - res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, - MPL3115_REG_OUT_P_MSB, - MPL3115_NUM_CONV_VALS, - data); - if (res < 0) - { - ERROR ("barometer: MPL3115_read - cannot read data registers: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - tmp_value = (data[0] << 16) | (data[1] << 8) | data[2]; - *pressure = ((double) tmp_value) / 4.0 / 16.0 / 100.0; - DEBUG ("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure); - - if(data[3] > 0x7F) - { - data[3] = ~data[3] + 1; - *temperature = data[3]; - *temperature = - *temperature; - } - else - { - *temperature = data[3]; - } - - *temperature += (double)(data[4]) / 256.0; - DEBUG ("barometer: MPL3115_read - temperature = %lf C", *temperature); - - return 0; + if (res < 0) { + ERROR("barometer: MPL3115_read - cannot read status register: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + } + + /* Now read all the data in one block. There is address autoincrement. */ + res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL3115_REG_OUT_P_MSB, + MPL3115_NUM_CONV_VALS, data); + if (res < 0) { + ERROR("barometer: MPL3115_read - cannot read data registers: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + tmp_value = (data[0] << 16) | (data[1] << 8) | data[2]; + *pressure = ((double)tmp_value) / 4.0 / 16.0 / 100.0; + DEBUG("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure); + + if (data[3] > 0x7F) { + data[3] = ~data[3] + 1; + *temperature = data[3]; + *temperature = -*temperature; + } else { + *temperature = data[3]; + } + + *temperature += (double)(data[4]) / 256.0; + DEBUG("barometer: MPL3115_read - temperature = %lf C", *temperature); + + return 0; } /** @@ -989,70 +885,62 @@ static int MPL3115_read(double * pressure, double * temperature) * * @return 0 if successful */ -static int MPL3115_init_sensor(void) -{ - __s32 res; - __s8 offset; - char errbuf[1024]; - - /* Reset the sensor. It will reset immediately without ACKing */ - /* the transaction, so no error handling here. */ - i2c_smbus_write_byte_data(i2c_bus_fd, - MPL3115_REG_CTRL_REG1, - MPL3115_CTRL_REG1_RST); - - /* wait some time for the reset to finish */ - usleep(100000); - - /* now it should be in standby already so we can go and configure it */ - - /* Set temperature offset. */ - /* result = ADCtemp + offset [C] */ - offset = (__s8) (config_temp_offset * 16.0); - res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset); - if (res < 0) - { - ERROR ("barometer: MPL3115_init_sensor - problem setting temp offset: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - - /* Set pressure offset. */ - /* result = ADCpress + offset [hPa] */ - offset = (__s8) (config_press_offset * 100.0 / 4.0); - res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset); - if (res < 0) - { - ERROR ("barometer: MPL3115_init_sensor - problem setting pressure offset: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - - /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */ - res = i2c_smbus_write_byte_data(i2c_bus_fd, - MPL3115_REG_PT_DATA_CFG, - MPL3115_PT_DATA_DREM \ - | MPL3115_PT_DATA_PDEF \ - | MPL3115_PT_DATA_TDEF); - if (res < 0) - { - ERROR ("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - - /* Set to barometer with an OSR */ - res = i2c_smbus_write_byte_data(i2c_bus_fd, - MPL3115_REG_CTRL_REG1, - mpl3115_oversample); - if (res < 0) - { - ERROR ("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - - return 0; +static int MPL3115_init_sensor(void) { + __s32 res; + __s8 offset; + char errbuf[1024]; + + /* Reset the sensor. It will reset immediately without ACKing */ + /* the transaction, so no error handling here. */ + i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1, + MPL3115_CTRL_REG1_RST); + + /* wait some time for the reset to finish */ + usleep(100000); + + /* now it should be in standby already so we can go and configure it */ + + /* Set temperature offset. */ + /* result = ADCtemp + offset [C] */ + offset = (__s8)(config_temp_offset * 16.0); + res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset); + if (res < 0) { + ERROR("barometer: MPL3115_init_sensor - problem setting temp offset: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + + /* Set pressure offset. */ + /* result = ADCpress + offset [hPa] */ + offset = (__s8)(config_press_offset * 100.0 / 4.0); + res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset); + if (res < 0) { + ERROR( + "barometer: MPL3115_init_sensor - problem setting pressure offset: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + + /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */ + res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_PT_DATA_CFG, + MPL3115_PT_DATA_DREM | MPL3115_PT_DATA_PDEF | + MPL3115_PT_DATA_TDEF); + if (res < 0) { + ERROR("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + + /* Set to barometer with an OSR */ + res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1, + mpl3115_oversample); + if (res < 0) { + ERROR("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + + return 0; } /* ------------------------ BMP085 access ------------------------ */ @@ -1064,88 +952,77 @@ static int MPL3115_init_sensor(void) * * @return 1 if BMP085, 0 otherwise */ -static int BMP085_detect(void) -{ - __s32 res; - char errbuf[1024]; - - if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0) - { - ERROR("barometer: BMP085_detect - problem setting i2c slave address to 0x%02X: %s", - BMP085_I2C_ADDRESS, - sstrerror (errno, errbuf, sizeof (errbuf))); - return 0 ; - } - - res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG); - if(res == BMP085_CHIP_ID) - { - DEBUG ("barometer: BMP085_detect - positive detection"); - - /* get version */ - res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION ); - if (res < 0) - { - ERROR("barometer: BMP085_detect - problem checking chip version: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 0 ; - } - DEBUG ("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X", - res & 0x0f, - (res & 0xf0) >> 4); - return 1; - } - - DEBUG ("barometer: BMP085_detect - negative detection"); +static int BMP085_detect(void) { + __s32 res; + char errbuf[1024]; + + if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0) { + ERROR("barometer: BMP085_detect - problem setting i2c slave address to " + "0x%02X: %s", + BMP085_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf))); return 0; + } + + res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG); + if (res == BMP085_CHIP_ID) { + DEBUG("barometer: BMP085_detect - positive detection"); + + /* get version */ + res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION); + if (res < 0) { + ERROR("barometer: BMP085_detect - problem checking chip version: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 0; + } + DEBUG("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X", + res & 0x0f, (res & 0xf0) >> 4); + return 1; + } + + DEBUG("barometer: BMP085_detect - negative detection"); + return 0; } - /** * Adjusts oversampling settings to values supported by BMP085 * * BMP085 supports only 1,2,4 or 8 samples. */ -static void BMP085_adjust_oversampling(void) -{ - int new_val = 0; - - if( config_oversample > 6 ) /* 8 */ - { - new_val = 8; - bmp085_oversampling = 3; - bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3; - bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3; - } - else if( config_oversample > 3 ) /* 4 */ - { - new_val = 4; - bmp085_oversampling = 2; - bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2; - bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2; - } - else if( config_oversample > 1 ) /* 2 */ - { - new_val = 2; - bmp085_oversampling = 1; - bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1; - bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1; - } - else /* 1 */ - { - new_val = 1; - bmp085_oversampling = 0; - bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0; - bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0; - } - - DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from %d to %d", - config_oversample, - new_val); - config_oversample = new_val; +static void BMP085_adjust_oversampling(void) { + int new_val = 0; + + if (config_oversample > 6) /* 8 */ + { + new_val = 8; + bmp085_oversampling = 3; + bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3; + bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3; + } else if (config_oversample > 3) /* 4 */ + { + new_val = 4; + bmp085_oversampling = 2; + bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2; + bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2; + } else if (config_oversample > 1) /* 2 */ + { + new_val = 2; + bmp085_oversampling = 1; + bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1; + bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1; + } else /* 1 */ + { + new_val = 1; + bmp085_oversampling = 0; + bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0; + bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0; + } + + DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from " + "%d to %d", + config_oversample, new_val); + config_oversample = new_val; } - /** * Read the BMP085 sensor conversion coefficients. * @@ -1153,53 +1030,39 @@ static void BMP085_adjust_oversampling(void) * * @return Zero when successful */ -static int BMP085_read_coeffs(void) -{ - __s32 res; - __u8 coeffs[BMP085_NUM_COEFFS]; - char errbuf[1024]; - - res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, - BMP085_ADDR_COEFFS, - BMP085_NUM_COEFFS, - coeffs); - if (res < 0) - { - ERROR ("barometer: BMP085_read_coeffs - problem reading data: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } - - bmp085_AC1 = ((int16_t) coeffs[0] <<8) | (int16_t) coeffs[1]; - bmp085_AC2 = ((int16_t) coeffs[2] <<8) | (int16_t) coeffs[3]; - bmp085_AC3 = ((int16_t) coeffs[4] <<8) | (int16_t) coeffs[5]; - bmp085_AC4 = ((uint16_t) coeffs[6] <<8) | (uint16_t) coeffs[7]; - bmp085_AC5 = ((uint16_t) coeffs[8] <<8) | (uint16_t) coeffs[9]; - bmp085_AC6 = ((uint16_t) coeffs[10] <<8) | (uint16_t) coeffs[11]; - bmp085_B1 = ((int16_t) coeffs[12] <<8) | (int16_t) coeffs[13]; - bmp085_B2 = ((int16_t) coeffs[14] <<8) | (int16_t) coeffs[15]; - bmp085_MB = ((int16_t) coeffs[16] <<8) | (int16_t) coeffs[17]; - bmp085_MC = ((int16_t) coeffs[18] <<8) | (int16_t) coeffs[19]; - bmp085_MD = ((int16_t) coeffs[20] <<8) | (int16_t) coeffs[21]; - - DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"\ - " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d", - bmp085_AC1, - bmp085_AC2, - bmp085_AC3, - bmp085_AC4, - bmp085_AC5, - bmp085_AC6, - bmp085_B1, - bmp085_B2, - bmp085_MB, - bmp085_MC, - bmp085_MD); - - return 0; +static int BMP085_read_coeffs(void) { + __s32 res; + __u8 coeffs[BMP085_NUM_COEFFS]; + char errbuf[1024]; + + res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_COEFFS, + BMP085_NUM_COEFFS, coeffs); + if (res < 0) { + ERROR("barometer: BMP085_read_coeffs - problem reading data: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + + bmp085_AC1 = ((int16_t)coeffs[0] << 8) | (int16_t)coeffs[1]; + bmp085_AC2 = ((int16_t)coeffs[2] << 8) | (int16_t)coeffs[3]; + bmp085_AC3 = ((int16_t)coeffs[4] << 8) | (int16_t)coeffs[5]; + bmp085_AC4 = ((uint16_t)coeffs[6] << 8) | (uint16_t)coeffs[7]; + bmp085_AC5 = ((uint16_t)coeffs[8] << 8) | (uint16_t)coeffs[9]; + bmp085_AC6 = ((uint16_t)coeffs[10] << 8) | (uint16_t)coeffs[11]; + bmp085_B1 = ((int16_t)coeffs[12] << 8) | (int16_t)coeffs[13]; + bmp085_B2 = ((int16_t)coeffs[14] << 8) | (int16_t)coeffs[15]; + bmp085_MB = ((int16_t)coeffs[16] << 8) | (int16_t)coeffs[17]; + bmp085_MC = ((int16_t)coeffs[18] << 8) | (int16_t)coeffs[19]; + bmp085_MD = ((int16_t)coeffs[20] << 8) | (int16_t)coeffs[21]; + + DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u," + " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d", + bmp085_AC1, bmp085_AC2, bmp085_AC3, bmp085_AC4, bmp085_AC5, bmp085_AC6, + bmp085_B1, bmp085_B2, bmp085_MB, bmp085_MC, bmp085_MD); + + return 0; } - /** * Convert raw BMP085 adc values to real data using the sensor coefficients. * @@ -1208,67 +1071,60 @@ static int BMP085_read_coeffs(void) * @param pressure computed real pressure * @param temperature computed real temperature */ -static void BMP085_convert_adc_to_real(long adc_pressure, - long adc_temperature, - double * pressure, - double * temperature) +static void BMP085_convert_adc_to_real(long adc_pressure, long adc_temperature, + double *pressure, double *temperature) { - long X1, X2, X3; - long B3, B5, B6; - unsigned long B4, B7; - - long T; - long P; - - - /* calculate real temperature */ - X1 = ( (adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15; - X2 = (bmp085_MC << 11) / (X1 + bmp085_MD); - - /* B5, T */ - B5 = X1 + X2; - T = (B5 + 8) >> 4; - *temperature = (double)T * 0.1; - - /* calculate real pressure */ - /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept */ - - /* B6, B3 */ - B6 = B5 - 4000; - X1 = ((bmp085_B2 * ((B6 * B6)>>12)) >> 11 ); - X2 = (((long)bmp085_AC2 * B6) >> 11); - X3 = X1 + X2; - B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2; - - /* B4 */ - X1 = (((long)bmp085_AC3*B6) >> 13); - X2 = (bmp085_B1*((B6*B6) >> 12) ) >> 16; - X3 = ((X1 + X2) + 2 ) >> 2; - B4 = ((long)bmp085_AC4* (unsigned long)(X3 + 32768)) >> 15; - - /* B7, P */ - B7 = (unsigned long)(adc_pressure - B3)*(50000>>bmp085_oversampling); - if( B7 < 0x80000000 ) - { - P = (B7 << 1) / B4; - } - else - { - P = (B7/B4) << 1; - } - X1 = (P >> 8) * (P >> 8); - X1 = (X1 * 3038) >> 16; - X2 = ((-7357) * P) >> 16; - P = P + ( ( X1 + X2 + 3791 ) >> 4); - - *pressure = P / 100.0; // in [hPa] - DEBUG ("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C", - *pressure, - *temperature); + long X1, X2, X3; + long B3, B5, B6; + unsigned long B4, B7; + + long T; + long P; + + /* calculate real temperature */ + X1 = ((adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15; + X2 = (bmp085_MC << 11) / (X1 + bmp085_MD); + + /* B5, T */ + B5 = X1 + X2; + T = (B5 + 8) >> 4; + *temperature = (double)T * 0.1; + + /* calculate real pressure */ + /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept + */ + + /* B6, B3 */ + B6 = B5 - 4000; + X1 = ((bmp085_B2 * ((B6 * B6) >> 12)) >> 11); + X2 = (((long)bmp085_AC2 * B6) >> 11); + X3 = X1 + X2; + B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2; + + /* B4 */ + X1 = (((long)bmp085_AC3 * B6) >> 13); + X2 = (bmp085_B1 * ((B6 * B6) >> 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + B4 = ((long)bmp085_AC4 * (unsigned long)(X3 + 32768)) >> 15; + + /* B7, P */ + B7 = (unsigned long)(adc_pressure - B3) * (50000 >> bmp085_oversampling); + if (B7 < 0x80000000) { + P = (B7 << 1) / B4; + } else { + P = (B7 / B4) << 1; + } + X1 = (P >> 8) * (P >> 8); + X1 = (X1 * 3038) >> 16; + X2 = ((-7357) * P) >> 16; + P = P + ((X1 + X2 + 3791) >> 4); + + *pressure = P / 100.0; // in [hPa] + DEBUG("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C", *pressure, + *temperature); } - /** * Read compensated sensor measurements * @@ -1277,82 +1133,70 @@ static void BMP085_convert_adc_to_real(long adc_pressure, * * @return Zero when successful */ -static int BMP085_read(double * pressure, double * temperature) -{ - __s32 res; - __u8 measBuff[3]; - - long adc_pressure; - long adc_temperature; - - char errbuf[1024]; - - /* start conversion of temperature */ - res = i2c_smbus_write_byte_data( i2c_bus_fd, - BMP085_ADDR_CTRL_REG, - BMP085_CMD_CONVERT_TEMP ); - if (res < 0) - { - ERROR ("barometer: BMP085_read - problem requesting temperature conversion: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */ - - res = i2c_smbus_read_i2c_block_data( i2c_bus_fd, - BMP085_ADDR_CONV, - 2, - measBuff); - if (res < 0) - { - ERROR ("barometer: BMP085_read - problem reading temperature data: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - adc_temperature = ( (unsigned short)measBuff[0] << 8 ) + measBuff[1]; - - - /* get presure */ - res = i2c_smbus_write_byte_data( i2c_bus_fd, - BMP085_ADDR_CTRL_REG, - bmp085_cmdCnvPress ); - if (res < 0) - { - ERROR ("barometer: BMP085_read - problem requesting pressure conversion: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - usleep(bmp085_timeCnvPress); /* wait for the conversion */ - - res = i2c_smbus_read_i2c_block_data( i2c_bus_fd, - BMP085_ADDR_CONV, - 3, - measBuff ); - if (res < 0) - { - ERROR ("barometer: BMP085_read - problem reading pressure data: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return 1; - } - - adc_pressure = (long)((((ulong)measBuff[0]<<16) | ((ulong)measBuff[1]<<8) | (ulong)measBuff[2] ) >> (8 - bmp085_oversampling)); - - - DEBUG ("barometer: BMP085_read - raw pressure ADC value = %ld, " \ - "raw temperature ADC value = %ld", - adc_pressure, - adc_temperature); - - BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature); - - return 0; +static int BMP085_read(double *pressure, double *temperature) { + __s32 res; + __u8 measBuff[3]; + + long adc_pressure; + long adc_temperature; + + char errbuf[1024]; + + /* start conversion of temperature */ + res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG, + BMP085_CMD_CONVERT_TEMP); + if (res < 0) { + ERROR("barometer: BMP085_read - problem requesting temperature conversion: " + "%s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */ + + res = + i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 2, measBuff); + if (res < 0) { + ERROR("barometer: BMP085_read - problem reading temperature data: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + adc_temperature = ((unsigned short)measBuff[0] << 8) + measBuff[1]; + + /* get presure */ + res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG, + bmp085_cmdCnvPress); + if (res < 0) { + ERROR("barometer: BMP085_read - problem requesting pressure conversion: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + usleep(bmp085_timeCnvPress); /* wait for the conversion */ + + res = + i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 3, measBuff); + if (res < 0) { + ERROR("barometer: BMP085_read - problem reading pressure data: %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + return 1; + } + + adc_pressure = (long)((((ulong)measBuff[0] << 16) | + ((ulong)measBuff[1] << 8) | (ulong)measBuff[2]) >> + (8 - bmp085_oversampling)); + + DEBUG("barometer: BMP085_read - raw pressure ADC value = %ld, " + "raw temperature ADC value = %ld", + adc_pressure, adc_temperature); + + BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure, + temperature); + + return 0; } - - /* ------------------------ Sensor detection ------------------------ */ /** * Detect presence of a supported sensor. @@ -1363,18 +1207,17 @@ static int BMP085_read(double * pressure, double * temperature) * * @return detected sensor type */ -static enum Sensor_type detect_sensor_type(void) -{ - if(BMP085_detect()) - return Sensor_BMP085; +static enum Sensor_type detect_sensor_type(void) { + if (BMP085_detect()) + return Sensor_BMP085; - else if(MPL3115_detect()) - return Sensor_MPL3115; + else if (MPL3115_detect()) + return Sensor_MPL3115; - else if(MPL115_detect()) - return Sensor_MPL115; + else if (MPL115_detect()) + return Sensor_MPL115; - return Sensor_none; + return Sensor_none; } /* ------------------------ Common functionality ------------------------ */ @@ -1385,7 +1228,8 @@ static enum Sensor_type detect_sensor_type(void) * Implemented methods are: * - MSLP_NONE - no converions, returns absolute pressure * - * - MSLP_INTERNATIONAL - see http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation + * - MSLP_INTERNATIONAL - see + * http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation * Requires #config_altitude * * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See @@ -1396,58 +1240,54 @@ static enum Sensor_type detect_sensor_type(void) * * @return mean sea level pressure if successful, NAN otherwise */ -static double abs_to_mean_sea_level_pressure(double abs_pressure) -{ - double mean = -1.0; - double temp = 0.0; - int result = 0; +static double abs_to_mean_sea_level_pressure(double abs_pressure) { + double mean = -1.0; + double temp = 0.0; + int result = 0; - if (config_normalize >= MSLP_DEU_WETT) - { - result = get_reference_temperature(&temp); - if(result) - { - return NAN; - } + if (config_normalize >= MSLP_DEU_WETT) { + result = get_reference_temperature(&temp); + if (result) { + return NAN; } + } - switch(config_normalize) - { - case MSLP_NONE: - mean = abs_pressure; - break; - - case MSLP_INTERNATIONAL: - mean = abs_pressure / \ - pow(1.0 - 0.0065*config_altitude/288.15, 9.80665*0.0289644/(8.31447*0.0065)); - break; + switch (config_normalize) { + case MSLP_NONE: + mean = abs_pressure; + break; - case MSLP_DEU_WETT: - { - double E; /* humidity */ - double x; - if(temp<9.1) - E = 5.6402 * (-0.0916 + exp(0.06*temp) ); - else - E = 18.2194 * (1.0463 - exp(-0.0666*temp) ); - x = 9.80665 / (287.05 * (temp+273.15 + 0.12*E + 0.0065*config_altitude/2)) * config_altitude; - mean = abs_pressure * exp(x); - } + case MSLP_INTERNATIONAL: + mean = abs_pressure / pow(1.0 - 0.0065 * config_altitude / 288.15, + 9.80665 * 0.0289644 / (8.31447 * 0.0065)); break; - default: - ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", - config_normalize); - mean = abs_pressure; - break; - } + case MSLP_DEU_WETT: { + double E; /* humidity */ + double x; + if (temp < 9.1) + E = 5.6402 * (-0.0916 + exp(0.06 * temp)); + else + E = 18.2194 * (1.0463 - exp(-0.0666 * temp)); + x = 9.80665 / + (287.05 * (temp + 273.15 + 0.12 * E + 0.0065 * config_altitude / 2)) * + config_altitude; + mean = abs_pressure * exp(x); + } break; + + default: + ERROR( + "barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", + config_normalize); + mean = abs_pressure; + break; + } - DEBUG ("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, method = %d, meanPressure = %lf hPa", - abs_pressure, - config_normalize, - mean); + DEBUG("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, " + "method = %d, meanPressure = %lf hPa", + abs_pressure, config_normalize, mean); - return mean; + return mean; } /* ------------------------ main plugin callbacks ------------------------ */ @@ -1460,66 +1300,47 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure) * * @return Zero when successful. */ -static int collectd_barometer_config (const char *key, const char *value) -{ - DEBUG("barometer: collectd_barometer_config"); - - if (strcasecmp (key, "Device") == 0) - { - sfree (config_device); - config_device = strdup (value); - } - else if (strcasecmp (key, "Oversampling") == 0) - { - int oversampling_tmp = atoi (value); - if (oversampling_tmp < 1 || oversampling_tmp > 1024) - { - WARNING ("barometer: collectd_barometer_config: invalid oversampling: %d." \ - " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for MPL3115) or 1 to 8 (for BMP085).", - oversampling_tmp); - return 1; - } - config_oversample = oversampling_tmp; - } - else if (strcasecmp (key, "Altitude") == 0) - { - config_altitude = atof (value); - } - else if (strcasecmp (key, "Normalization") == 0) - { - int normalize_tmp = atoi (value); - if (normalize_tmp < 0 || normalize_tmp > 2) - { - WARNING ("barometer: collectd_barometer_config: invalid normalization: %d", - normalize_tmp); - return 1; - } - config_normalize = normalize_tmp; - } - else if (strcasecmp (key, "TemperatureSensor") == 0) - { - if(temp_list_add(temp_list, value)) - { - return -1; - } - } - else if (strcasecmp (key, "PressureOffset") == 0) - { - config_press_offset = atof(value); - } - else if (strcasecmp (key, "TemperatureOffset") == 0) - { - config_temp_offset = atof(value); - } - else - { - return -1; - } - - return 0; +static int collectd_barometer_config(const char *key, const char *value) { + DEBUG("barometer: collectd_barometer_config"); + + if (strcasecmp(key, "Device") == 0) { + sfree(config_device); + config_device = strdup(value); + } else if (strcasecmp(key, "Oversampling") == 0) { + int oversampling_tmp = atoi(value); + if (oversampling_tmp < 1 || oversampling_tmp > 1024) { + WARNING("barometer: collectd_barometer_config: invalid oversampling: %d." + " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for " + "MPL3115) or 1 to 8 (for BMP085).", + oversampling_tmp); + return 1; + } + config_oversample = oversampling_tmp; + } else if (strcasecmp(key, "Altitude") == 0) { + config_altitude = atof(value); + } else if (strcasecmp(key, "Normalization") == 0) { + int normalize_tmp = atoi(value); + if (normalize_tmp < 0 || normalize_tmp > 2) { + WARNING("barometer: collectd_barometer_config: invalid normalization: %d", + normalize_tmp); + return 1; + } + config_normalize = normalize_tmp; + } else if (strcasecmp(key, "TemperatureSensor") == 0) { + if (temp_list_add(temp_list, value)) { + return -1; + } + } else if (strcasecmp(key, "PressureOffset") == 0) { + config_press_offset = atof(value); + } else if (strcasecmp(key, "TemperatureOffset") == 0) { + config_temp_offset = atof(value); + } else { + return -1; + } + + return 0; } - /** * Shutdown callback. * @@ -1527,29 +1348,25 @@ static int collectd_barometer_config (const char *key, const char *value) * * @return Zero when successful (at the moment the only possible outcome) */ -static int collectd_barometer_shutdown(void) -{ - DEBUG ("barometer: collectd_barometer_shutdown"); +static int collectd_barometer_shutdown(void) { + DEBUG("barometer: collectd_barometer_shutdown"); - if(sensor_type == Sensor_MPL115) - { - averaging_delete (&pressure_averaging); - averaging_delete (&temperature_averaging); + if (sensor_type == Sensor_MPL115) { + averaging_delete(&pressure_averaging); + averaging_delete(&temperature_averaging); - temp_list_delete(&temp_list); - } + temp_list_delete(&temp_list); + } - if (i2c_bus_fd > 0) - { - close (i2c_bus_fd); - i2c_bus_fd = -1; - sfree (config_device); - } + if (i2c_bus_fd > 0) { + close(i2c_bus_fd); + i2c_bus_fd = -1; + sfree(config_device); + } - return 0; + return 0; } - /** * Plugin read callback for MPL115. * @@ -1560,78 +1377,73 @@ static int collectd_barometer_shutdown(void) * * @return Zero when successful. */ -static int MPL115_collectd_barometer_read (void) -{ - int result = 0; - - double pressure = 0.0; - double temperature = 0.0; - double norm_pressure = 0.0; - - value_list_t vl = VALUE_LIST_INIT; - value_t values[1]; - - DEBUG("barometer: MPL115_collectd_barometer_read"); - - if (!configured) - { - return -1; - } - - /* Rather than delaying init, we will intitialize during first read. This - way at least we have a better chance to have the reference temperature - already available. */ - if(!avg_initialized) - { - int i; - for(i=0; i= MSLP_INTERNATIONAL && isnan(config_altitude)) - { - ERROR("barometer: collectd_barometer_init no altitude configured " \ - "for mean sea level pressure normalization."); - return -1; - } + if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude)) { + ERROR("barometer: collectd_barometer_init no altitude configured " + "for mean sea level pressure normalization."); + return -1; + } - if (config_normalize == MSLP_DEU_WETT - && - temp_list == NULL) - { - ERROR("barometer: collectd_barometer_init no temperature reference "\ - "configured for mean sea level pressure normalization."); - return -1; - } + if (config_normalize == MSLP_DEU_WETT && temp_list == NULL) { + ERROR("barometer: collectd_barometer_init no temperature reference " + "configured for mean sea level pressure normalization."); + return -1; + } + i2c_bus_fd = open(config_device, O_RDWR); + if (i2c_bus_fd < 0) { + ERROR("barometer: collectd_barometer_init problem opening I2C bus device " + "\"%s\": %s (is loaded mod i2c-dev?)", + config_device, sstrerror(errno, errbuf, sizeof(errbuf))); + return -1; + } - i2c_bus_fd = open(config_device, O_RDWR); - if (i2c_bus_fd < 0) - { - ERROR ("barometer: collectd_barometer_init problem opening I2C bus device \"%s\": %s (is loaded mod i2c-dev?)", - config_device, - sstrerror (errno, errbuf, sizeof (errbuf))); - return -1; - } + /* detect sensor type - this will also set slave address */ + sensor_type = detect_sensor_type(); - /* detect sensor type - this will also set slave address */ - sensor_type = detect_sensor_type(); + /* init correct sensor type */ + switch (sensor_type) { + /* MPL3115 */ + case Sensor_MPL3115: { + MPL3115_adjust_oversampling(); - /* init correct sensor type */ - switch(sensor_type) - { -/* MPL3115 */ - case Sensor_MPL3115: - { - MPL3115_adjust_oversampling(); + if (MPL3115_init_sensor()) + return -1; - if(MPL3115_init_sensor()) - return -1; + plugin_register_read("barometer", MPL3115_collectd_barometer_read); + } break; - plugin_register_read ("barometer", MPL3115_collectd_barometer_read); + /* MPL115 */ + case Sensor_MPL115: { + if (averaging_create(&pressure_averaging, config_oversample)) { + ERROR( + "barometer: collectd_barometer_init pressure averaging init failed"); + return -1; } - break; - -/* MPL115 */ - case Sensor_MPL115: - { - if (averaging_create (&pressure_averaging, config_oversample)) - { - ERROR("barometer: collectd_barometer_init pressure averaging init failed"); - return -1; - } - - if (averaging_create (&temperature_averaging, config_oversample)) - { - ERROR("barometer: collectd_barometer_init temperature averaging init failed"); - return -1; - } - - if (MPL115_read_coeffs() < 0) - return -1; - plugin_register_read ("barometer", MPL115_collectd_barometer_read); + if (averaging_create(&temperature_averaging, config_oversample)) { + ERROR("barometer: collectd_barometer_init temperature averaging init " + "failed"); + return -1; } - break; -/* BMP085 */ - case Sensor_BMP085: - { - BMP085_adjust_oversampling(); + if (MPL115_read_coeffs() < 0) + return -1; - if (BMP085_read_coeffs() < 0) - return -1; + plugin_register_read("barometer", MPL115_collectd_barometer_read); + } break; - plugin_register_read ("barometer", BMP085_collectd_barometer_read); - } - break; + /* BMP085 */ + case Sensor_BMP085: { + BMP085_adjust_oversampling(); -/* anything else -> error */ - default: - ERROR("barometer: collectd_barometer_init - no supported sensor found"); - return -1; - } + if (BMP085_read_coeffs() < 0) + return -1; + plugin_register_read("barometer", BMP085_collectd_barometer_read); + } break; - configured = 1; - return 0; + /* anything else -> error */ + default: + ERROR("barometer: collectd_barometer_init - no supported sensor found"); + return -1; + } + + configured = 1; + return 0; } -/* ------------------------ plugin register / entry point ------------------------ */ +/* ------------------------ plugin register / entry point + * ------------------------ */ /** * Plugin "entry" - register all callback. * */ -void module_register (void) -{ - plugin_register_config ("barometer", - collectd_barometer_config, - config_keys, - config_keys_num); - plugin_register_init ("barometer", collectd_barometer_init); - plugin_register_shutdown ("barometer", collectd_barometer_shutdown); +void module_register(void) { + plugin_register_config("barometer", collectd_barometer_config, config_keys, + config_keys_num); + plugin_register_init("barometer", collectd_barometer_init); + plugin_register_shutdown("barometer", collectd_barometer_shutdown); } diff --git a/src/battery.c b/src/battery.c index c501a301..48691ce9 100644 --- a/src/battery.c +++ b/src/battery.c @@ -24,360 +24,314 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" -#include "utils_complain.h" - #if HAVE_MACH_MACH_TYPES_H -# include +#include #endif #if HAVE_MACH_MACH_INIT_H -# include +#include #endif #if HAVE_MACH_MACH_ERROR_H -# include +#include #endif #if HAVE_COREFOUNDATION_COREFOUNDATION_H -# include +#include #endif #if HAVE_IOKIT_IOKITLIB_H -# include +#include #endif #if HAVE_IOKIT_IOTYPES_H -# include +#include #endif #if HAVE_IOKIT_PS_IOPOWERSOURCES_H -# include +#include #endif #if HAVE_IOKIT_PS_IOPSKEYS_H -# include +#include #endif #if !HAVE_IOKIT_IOKITLIB_H && !HAVE_IOKIT_PS_IOPOWERSOURCES_H && !KERNEL_LINUX -# error "No applicable input method." +#error "No applicable input method." #endif #if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H - /* No global variables */ +/* No global variables */ /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */ #elif KERNEL_LINUX -# define PROC_PMU_PATH_FORMAT "/proc/pmu/battery_%i" -# define PROC_ACPI_PATH "/proc/acpi/battery" -# define PROC_ACPI_FACTOR 0.001 -# define SYSFS_PATH "/sys/class/power_supply" -# define SYSFS_FACTOR 0.000001 +#define PROC_PMU_PATH_FORMAT "/proc/pmu/battery_%i" +#define PROC_ACPI_PATH "/proc/acpi/battery" +#define PROC_ACPI_FACTOR 0.001 +#define SYSFS_PATH "/sys/class/power_supply" +#define SYSFS_FACTOR 0.000001 #endif /* KERNEL_LINUX */ static _Bool report_percent = 0; static _Bool report_degraded = 0; -static void battery_submit2 (char const *plugin_instance, /* {{{ */ - char const *type, char const *type_instance, gauge_t value) -{ - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; +static void battery_submit2(char const *plugin_instance, /* {{{ */ + char const *type, char const *type_instance, + gauge_t value) { + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; + values[0].gauge = value; - vl.values = values; - vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "battery", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - if (type_instance != NULL) - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + vl.values = values; + vl.values_len = 1; + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "battery", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + if (type_instance != NULL) + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } /* }}} void battery_submit2 */ -static void battery_submit (char const *plugin_instance, /* {{{ */ - char const *type, gauge_t value) -{ - battery_submit2 (plugin_instance, type, NULL, value); +static void battery_submit(char const *plugin_instance, /* {{{ */ + char const *type, gauge_t value) { + battery_submit2(plugin_instance, type, NULL, value); } /* }}} void battery_submit */ -static void submit_capacity (char const *plugin_instance, /* {{{ */ - gauge_t capacity_charged, - gauge_t capacity_full, - gauge_t capacity_design) -{ - if (report_percent && (capacity_charged > capacity_full)) - return; - if (report_degraded && (capacity_full > capacity_design)) - return; - - if (report_percent) - { - gauge_t capacity_max; - - if (report_degraded) - capacity_max = capacity_design; - else - capacity_max = capacity_full; - - battery_submit2 (plugin_instance, "percent", "charged", - 100.0 * capacity_charged / capacity_max); - battery_submit2 (plugin_instance, "percent", "discharged", - 100.0 * (capacity_full - capacity_charged) / capacity_max); - - if (report_degraded) - battery_submit2 (plugin_instance, "percent", "degraded", - 100.0 * (capacity_design - capacity_full) / capacity_max); - } - else if (report_degraded) /* && !report_percent */ - { - battery_submit2 (plugin_instance, "capacity", "charged", - capacity_charged); - battery_submit2 (plugin_instance, "capacity", "discharged", - (capacity_full - capacity_charged)); - battery_submit2 (plugin_instance, "capacity", "degraded", - (capacity_design - capacity_full)); - } - else /* !report_percent && !report_degraded */ - { - battery_submit (plugin_instance, "capacity", capacity_charged); - } +static void submit_capacity(char const *plugin_instance, /* {{{ */ + gauge_t capacity_charged, gauge_t capacity_full, + gauge_t capacity_design) { + if (report_percent && (capacity_charged > capacity_full)) + return; + if (report_degraded && (capacity_full > capacity_design)) + return; + + if (report_percent) { + gauge_t capacity_max; + + if (report_degraded) + capacity_max = capacity_design; + else + capacity_max = capacity_full; + + battery_submit2(plugin_instance, "percent", "charged", + 100.0 * capacity_charged / capacity_max); + battery_submit2(plugin_instance, "percent", "discharged", + 100.0 * (capacity_full - capacity_charged) / capacity_max); + + if (report_degraded) + battery_submit2(plugin_instance, "percent", "degraded", + 100.0 * (capacity_design - capacity_full) / capacity_max); + } else if (report_degraded) /* && !report_percent */ + { + battery_submit2(plugin_instance, "capacity", "charged", capacity_charged); + battery_submit2(plugin_instance, "capacity", "discharged", + (capacity_full - capacity_charged)); + battery_submit2(plugin_instance, "capacity", "degraded", + (capacity_design - capacity_full)); + } else /* !report_percent && !report_degraded */ + { + battery_submit(plugin_instance, "capacity", capacity_charged); + } } /* }}} 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; - CFNumberRef val_obj; - CFStringRef key_obj; - - key_obj = CFStringCreateWithCString (kCFAllocatorDefault, key_string, - kCFStringEncodingASCII); - if (key_obj == NULL) - { - DEBUG ("CFStringCreateWithCString (%s) failed.\n", key_string); - return (NAN); - } - - if ((val_obj = CFDictionaryGetValue (dict, key_obj)) == NULL) - { - DEBUG ("CFDictionaryGetValue (%s) failed.", key_string); - CFRelease (key_obj); - return (NAN); - } - CFRelease (key_obj); - - if (CFGetTypeID (val_obj) == CFNumberGetTypeID ()) - { - if (CFNumberIsFloatType (val_obj)) - { - CFNumberGetValue (val_obj, - kCFNumberDoubleType, - &val_double); - } - else - { - CFNumberGetValue (val_obj, - kCFNumberLongLongType, - &val_int); - val_double = val_int; - } - } - else - { - DEBUG ("CFGetTypeID (val_obj) = %i", (int) CFGetTypeID (val_obj)); - return (NAN); - } - - return (val_double); + double val_double; + long long val_int; + CFNumberRef val_obj; + CFStringRef key_obj; + + key_obj = CFStringCreateWithCString(kCFAllocatorDefault, key_string, + kCFStringEncodingASCII); + if (key_obj == NULL) { + DEBUG("CFStringCreateWithCString (%s) failed.\n", key_string); + return (NAN); + } + + if ((val_obj = CFDictionaryGetValue(dict, key_obj)) == NULL) { + DEBUG("CFDictionaryGetValue (%s) failed.", key_string); + CFRelease(key_obj); + return (NAN); + } + CFRelease(key_obj); + + if (CFGetTypeID(val_obj) == CFNumberGetTypeID()) { + if (CFNumberIsFloatType(val_obj)) { + CFNumberGetValue(val_obj, kCFNumberDoubleType, &val_double); + } else { + CFNumberGetValue(val_obj, kCFNumberLongLongType, &val_int); + val_double = val_int; + } + } else { + DEBUG("CFGetTypeID (val_obj) = %i", (int)CFGetTypeID(val_obj)); + return (NAN); + } + + return (val_double); } /* }}} double dict_get_double */ -# if HAVE_IOKIT_PS_IOPOWERSOURCES_H -static void get_via_io_power_sources (double *ret_charge, /* {{{ */ - double *ret_current, - double *ret_voltage) -{ - CFTypeRef ps_raw; - CFArrayRef ps_array; - int ps_array_len; - CFDictionaryRef ps_dict; - CFTypeRef ps_obj; - - double temp_double; - int i; - - ps_raw = IOPSCopyPowerSourcesInfo (); - ps_array = IOPSCopyPowerSourcesList (ps_raw); - ps_array_len = CFArrayGetCount (ps_array); - - DEBUG ("ps_array_len == %i", ps_array_len); - - for (i = 0; i < ps_array_len; i++) - { - ps_obj = CFArrayGetValueAtIndex (ps_array, i); - ps_dict = IOPSGetPowerSourceDescription (ps_raw, ps_obj); - - if (ps_dict == NULL) - { - DEBUG ("IOPSGetPowerSourceDescription failed."); - continue; - } - - if (CFGetTypeID (ps_dict) != CFDictionaryGetTypeID ()) - { - DEBUG ("IOPSGetPowerSourceDescription did not return a CFDictionaryRef"); - continue; - } - - /* FIXME: Check if this is really an internal battery */ - - if (isnan (*ret_charge)) - { - /* This is the charge in percent. */ - temp_double = dict_get_double (ps_dict, - kIOPSCurrentCapacityKey); - if (!isnan ((temp_double)) - && (temp_double >= 0.0) - && (temp_double <= 100.0)) - *ret_charge = temp_double; - } - - if (isnan (*ret_current)) - { - temp_double = dict_get_double (ps_dict, - kIOPSCurrentKey); - if (!isnan (temp_double)) - *ret_current = temp_double / 1000.0; - } - - if (isnan (*ret_voltage)) - { - temp_double = dict_get_double (ps_dict, - kIOPSVoltageKey); - if (!isnan (temp_double)) - *ret_voltage = temp_double / 1000.0; - } - } - - CFRelease(ps_array); - CFRelease(ps_raw); +#if HAVE_IOKIT_PS_IOPOWERSOURCES_H +static void get_via_io_power_sources(double *ret_charge, /* {{{ */ + double *ret_current, double *ret_voltage) { + CFTypeRef ps_raw; + CFArrayRef ps_array; + int ps_array_len; + CFDictionaryRef ps_dict; + CFTypeRef ps_obj; + + double temp_double; + + ps_raw = IOPSCopyPowerSourcesInfo(); + ps_array = IOPSCopyPowerSourcesList(ps_raw); + ps_array_len = CFArrayGetCount(ps_array); + + DEBUG("ps_array_len == %i", ps_array_len); + + for (int i = 0; i < ps_array_len; i++) { + ps_obj = CFArrayGetValueAtIndex(ps_array, i); + ps_dict = IOPSGetPowerSourceDescription(ps_raw, ps_obj); + + if (ps_dict == NULL) { + DEBUG("IOPSGetPowerSourceDescription failed."); + continue; + } + + if (CFGetTypeID(ps_dict) != CFDictionaryGetTypeID()) { + DEBUG("IOPSGetPowerSourceDescription did not return a CFDictionaryRef"); + continue; + } + + /* FIXME: Check if this is really an internal battery */ + + if (isnan(*ret_charge)) { + /* This is the charge in percent. */ + temp_double = dict_get_double(ps_dict, kIOPSCurrentCapacityKey); + if (!isnan((temp_double)) && (temp_double >= 0.0) && + (temp_double <= 100.0)) + *ret_charge = temp_double; + } + + if (isnan(*ret_current)) { + temp_double = dict_get_double(ps_dict, kIOPSCurrentKey); + if (!isnan(temp_double)) + *ret_current = temp_double / 1000.0; + } + + if (isnan(*ret_voltage)) { + temp_double = dict_get_double(ps_dict, kIOPSVoltageKey); + if (!isnan(temp_double)) + *ret_voltage = temp_double / 1000.0; + } + } + + CFRelease(ps_array); + CFRelease(ps_raw); } /* }}} void get_via_io_power_sources */ -# endif /* HAVE_IOKIT_PS_IOPOWERSOURCES_H */ +#endif /* HAVE_IOKIT_PS_IOPOWERSOURCES_H */ -# if HAVE_IOKIT_IOKITLIB_H -static void get_via_generic_iokit (double *ret_capacity_full, /* {{{ */ - double *ret_capacity_design, - double *ret_current, - double *ret_voltage) -{ - kern_return_t status; - io_iterator_t iterator; - io_object_t io_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; - - status = IOServiceGetMatchingServices (kIOMasterPortDefault, - IOServiceNameMatching ("battery"), - &iterator); - if (status != kIOReturnSuccess) - { - DEBUG ("IOServiceGetMatchingServices failed."); - return; - } - - while ((io_obj = IOIteratorNext (iterator))) - { - status = IORegistryEntryCreateCFProperties (io_obj, - (CFMutableDictionaryRef *) &bat_root_dict, - kCFAllocatorDefault, - kNilOptions); - if (status != kIOReturnSuccess) - { - DEBUG ("IORegistryEntryCreateCFProperties failed."); - continue; - } - - bat_info_arry = (CFArrayRef) CFDictionaryGetValue (bat_root_dict, - CFSTR ("IOBatteryInfo")); - if (bat_info_arry == NULL) - { - CFRelease (bat_root_dict); - continue; - } - bat_info_arry_len = CFArrayGetCount (bat_info_arry); - - for (bat_info_arry_pos = 0; - bat_info_arry_pos < bat_info_arry_len; - bat_info_arry_pos++) - { - bat_info_dict = (CFDictionaryRef) CFArrayGetValueAtIndex (bat_info_arry, bat_info_arry_pos); - - if (isnan (*ret_capacity_full)) - { - temp_double = dict_get_double (bat_info_dict, "Capacity"); - *ret_capacity_full = temp_double / 1000.0; - } - - if (isnan (*ret_capacity_design)) - { - temp_double = dict_get_double (bat_info_dict, "AbsoluteMaxCapacity"); - *ret_capacity_design = temp_double / 1000.0; - } - - if (isnan (*ret_current)) - { - temp_double = dict_get_double (bat_info_dict, "Current"); - *ret_current = temp_double / 1000.0; - } - - if (isnan (*ret_voltage)) - { - temp_double = dict_get_double (bat_info_dict, "Voltage"); - *ret_voltage = temp_double / 1000.0; - } - } - - CFRelease (bat_root_dict); - } - - IOObjectRelease (iterator); +#if HAVE_IOKIT_IOKITLIB_H +static void get_via_generic_iokit(double *ret_capacity_full, /* {{{ */ + double *ret_capacity_design, + double *ret_current, double *ret_voltage) { + kern_return_t status; + io_iterator_t iterator; + io_object_t io_obj; + + CFDictionaryRef bat_root_dict; + CFArrayRef bat_info_arry; + CFIndex bat_info_arry_len; + CFDictionaryRef bat_info_dict; + + double temp_double; + + status = IOServiceGetMatchingServices( + kIOMasterPortDefault, IOServiceNameMatching("battery"), &iterator); + if (status != kIOReturnSuccess) { + DEBUG("IOServiceGetMatchingServices failed."); + return; + } + + while ((io_obj = IOIteratorNext(iterator))) { + status = IORegistryEntryCreateCFProperties( + io_obj, (CFMutableDictionaryRef *)&bat_root_dict, kCFAllocatorDefault, + kNilOptions); + if (status != kIOReturnSuccess) { + DEBUG("IORegistryEntryCreateCFProperties failed."); + continue; + } + + bat_info_arry = + (CFArrayRef)CFDictionaryGetValue(bat_root_dict, CFSTR("IOBatteryInfo")); + if (bat_info_arry == NULL) { + CFRelease(bat_root_dict); + continue; + } + bat_info_arry_len = CFArrayGetCount(bat_info_arry); + + for (CFIndex bat_info_arry_pos = 0; bat_info_arry_pos < bat_info_arry_len; + bat_info_arry_pos++) { + bat_info_dict = (CFDictionaryRef)CFArrayGetValueAtIndex( + bat_info_arry, bat_info_arry_pos); + + if (isnan(*ret_capacity_full)) { + temp_double = dict_get_double(bat_info_dict, "Capacity"); + *ret_capacity_full = temp_double / 1000.0; + } + + if (isnan(*ret_capacity_design)) { + temp_double = dict_get_double(bat_info_dict, "AbsoluteMaxCapacity"); + *ret_capacity_design = temp_double / 1000.0; + } + + if (isnan(*ret_current)) { + temp_double = dict_get_double(bat_info_dict, "Current"); + *ret_current = temp_double / 1000.0; + } + + if (isnan(*ret_voltage)) { + temp_double = dict_get_double(bat_info_dict, "Voltage"); + *ret_voltage = temp_double / 1000.0; + } + } + + CFRelease(bat_root_dict); + } + + IOObjectRelease(iterator); } /* }}} void get_via_generic_iokit */ -# endif /* HAVE_IOKIT_IOKITLIB_H */ +#endif /* HAVE_IOKIT_IOKITLIB_H */ -static int battery_read (void) /* {{{ */ +static int battery_read(void) /* {{{ */ { - gauge_t current = NAN; /* Current in A */ - gauge_t voltage = NAN; /* Voltage in V */ + gauge_t current = NAN; /* Current in A */ + gauge_t voltage = NAN; /* Voltage in V */ - /* We only get the charged capacity as a percentage from - * 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_full = NAN; /* Total capacity */ - gauge_t capacity_design = NAN; /* Full design capacity */ + /* We only get the charged capacity as a percentage from + * 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; /* Charged capacity */ + gauge_t capacity_full = NAN; /* Total capacity */ + gauge_t capacity_design = NAN; /* Full design capacity */ #if HAVE_IOKIT_PS_IOPOWERSOURCES_H - get_via_io_power_sources (&charge_rel, ¤t, &voltage); + get_via_io_power_sources(&charge_rel, ¤t, &voltage); #endif #if HAVE_IOKIT_IOKITLIB_H - get_via_generic_iokit (&capacity_full, &capacity_design, ¤t, &voltage); + get_via_generic_iokit(&capacity_full, &capacity_design, ¤t, &voltage); #endif - capacity_charged = charge_rel * capacity_full / 100.0; - submit_capacity ("0", capacity_charged, capacity_full, capacity_design); + capacity_charged = charge_rel * capacity_full / 100.0; + submit_capacity("0", capacity_charged, capacity_full, capacity_design); - if (!isnan (current)) - battery_submit ("0", "current", current); - if (!isnan (voltage)) - battery_submit ("0", "voltage", voltage); + if (!isnan(current)) + battery_submit("0", "current", current); + if (!isnan(voltage)) + battery_submit("0", "voltage", voltage); - return (0); + return (0); } /* }}} int battery_read */ /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */ @@ -385,446 +339,416 @@ static int battery_read (void) /* {{{ */ /* Reads a file which contains only a number (and optionally a trailing * newline) and parses that number. */ static int sysfs_file_to_buffer(char const *dir, /* {{{ */ - char const *power_supply, - char const *basename, - char *buffer, size_t buffer_size) -{ - int status; - FILE *fp; - char filename[PATH_MAX]; - - ssnprintf (filename, sizeof (filename), "%s/%s/%s", - dir, power_supply, basename); - - /* No file isn't the end of the world -- not every system will be - * reporting the same set of statistics */ - if (access (filename, R_OK) != 0) - return ENOENT; - - fp = fopen (filename, "r"); - if (fp == NULL) - { - status = errno; - if (status != ENOENT) - { - char errbuf[1024]; - WARNING ("battery plugin: fopen (%s) failed: %s", filename, - sstrerror (status, errbuf, sizeof (errbuf))); - } - return status; - } - - if (fgets (buffer, buffer_size, fp) == NULL) - { - status = errno; - if (status != ENODEV) - { - char errbuf[1024]; - WARNING ("battery plugin: fgets (%s) failed: %s", filename, - sstrerror (status, errbuf, sizeof (errbuf))); - } - fclose (fp); - return status; - } - - strstripnewline (buffer); - - fclose (fp); - return 0; + char const *power_supply, char const *basename, + char *buffer, size_t buffer_size) { + int status; + FILE *fp; + char filename[PATH_MAX]; + + ssnprintf(filename, sizeof(filename), "%s/%s/%s", dir, power_supply, + basename); + + /* No file isn't the end of the world -- not every system will be + * reporting the same set of statistics */ + if (access(filename, R_OK) != 0) + return ENOENT; + + fp = fopen(filename, "r"); + if (fp == NULL) { + status = errno; + if (status != ENOENT) { + char errbuf[1024]; + WARNING("battery plugin: fopen (%s) failed: %s", filename, + sstrerror(status, errbuf, sizeof(errbuf))); + } + return status; + } + + if (fgets(buffer, buffer_size, fp) == NULL) { + status = errno; + if (status != ENODEV) { + char errbuf[1024]; + WARNING("battery plugin: fgets (%s) failed: %s", filename, + sstrerror(status, errbuf, sizeof(errbuf))); + } + fclose(fp); + return status; + } + + strstripnewline(buffer); + + fclose(fp); + return 0; } /* }}} int sysfs_file_to_buffer */ /* Reads a file which contains only a number (and optionally a trailing * newline) and parses that number. */ static int sysfs_file_to_gauge(char const *dir, /* {{{ */ - char const *power_supply, - char const *basename, gauge_t *ret_value) -{ - int status; - char buffer[32] = ""; + char const *power_supply, char const *basename, + gauge_t *ret_value) { + int status; + char buffer[32] = ""; - status = sysfs_file_to_buffer (dir, power_supply, basename, buffer, sizeof (buffer)); - if (status != 0) - return (status); + status = + sysfs_file_to_buffer(dir, power_supply, basename, buffer, sizeof(buffer)); + if (status != 0) + return (status); - return (strtogauge (buffer, ret_value)); + return (strtogauge(buffer, ret_value)); } /* }}} sysfs_file_to_gauge */ -static int read_sysfs_capacity (char const *dir, /* {{{ */ - char const *power_supply, - char const *plugin_instance) -{ - gauge_t capacity_charged = NAN; - gauge_t capacity_full = NAN; - gauge_t capacity_design = NAN; - int status; - - status = sysfs_file_to_gauge (dir, power_supply, "energy_now", &capacity_charged); - if (status != 0) - return (status); - - status = sysfs_file_to_gauge (dir, power_supply, "energy_full", &capacity_full); - if (status != 0) - return (status); - - status = sysfs_file_to_gauge (dir, power_supply, "energy_full_design", &capacity_design); - if (status != 0) - return (status); - - submit_capacity (plugin_instance, - capacity_charged * SYSFS_FACTOR, - capacity_full * SYSFS_FACTOR, - capacity_design * SYSFS_FACTOR); - return (0); +static int read_sysfs_capacity(char const *dir, /* {{{ */ + char const *power_supply, + char const *plugin_instance) { + gauge_t capacity_charged = NAN; + gauge_t capacity_full = NAN; + gauge_t capacity_design = NAN; + int status; + + status = + sysfs_file_to_gauge(dir, power_supply, "energy_now", &capacity_charged); + if (status != 0) + return (status); + + status = + sysfs_file_to_gauge(dir, power_supply, "energy_full", &capacity_full); + if (status != 0) + return (status); + + status = sysfs_file_to_gauge(dir, power_supply, "energy_full_design", + &capacity_design); + if (status != 0) + return (status); + + submit_capacity(plugin_instance, capacity_charged * SYSFS_FACTOR, + capacity_full * SYSFS_FACTOR, capacity_design * SYSFS_FACTOR); + return (0); } /* }}} int read_sysfs_capacity */ -static int read_sysfs_callback (char const *dir, /* {{{ */ - char const *power_supply, - void *user_data) -{ - int *battery_index = user_data; - - char const *plugin_instance; - char buffer[32]; - gauge_t v = NAN; - _Bool discharging = 0; - int status; - - /* Ignore non-battery directories, such as AC power. */ - status = sysfs_file_to_buffer (dir, power_supply, "type", buffer, sizeof (buffer)); - if (status != 0) - return (0); - if (strcasecmp ("Battery", buffer) != 0) - return (0); - - (void) sysfs_file_to_buffer (dir, power_supply, "status", buffer, sizeof (buffer)); - if (strcasecmp ("Discharging", buffer) == 0) - discharging = 1; - - /* FIXME: This is a dirty hack for backwards compatibility: The battery - * plugin, for a very long time, has had the plugin_instance - * hard-coded to "0". So, to keep backwards compatibility, we'll use - * "0" for the first battery we find and the power_supply name for all - * following. This should be reverted in a future major version. */ - plugin_instance = (*battery_index == 0) ? "0" : power_supply; - (*battery_index)++; - - read_sysfs_capacity (dir, power_supply, plugin_instance); - - if (sysfs_file_to_gauge (dir, power_supply, "power_now", &v) == 0) - { - if (discharging) - v *= -1.0; - battery_submit (plugin_instance, "power", v * SYSFS_FACTOR); - } - if (sysfs_file_to_gauge (dir, power_supply, "current_now", &v) == 0) - { - if (discharging) - v *= -1.0; - battery_submit (plugin_instance, "current", v * SYSFS_FACTOR); - } - - if (sysfs_file_to_gauge (dir, power_supply, "voltage_now", &v) == 0) - battery_submit (plugin_instance, "voltage", v * SYSFS_FACTOR); - - return (0); +static int read_sysfs_callback(char const *dir, /* {{{ */ + char const *power_supply, void *user_data) { + int *battery_index = user_data; + + char const *plugin_instance; + char buffer[32]; + gauge_t v = NAN; + _Bool discharging = 0; + int status; + + /* Ignore non-battery directories, such as AC power. */ + status = + sysfs_file_to_buffer(dir, power_supply, "type", buffer, sizeof(buffer)); + if (status != 0) + return (0); + if (strcasecmp("Battery", buffer) != 0) + return (0); + + (void)sysfs_file_to_buffer(dir, power_supply, "status", buffer, + sizeof(buffer)); + if (strcasecmp("Discharging", buffer) == 0) + discharging = 1; + + /* FIXME: This is a dirty hack for backwards compatibility: The battery + * plugin, for a very long time, has had the plugin_instance + * hard-coded to "0". So, to keep backwards compatibility, we'll use + * "0" for the first battery we find and the power_supply name for all + * following. This should be reverted in a future major version. */ + plugin_instance = (*battery_index == 0) ? "0" : power_supply; + (*battery_index)++; + + read_sysfs_capacity(dir, power_supply, plugin_instance); + + if (sysfs_file_to_gauge(dir, power_supply, "power_now", &v) == 0) { + if (discharging) + v *= -1.0; + battery_submit(plugin_instance, "power", v * SYSFS_FACTOR); + } + if (sysfs_file_to_gauge(dir, power_supply, "current_now", &v) == 0) { + if (discharging) + v *= -1.0; + battery_submit(plugin_instance, "current", v * SYSFS_FACTOR); + } + + if (sysfs_file_to_gauge(dir, power_supply, "voltage_now", &v) == 0) + battery_submit(plugin_instance, "voltage", v * SYSFS_FACTOR); + + return (0); } /* }}} int read_sysfs_callback */ -static int read_sysfs (void) /* {{{ */ +static int read_sysfs(void) /* {{{ */ { - int status; - int battery_counter = 0; + int status; + int battery_counter = 0; - if (access (SYSFS_PATH, R_OK) != 0) - return (ENOENT); + if (access(SYSFS_PATH, R_OK) != 0) + return (ENOENT); - status = walk_directory (SYSFS_PATH, read_sysfs_callback, - /* user_data = */ &battery_counter, - /* include hidden */ 0); - return (status); + status = walk_directory(SYSFS_PATH, read_sysfs_callback, + /* user_data = */ &battery_counter, + /* include hidden */ 0); + return (status); } /* }}} int read_sysfs */ -static int read_acpi_full_capacity (char const *dir, /* {{{ */ - char const *power_supply, - gauge_t *ret_capacity_full, - gauge_t *ret_capacity_design) +static int read_acpi_full_capacity(char const *dir, /* {{{ */ + char const *power_supply, + gauge_t *ret_capacity_full, + gauge_t *ret_capacity_design) { - char filename[PATH_MAX]; - char buffer[1024]; - - FILE *fh; - - ssnprintf (filename, sizeof (filename), "%s/%s/info", dir, power_supply); - fh = fopen (filename, "r"); - if (fh == NULL) - return (errno); - - /* last full capacity: 40090 mWh */ - while (fgets (buffer, sizeof (buffer), fh) != NULL) - { - gauge_t *value_ptr; - int fields_num; - char *fields[8]; - int index; - - if (strncmp ("last full capacity:", buffer, strlen ("last full capacity:")) == 0) - { - value_ptr = ret_capacity_full; - index = 3; - } - else if (strncmp ("design capacity:", buffer, strlen ("design capacity:")) == 0) - { - value_ptr = ret_capacity_design; - index = 2; - } - else - { - continue; - } - - fields_num = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); - if (fields_num <= index) - continue; - - strtogauge (fields[index], value_ptr); - } - - fclose (fh); - return (0); + char filename[PATH_MAX]; + char buffer[1024]; + + FILE *fh; + + ssnprintf(filename, sizeof(filename), "%s/%s/info", dir, power_supply); + fh = fopen(filename, "r"); + if (fh == NULL) + return (errno); + + /* last full capacity: 40090 mWh */ + while (fgets(buffer, sizeof(buffer), fh) != NULL) { + gauge_t *value_ptr; + int fields_num; + char *fields[8]; + int index; + + if (strncmp("last full capacity:", buffer, strlen("last full capacity:")) == + 0) { + value_ptr = ret_capacity_full; + index = 3; + } else if (strncmp("design capacity:", buffer, + strlen("design capacity:")) == 0) { + value_ptr = ret_capacity_design; + index = 2; + } else { + continue; + } + + fields_num = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields)); + if (fields_num <= index) + continue; + + strtogauge(fields[index], value_ptr); + } + + fclose(fh); + return (0); } /* }}} int read_acpi_full_capacity */ -static int read_acpi_callback (char const *dir, /* {{{ */ - char const *power_supply, - void *user_data) -{ - int *battery_index = user_data; - - gauge_t power = NAN; - gauge_t voltage = NAN; - gauge_t capacity_charged = NAN; - gauge_t capacity_full = NAN; - gauge_t capacity_design = NAN; - _Bool charging = 0; - _Bool is_current = 0; - - char const *plugin_instance; - char filename[PATH_MAX]; - char buffer[1024]; - - FILE *fh; - - ssnprintf (filename, sizeof (filename), "%s/%s/state", dir, power_supply); - fh = fopen (filename, "r"); - if (fh == NULL) - { - if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT)) - return (0); - else - return (errno); - } - - /* - * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state - * [11:00] <@tokkee> present: yes - * [11:00] <@tokkee> capacity state: ok - * [11:00] <@tokkee> charging state: charging - * [11:00] <@tokkee> present rate: 1724 mA - * [11:00] <@tokkee> remaining capacity: 4136 mAh - * [11:00] <@tokkee> present voltage: 12428 mV - */ - while (fgets (buffer, sizeof (buffer), fh) != NULL) - { - char *fields[8]; - int numfields; - - numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); - if (numfields < 3) - continue; - - if ((strcmp (fields[0], "charging") == 0) - && (strcmp (fields[1], "state:") == 0)) - { - if (strcmp (fields[2], "charging") == 0) - charging = 1; - else - charging = 0; - continue; - } - - /* The unit of "present rate" depends on the battery. Modern - * batteries export power (watts), older batteries (used to) - * export current (amperes). We check the fourth column and try - * to find old batteries this way. */ - if ((strcmp (fields[0], "present") == 0) - && (strcmp (fields[1], "rate:") == 0)) - { - strtogauge (fields[2], &power); - - if ((numfields >= 4) && (strcmp ("mA", fields[3]) == 0)) - is_current = 1; - } - else if ((strcmp (fields[0], "remaining") == 0) - && (strcmp (fields[1], "capacity:") == 0)) - strtogauge (fields[2], &capacity_charged); - else if ((strcmp (fields[0], "present") == 0) - && (strcmp (fields[1], "voltage:") == 0)) - strtogauge (fields[2], &voltage); - } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ - - fclose (fh); - - if (!charging) - power *= -1.0; - - /* FIXME: This is a dirty hack for backwards compatibility: The battery - * plugin, for a very long time, has had the plugin_instance - * hard-coded to "0". So, to keep backwards compatibility, we'll use - * "0" for the first battery we find and the power_supply name for all - * following. This should be reverted in a future major version. */ - plugin_instance = (*battery_index == 0) ? "0" : power_supply; - (*battery_index)++; - - read_acpi_full_capacity (dir, power_supply, &capacity_full, &capacity_design); - - submit_capacity (plugin_instance, - capacity_charged * PROC_ACPI_FACTOR, - capacity_full * PROC_ACPI_FACTOR, - capacity_design * PROC_ACPI_FACTOR); - - battery_submit (plugin_instance, - is_current ? "current" : "power", - power * PROC_ACPI_FACTOR); - battery_submit (plugin_instance, "voltage", voltage * PROC_ACPI_FACTOR); - - return 0; +static int read_acpi_callback(char const *dir, /* {{{ */ + char const *power_supply, void *user_data) { + int *battery_index = user_data; + + gauge_t power = NAN; + gauge_t voltage = NAN; + gauge_t capacity_charged = NAN; + gauge_t capacity_full = NAN; + gauge_t capacity_design = NAN; + _Bool charging = 0; + _Bool is_current = 0; + + char const *plugin_instance; + char filename[PATH_MAX]; + char buffer[1024]; + + FILE *fh; + + ssnprintf(filename, sizeof(filename), "%s/%s/state", dir, power_supply); + fh = fopen(filename, "r"); + if (fh == NULL) { + if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT)) + return (0); + else + return (errno); + } + + /* + * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state + * [11:00] <@tokkee> present: yes + * [11:00] <@tokkee> capacity state: ok + * [11:00] <@tokkee> charging state: charging + * [11:00] <@tokkee> present rate: 1724 mA + * [11:00] <@tokkee> remaining capacity: 4136 mAh + * [11:00] <@tokkee> present voltage: 12428 mV + */ + while (fgets(buffer, sizeof(buffer), fh) != NULL) { + char *fields[8]; + int numfields; + + numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields)); + if (numfields < 3) + continue; + + if ((strcmp(fields[0], "charging") == 0) && + (strcmp(fields[1], "state:") == 0)) { + if (strcmp(fields[2], "charging") == 0) + charging = 1; + else + charging = 0; + continue; + } + + /* The unit of "present rate" depends on the battery. Modern + * batteries export power (watts), older batteries (used to) + * export current (amperes). We check the fourth column and try + * to find old batteries this way. */ + if ((strcmp(fields[0], "present") == 0) && + (strcmp(fields[1], "rate:") == 0)) { + strtogauge(fields[2], &power); + + if ((numfields >= 4) && (strcmp("mA", fields[3]) == 0)) + is_current = 1; + } else if ((strcmp(fields[0], "remaining") == 0) && + (strcmp(fields[1], "capacity:") == 0)) + strtogauge(fields[2], &capacity_charged); + else if ((strcmp(fields[0], "present") == 0) && + (strcmp(fields[1], "voltage:") == 0)) + strtogauge(fields[2], &voltage); + } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ + + fclose(fh); + + if (!charging) + power *= -1.0; + + /* FIXME: This is a dirty hack for backwards compatibility: The battery + * plugin, for a very long time, has had the plugin_instance + * hard-coded to "0". So, to keep backwards compatibility, we'll use + * "0" for the first battery we find and the power_supply name for all + * following. This should be reverted in a future major version. */ + plugin_instance = (*battery_index == 0) ? "0" : power_supply; + (*battery_index)++; + + read_acpi_full_capacity(dir, power_supply, &capacity_full, &capacity_design); + + submit_capacity(plugin_instance, capacity_charged * PROC_ACPI_FACTOR, + capacity_full * PROC_ACPI_FACTOR, + capacity_design * PROC_ACPI_FACTOR); + + battery_submit(plugin_instance, is_current ? "current" : "power", + power * PROC_ACPI_FACTOR); + battery_submit(plugin_instance, "voltage", voltage * PROC_ACPI_FACTOR); + + return 0; } /* }}} int read_acpi_callback */ -static int read_acpi (void) /* {{{ */ +static int read_acpi(void) /* {{{ */ { - int status; - int battery_counter = 0; + int status; + int battery_counter = 0; - if (access (PROC_ACPI_PATH, R_OK) != 0) - return (ENOENT); + if (access(PROC_ACPI_PATH, R_OK) != 0) + return (ENOENT); - status = walk_directory (PROC_ACPI_PATH, read_acpi_callback, - /* user_data = */ &battery_counter, - /* include hidden */ 0); - return (status); + status = walk_directory(PROC_ACPI_PATH, read_acpi_callback, + /* user_data = */ &battery_counter, + /* include hidden */ 0); + return (status); } /* }}} int read_acpi */ -static int read_pmu (void) /* {{{ */ +static int read_pmu(void) /* {{{ */ { - int i; - - /* 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++) - { - FILE *fh; - - char buffer[1024]; - char filename[PATH_MAX]; - char plugin_instance[DATA_MAX_NAME_LEN]; - - gauge_t current = NAN; - gauge_t voltage = NAN; - gauge_t charge = NAN; - - ssnprintf (filename, sizeof (filename), PROC_PMU_PATH_FORMAT, i); - if (access (filename, R_OK) != 0) - break; - - ssnprintf (plugin_instance, sizeof (plugin_instance), "%i", i); - - fh = fopen (filename, "r"); - if (fh == NULL) - { - if (errno == ENOENT) - break; - else if ((errno == EAGAIN) || (errno == EINTR)) - continue; - else - return (errno); - } - - while (fgets (buffer, sizeof (buffer), fh) != NULL) - { - char *fields[8]; - int numfields; - - numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); - if (numfields < 3) - continue; - - if (strcmp ("current", fields[0]) == 0) - strtogauge (fields[2], ¤t); - else if (strcmp ("voltage", fields[0]) == 0) - strtogauge (fields[2], &voltage); - else if (strcmp ("charge", fields[0]) == 0) - strtogauge (fields[2], &charge); - } - - fclose (fh); - fh = NULL; - - battery_submit (plugin_instance, "charge", charge / 1000.0); - battery_submit (plugin_instance, "current", current / 1000.0); - battery_submit (plugin_instance, "voltage", voltage / 1000.0); - } - - if (i == 0) - return (ENOENT); - return (0); + 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 < 100; i++) { + FILE *fh; + + char buffer[1024]; + char filename[PATH_MAX]; + char plugin_instance[DATA_MAX_NAME_LEN]; + + gauge_t current = NAN; + gauge_t voltage = NAN; + gauge_t charge = NAN; + + ssnprintf(filename, sizeof(filename), PROC_PMU_PATH_FORMAT, i); + if (access(filename, R_OK) != 0) + break; + + ssnprintf(plugin_instance, sizeof(plugin_instance), "%i", i); + + fh = fopen(filename, "r"); + if (fh == NULL) { + if (errno == ENOENT) + break; + else if ((errno == EAGAIN) || (errno == EINTR)) + continue; + else + return (errno); + } + + while (fgets(buffer, sizeof(buffer), fh) != NULL) { + char *fields[8]; + int numfields; + + numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields)); + if (numfields < 3) + continue; + + if (strcmp("current", fields[0]) == 0) + strtogauge(fields[2], ¤t); + else if (strcmp("voltage", fields[0]) == 0) + strtogauge(fields[2], &voltage); + else if (strcmp("charge", fields[0]) == 0) + strtogauge(fields[2], &charge); + } + + fclose(fh); + fh = NULL; + + battery_submit(plugin_instance, "charge", charge / 1000.0); + battery_submit(plugin_instance, "current", current / 1000.0); + battery_submit(plugin_instance, "voltage", voltage / 1000.0); + } + + if (i == 0) + return (ENOENT); + return (0); } /* }}} int read_pmu */ -static int battery_read (void) /* {{{ */ +static int battery_read(void) /* {{{ */ { - int status; + int status; - DEBUG ("battery plugin: Trying sysfs ..."); - status = read_sysfs (); - if (status == 0) - return (0); + DEBUG("battery plugin: Trying sysfs ..."); + status = read_sysfs(); + if (status == 0) + return (0); - DEBUG ("battery plugin: Trying acpi ..."); - status = read_acpi (); - if (status == 0) - return (0); + DEBUG("battery plugin: Trying acpi ..."); + status = read_acpi(); + if (status == 0) + return (0); - DEBUG ("battery plugin: Trying pmu ..."); - status = read_pmu (); - if (status == 0) - return (0); + DEBUG("battery plugin: Trying pmu ..."); + status = read_pmu(); + if (status == 0) + return (0); - ERROR ("battery plugin: All available input methods failed."); - return (-1); + ERROR("battery plugin: All available input methods failed."); + return (-1); } /* }}} int battery_read */ #endif /* KERNEL_LINUX */ -static int battery_config (oconfig_item_t *ci) -{ - int i; - - for (i = 0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; - - if (strcasecmp ("ValuesPercentage", child->key) == 0) - cf_util_get_boolean (child, &report_percent); - else if (strcasecmp ("ReportDegraded", child->key) == 0) - cf_util_get_boolean (child, &report_degraded); - else - WARNING ("battery plugin: Ignoring unknown " - "configuration option \"%s\".", - child->key); - } - - return (0); +static int battery_config(oconfig_item_t *ci) { + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("ValuesPercentage", child->key) == 0) + cf_util_get_boolean(child, &report_percent); + else if (strcasecmp("ReportDegraded", child->key) == 0) + cf_util_get_boolean(child, &report_degraded); + else + WARNING("battery plugin: Ignoring unknown " + "configuration option \"%s\".", + child->key); + } + + return (0); } /* }}} int battery_config */ -void module_register (void) -{ - plugin_register_complex_config ("battery", battery_config); - plugin_register_read ("battery", battery_read); +void module_register(void) { + plugin_register_complex_config("battery", battery_config); + plugin_register_read("battery", battery_read); } /* void module_register */ diff --git a/src/bind.c b/src/bind.c index 6eac159c..c69c56dc 100644 --- a/src/bind.c +++ b/src/bind.c @@ -24,26 +24,26 @@ #include "config.h" #if STRPTIME_NEEDS_STANDARDS -# ifndef _ISOC99_SOURCE -# define _ISOC99_SOURCE 1 -# endif -# ifndef _POSIX_C_SOURCE -# define _POSIX_C_SOURCE 200112L -# endif -# ifndef _XOPEN_SOURCE -# define _XOPEN_SOURCE 500 -# endif +#ifndef _ISOC99_SOURCE +#define _ISOC99_SOURCE 1 +#endif +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif #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. */ #if HAVE_SYS_SELECT_H -# include +#include #endif #include @@ -51,19 +51,18 @@ #include #ifndef BIND_DEFAULT_URL -# define BIND_DEFAULT_URL "http://localhost:8053/" +#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. */ -typedef int (*list_callback_t) (const char *name, value_t value, - time_t current_time, void *user_data); +typedef int (*list_callback_t)(const char *name, value_t value, + time_t current_time, void *user_data); -struct cb_view_s -{ +struct cb_view_s { char *name; int qtypes; @@ -75,24 +74,21 @@ struct cb_view_s }; typedef struct cb_view_s cb_view_t; -struct translation_info_s -{ +struct translation_info_s { const char *xml_name; const char *type; const char *type_instance; }; typedef struct translation_info_s translation_info_t; -struct translation_table_ptr_s -{ +struct translation_table_ptr_s { const translation_info_t *table; size_t table_length; const char *plugin_instance; }; typedef struct translation_table_ptr_s translation_table_ptr_t; -struct list_info_ptr_s -{ +struct list_info_ptr_s { const char *plugin_instance; const char *type; }; @@ -102,62 +98,62 @@ typedef struct list_info_ptr_s list_info_ptr_t; /* TODO: Remove time parsing code. */ static _Bool config_parse_time = 1; -static char *url = NULL; -static int global_opcodes = 1; -static int global_qtypes = 1; -static int global_server_stats = 1; +static char *url = NULL; +static int global_opcodes = 1; +static int global_qtypes = 1; +static int global_server_stats = 1; static int global_zone_maint_stats = 1; -static int global_resolver_stats = 0; -static int global_memory_stats = 1; -static int timeout = -1; +static int global_resolver_stats = 0; +static int global_memory_stats = 1; +static int timeout = -1; static cb_view_t *views = NULL; -static size_t views_num = 0; +static size_t views_num = 0; static CURL *curl = NULL; -static char *bind_buffer = NULL; +static char *bind_buffer = NULL; static size_t bind_buffer_size = 0; static size_t bind_buffer_fill = 0; -static char bind_curl_error[CURL_ERROR_SIZE]; +static char bind_curl_error[CURL_ERROR_SIZE]; /* Translation table for the `nsstats' values. */ static const translation_info_t nsstats_translation_table[] = /* {{{ */ -{ - /* Requests */ - { "Requestv4", "dns_request", "IPv4" }, - { "Requestv6", "dns_request", "IPv6" }, - { "ReqEdns0", "dns_request", "EDNS0" }, - { "ReqBadEDNSVer", "dns_request", "BadEDNSVer" }, - { "ReqTSIG", "dns_request", "TSIG" }, - { "ReqSIG0", "dns_request", "SIG0" }, - { "ReqBadSIG", "dns_request", "BadSIG" }, - { "ReqTCP", "dns_request", "TCP" }, - /* Rejects */ - { "AuthQryRej", "dns_reject", "authorative" }, - { "RecQryRej", "dns_reject", "recursive" }, - { "XfrRej", "dns_reject", "transfer" }, - { "UpdateRej", "dns_reject", "update" }, - /* Responses */ - { "Response", "dns_response", "normal" }, - { "TruncatedResp", "dns_response", "truncated" }, - { "RespEDNS0", "dns_response", "EDNS0" }, - { "RespTSIG", "dns_response", "TSIG" }, - { "RespSIG0", "dns_response", "SIG0" }, - /* Queries */ - { "QryAuthAns", "dns_query", "authorative" }, - { "QryNoauthAns", "dns_query", "nonauth" }, - { "QryReferral", "dns_query", "referral" }, - { "QryRecursion", "dns_query", "recursion" }, - { "QryDuplicate", "dns_query", "dupliate" }, - { "QryDropped", "dns_query", "dropped" }, - { "QryFailure", "dns_query", "failure" }, - /* Response codes */ - { "QrySuccess", "dns_rcode", "tx-NOERROR" }, - { "QryNxrrset", "dns_rcode", "tx-NXRRSET" }, - { "QrySERVFAIL", "dns_rcode", "tx-SERVFAIL" }, - { "QryFORMERR", "dns_rcode", "tx-FORMERR" }, - { "QryNXDOMAIN", "dns_rcode", "tx-NXDOMAIN" } + { + /* Requests */ + {"Requestv4", "dns_request", "IPv4"}, + {"Requestv6", "dns_request", "IPv6"}, + {"ReqEdns0", "dns_request", "EDNS0"}, + {"ReqBadEDNSVer", "dns_request", "BadEDNSVer"}, + {"ReqTSIG", "dns_request", "TSIG"}, + {"ReqSIG0", "dns_request", "SIG0"}, + {"ReqBadSIG", "dns_request", "BadSIG"}, + {"ReqTCP", "dns_request", "TCP"}, + /* Rejects */ + {"AuthQryRej", "dns_reject", "authorative"}, + {"RecQryRej", "dns_reject", "recursive"}, + {"XfrRej", "dns_reject", "transfer"}, + {"UpdateRej", "dns_reject", "update"}, + /* Responses */ + {"Response", "dns_response", "normal"}, + {"TruncatedResp", "dns_response", "truncated"}, + {"RespEDNS0", "dns_response", "EDNS0"}, + {"RespTSIG", "dns_response", "TSIG"}, + {"RespSIG0", "dns_response", "SIG0"}, + /* Queries */ + {"QryAuthAns", "dns_query", "authorative"}, + {"QryNoauthAns", "dns_query", "nonauth"}, + {"QryReferral", "dns_query", "referral"}, + {"QryRecursion", "dns_query", "recursion"}, + {"QryDuplicate", "dns_query", "dupliate"}, + {"QryDropped", "dns_query", "dropped"}, + {"QryFailure", "dns_query", "failure"}, + /* Response codes */ + {"QrySuccess", "dns_rcode", "tx-NOERROR"}, + {"QryNxrrset", "dns_rcode", "tx-NXRRSET"}, + {"QrySERVFAIL", "dns_rcode", "tx-SERVFAIL"}, + {"QryFORMERR", "dns_rcode", "tx-FORMERR"}, + {"QryNXDOMAIN", "dns_rcode", "tx-NXDOMAIN"} #if 0 { "XfrReqDone", "type", "type_instance" }, { "UpdateReqFwd", "type", "type_instance" }, @@ -169,84 +165,79 @@ static const translation_info_t nsstats_translation_table[] = /* {{{ */ #endif }; static int nsstats_translation_table_length = - STATIC_ARRAY_SIZE (nsstats_translation_table); + STATIC_ARRAY_SIZE(nsstats_translation_table); /* }}} */ /* Translation table for the `zonestats' values. */ static const translation_info_t zonestats_translation_table[] = /* {{{ */ -{ - /* Notify's */ - { "NotifyOutv4", "dns_notify", "tx-IPv4" }, - { "NotifyOutv6", "dns_notify", "tx-IPv6" }, - { "NotifyInv4", "dns_notify", "rx-IPv4" }, - { "NotifyInv6", "dns_notify", "rx-IPv6" }, - { "NotifyRej", "dns_notify", "rejected" }, - /* SOA/AXFS/IXFS requests */ - { "SOAOutv4", "dns_opcode", "SOA-IPv4" }, - { "SOAOutv6", "dns_opcode", "SOA-IPv6" }, - { "AXFRReqv4", "dns_opcode", "AXFR-IPv4" }, - { "AXFRReqv6", "dns_opcode", "AXFR-IPv6" }, - { "IXFRReqv4", "dns_opcode", "IXFR-IPv4" }, - { "IXFRReqv6", "dns_opcode", "IXFR-IPv6" }, - /* Domain transfers */ - { "XfrSuccess", "dns_transfer", "success" }, - { "XfrFail", "dns_transfer", "failure" } -}; + { + /* Notify's */ + {"NotifyOutv4", "dns_notify", "tx-IPv4"}, + {"NotifyOutv6", "dns_notify", "tx-IPv6"}, + {"NotifyInv4", "dns_notify", "rx-IPv4"}, + {"NotifyInv6", "dns_notify", "rx-IPv6"}, + {"NotifyRej", "dns_notify", "rejected"}, + /* SOA/AXFS/IXFS requests */ + {"SOAOutv4", "dns_opcode", "SOA-IPv4"}, + {"SOAOutv6", "dns_opcode", "SOA-IPv6"}, + {"AXFRReqv4", "dns_opcode", "AXFR-IPv4"}, + {"AXFRReqv6", "dns_opcode", "AXFR-IPv6"}, + {"IXFRReqv4", "dns_opcode", "IXFR-IPv4"}, + {"IXFRReqv6", "dns_opcode", "IXFR-IPv6"}, + /* Domain transfers */ + {"XfrSuccess", "dns_transfer", "success"}, + {"XfrFail", "dns_transfer", "failure"}}; static int zonestats_translation_table_length = - STATIC_ARRAY_SIZE (zonestats_translation_table); + STATIC_ARRAY_SIZE(zonestats_translation_table); /* }}} */ /* Translation table for the `resstats' values. */ static const translation_info_t resstats_translation_table[] = /* {{{ */ -{ - /* Generic resolver information */ - { "Queryv4", "dns_query", "IPv4" }, - { "Queryv6", "dns_query", "IPv6" }, - { "Responsev4", "dns_response", "IPv4" }, - { "Responsev6", "dns_response", "IPv6" }, - /* Received response codes */ - { "NXDOMAIN", "dns_rcode", "rx-NXDOMAIN" }, - { "SERVFAIL", "dns_rcode", "rx-SERVFAIL" }, - { "FORMERR", "dns_rcode", "rx-FORMERR" }, - { "OtherError", "dns_rcode", "rx-OTHER" }, - { "EDNS0Fail", "dns_rcode", "rx-EDNS0Fail"}, - /* Received responses */ - { "Mismatch", "dns_response", "mismatch" }, - { "Truncated", "dns_response", "truncated" }, - { "Lame", "dns_response", "lame" }, - { "Retry", "dns_query", "retry" }, + { + /* Generic resolver information */ + {"Queryv4", "dns_query", "IPv4"}, + {"Queryv6", "dns_query", "IPv6"}, + {"Responsev4", "dns_response", "IPv4"}, + {"Responsev6", "dns_response", "IPv6"}, + /* Received response codes */ + {"NXDOMAIN", "dns_rcode", "rx-NXDOMAIN"}, + {"SERVFAIL", "dns_rcode", "rx-SERVFAIL"}, + {"FORMERR", "dns_rcode", "rx-FORMERR"}, + {"OtherError", "dns_rcode", "rx-OTHER"}, + {"EDNS0Fail", "dns_rcode", "rx-EDNS0Fail"}, + /* Received responses */ + {"Mismatch", "dns_response", "mismatch"}, + {"Truncated", "dns_response", "truncated"}, + {"Lame", "dns_response", "lame"}, + {"Retry", "dns_query", "retry"}, #if 0 { "GlueFetchv4", "type", "type_instance" }, { "GlueFetchv6", "type", "type_instance" }, { "GlueFetchv4Fail", "type", "type_instance" }, { "GlueFetchv6Fail", "type", "type_instance" }, #endif - /* DNSSEC information */ - { "ValAttempt", "dns_resolver", "DNSSEC-attempt" }, - { "ValOk", "dns_resolver", "DNSSEC-okay" }, - { "ValNegOk", "dns_resolver", "DNSSEC-negokay" }, - { "ValFail", "dns_resolver", "DNSSEC-fail" } -}; + /* DNSSEC information */ + {"ValAttempt", "dns_resolver", "DNSSEC-attempt"}, + {"ValOk", "dns_resolver", "DNSSEC-okay"}, + {"ValNegOk", "dns_resolver", "DNSSEC-negokay"}, + {"ValFail", "dns_resolver", "DNSSEC-fail"}}; static int resstats_translation_table_length = - STATIC_ARRAY_SIZE (resstats_translation_table); + STATIC_ARRAY_SIZE(resstats_translation_table); /* }}} */ /* Translation table for the `memory/summary' values. */ static const translation_info_t memsummary_translation_table[] = /* {{{ */ -{ - { "TotalUse", "memory", "TotalUse" }, - { "InUse", "memory", "InUse" }, - { "BlockSize", "memory", "BlockSize" }, - { "ContextSize", "memory", "ContextSize" }, - { "Lost", "memory", "Lost" } -}; + {{"TotalUse", "memory", "TotalUse"}, + {"InUse", "memory", "InUse"}, + {"BlockSize", "memory", "BlockSize"}, + {"ContextSize", "memory", "ContextSize"}, + {"Lost", "memory", "Lost"}}; static int memsummary_translation_table_length = - STATIC_ARRAY_SIZE (memsummary_translation_table); + STATIC_ARRAY_SIZE(memsummary_translation_table); /* }}} */ -static void submit (time_t ts, const char *plugin_instance, /* {{{ */ - const char *type, const char *type_instance, value_t value) -{ +static void submit(time_t ts, const char *plugin_instance, /* {{{ */ + const char *type, const char *type_instance, value_t value) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; @@ -255,46 +246,42 @@ static void submit (time_t ts, const char *plugin_instance, /* {{{ */ vl.values = values; vl.values_len = 1; if (config_parse_time) - vl.time = TIME_T_TO_CDTIME_T (ts); + vl.time = TIME_T_TO_CDTIME_T(ts); sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "bind", sizeof(vl.plugin)); if (plugin_instance) { - sstrncpy(vl.plugin_instance, plugin_instance, - sizeof(vl.plugin_instance)); - replace_special (vl.plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance)); + replace_special(vl.plugin_instance, sizeof(vl.plugin_instance)); } sstrncpy(vl.type, type, sizeof(vl.type)); if (type_instance) { - sstrncpy(vl.type_instance, type_instance, - sizeof(vl.type_instance)); - replace_special (vl.type_instance, sizeof (vl.type_instance)); + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); + replace_special(vl.type_instance, sizeof(vl.type_instance)); } plugin_dispatch_values(&vl); } /* }}} void submit */ -static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */ - size_t nmemb, void __attribute__((unused)) *stream) -{ +static size_t bind_curl_callback(void *buf, size_t size, /* {{{ */ + size_t nmemb, + void __attribute__((unused)) * stream) { size_t len = size * nmemb; - if (len <= 0) + if (len == 0) return (len); - if ((bind_buffer_fill + len) >= bind_buffer_size) - { + if ((bind_buffer_fill + len) >= bind_buffer_size) { char *temp; temp = realloc(bind_buffer, bind_buffer_fill + len + 1); - if (temp == NULL) - { - ERROR ("bind plugin: realloc failed."); + if (temp == NULL) { + ERROR("bind plugin: realloc failed."); return (0); } bind_buffer = temp; bind_buffer_size = bind_buffer_fill + len + 1; } - memcpy (bind_buffer + bind_buffer_fill, (char *) buf, len); + memcpy(bind_buffer + bind_buffer_fill, (char *)buf, len); bind_buffer_fill += len; bind_buffer[bind_buffer_fill] = 0; @@ -305,25 +292,19 @@ static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */ * Callback, that's called with a translation table. * (Plugin instance is fixed, type and type instance come from lookup table.) */ -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; +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; if (table == NULL) return (-1); - for (i = 0; i < table->table_length; i++) - { - if (strcmp (table->table[i].xml_name, name) != 0) + for (size_t i = 0; i < table->table_length; i++) { + if (strcmp(table->table[i].xml_name, name) != 0) continue; - submit (current_time, - table->plugin_instance, - table->table[i].type, - table->table[i].type_instance, - value); + submit(current_time, table->plugin_instance, table->table[i].type, + table->table[i].type_instance, value); break; } @@ -334,42 +315,36 @@ static int bind_xml_table_callback (const char *name, value_t value, /* {{{ */ * Callback, that's used for lists. * (Plugin instance and type are fixed, xml name is used as type instance.) */ -static int bind_xml_list_callback (const char *name, /* {{{ */ - value_t value, time_t current_time, void *user_data) -{ - list_info_ptr_t *list_info = (list_info_ptr_t *) user_data; +static int bind_xml_list_callback(const char *name, /* {{{ */ + value_t value, time_t current_time, + void *user_data) { + list_info_ptr_t *list_info = (list_info_ptr_t *)user_data; if (list_info == NULL) return (-1); - submit (current_time, - list_info->plugin_instance, - list_info->type, - /* type instance = */ name, - value); + submit(current_time, list_info->plugin_instance, list_info->type, + /* type instance = */ name, value); return (0); } /* }}} int bind_xml_list_callback */ -static int bind_xml_read_derive (xmlDoc *doc, xmlNode *node, /* {{{ */ - derive_t *ret_value) -{ +static int bind_xml_read_derive(xmlDoc *doc, xmlNode *node, /* {{{ */ + derive_t *ret_value) { char *str_ptr; value_t value; int status; - str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); - if (str_ptr == NULL) - { - ERROR ("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed."); + str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + ERROR("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed."); return (-1); } - status = parse_value (str_ptr, &value, DS_TYPE_DERIVE); - if (status != 0) - { - ERROR ("bind plugin: Parsing string \"%s\" to derive value failed.", - str_ptr); + status = parse_value(str_ptr, &value, DS_TYPE_DERIVE); + if (status != 0) { + ERROR("bind plugin: Parsing string \"%s\" to derive value failed.", + str_ptr); xmlFree(str_ptr); return (-1); } @@ -379,102 +354,92 @@ static int bind_xml_read_derive (xmlDoc *doc, xmlNode *node, /* {{{ */ return (0); } /* }}} int bind_xml_read_derive */ -static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */ - gauge_t *ret_value) -{ +static int bind_xml_read_gauge(xmlDoc *doc, xmlNode *node, /* {{{ */ + gauge_t *ret_value) { char *str_ptr, *end_ptr; double value; - str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); - if (str_ptr == NULL) - { - ERROR ("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed."); + str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + ERROR("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed."); return (-1); } errno = 0; - value = strtod (str_ptr, &end_ptr); + value = strtod(str_ptr, &end_ptr); xmlFree(str_ptr); - if (str_ptr == end_ptr || errno) - { + if (str_ptr == end_ptr || errno) { if (errno && (value < 0)) - ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with underflow."); + ERROR("bind plugin: bind_xml_read_gauge: strtod failed with underflow."); else if (errno && (value > 0)) - ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with overflow."); + ERROR("bind plugin: bind_xml_read_gauge: strtod failed with overflow."); else - ERROR ("bind plugin: bind_xml_read_gauge: strtod failed."); + ERROR("bind plugin: bind_xml_read_gauge: strtod failed."); return (-1); } - *ret_value = (gauge_t) value; + *ret_value = (gauge_t)value; return (0); } /* }}} int bind_xml_read_gauge */ -static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */ - xmlDoc *doc, xmlXPathContext *xpathCtx, time_t *ret_value) -{ +static int bind_xml_read_timestamp(const char *xpath_expression, /* {{{ */ + xmlDoc *doc, xmlXPathContext *xpathCtx, + time_t *ret_value) { xmlXPathObject *xpathObj = NULL; xmlNode *node; char *str_ptr; char *tmp; - struct tm tm; + struct tm tm = {0}; - xpathObj = xmlXPathEvalExpression (BAD_CAST xpath_expression, xpathCtx); - if (xpathObj == NULL) - { - ERROR ("bind plugin: Unable to evaluate XPath expression `%s'.", - xpath_expression); + xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + if (xpathObj == NULL) { + ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", + xpath_expression); return (-1); } - if ((xpathObj->nodesetval == NULL) || (xpathObj->nodesetval->nodeNr < 1)) - { - xmlXPathFreeObject (xpathObj); + if ((xpathObj->nodesetval == NULL) || (xpathObj->nodesetval->nodeNr < 1)) { + xmlXPathFreeObject(xpathObj); return (-1); } - if (xpathObj->nodesetval->nodeNr != 1) - { - NOTICE ("bind plugin: Evaluating the XPath expression `%s' returned " - "%i nodes. Only handling the first one.", - xpath_expression, xpathObj->nodesetval->nodeNr); + if (xpathObj->nodesetval->nodeNr != 1) { + NOTICE("bind plugin: Evaluating the XPath expression `%s' returned " + "%i nodes. Only handling the first one.", + xpath_expression, xpathObj->nodesetval->nodeNr); } node = xpathObj->nodesetval->nodeTab[0]; - if (node->xmlChildrenNode == NULL) - { - ERROR ("bind plugin: bind_xml_read_timestamp: " - "node->xmlChildrenNode == NULL"); - xmlXPathFreeObject (xpathObj); + if (node->xmlChildrenNode == NULL) { + ERROR("bind plugin: bind_xml_read_timestamp: " + "node->xmlChildrenNode == NULL"); + xmlXPathFreeObject(xpathObj); return (-1); } - str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); - if (str_ptr == NULL) - { - ERROR ("bind plugin: bind_xml_read_timestamp: xmlNodeListGetString failed."); - xmlXPathFreeObject (xpathObj); + str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (str_ptr == NULL) { + ERROR("bind plugin: bind_xml_read_timestamp: xmlNodeListGetString failed."); + xmlXPathFreeObject(xpathObj); return (-1); } - memset (&tm, 0, sizeof(tm)); - tmp = strptime (str_ptr, "%Y-%m-%dT%T", &tm); + tmp = strptime(str_ptr, "%Y-%m-%dT%T", &tm); xmlFree(str_ptr); - if (tmp == NULL) - { - ERROR ("bind plugin: bind_xml_read_timestamp: strptime failed."); - xmlXPathFreeObject (xpathObj); + if (tmp == NULL) { + ERROR("bind plugin: bind_xml_read_timestamp: strptime failed."); + xmlXPathFreeObject(xpathObj); return (-1); } *ret_value = mktime(&tm); - xmlXPathFreeObject (xpathObj); + xmlXPathFreeObject(xpathObj); return (0); } /* }}} int bind_xml_read_timestamp */ -/* +/* * bind_parse_generic_name_value * * Reads statistics in the form: @@ -483,83 +448,75 @@ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */ * 123 * */ -static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ */ - list_callback_t list_callback, - void *user_data, - xmlDoc *doc, xmlXPathContext *xpathCtx, - time_t current_time, int ds_type) -{ +static int bind_parse_generic_name_value(const char *xpath_expression, /* {{{ */ + list_callback_t list_callback, + void *user_data, xmlDoc *doc, + xmlXPathContext *xpathCtx, + time_t current_time, int ds_type) { xmlXPathObject *xpathObj = NULL; int num_entries; - int i; xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); - if (xpathObj == NULL) - { + if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", - xpath_expression); + xpath_expression); return (-1); } 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); + DEBUG("bind plugin: bind_parse_generic_name_value: parent->name = %s;", + (char *)parent->name); /* Iterate over all child nodes. */ - for (child = parent->xmlChildrenNode; - child != NULL; - child = child->next) - { + for (xmlNode *child = parent->xmlChildrenNode; child != NULL; + child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; - if (xmlStrcmp (BAD_CAST "name", child->name) == 0) + if (xmlStrcmp(BAD_CAST "name", child->name) == 0) name_node = child; - else if (xmlStrcmp (BAD_CAST "counter", child->name) == 0) + else if (xmlStrcmp(BAD_CAST "counter", child->name) == 0) counter = child; } - if ((name_node != NULL) && (counter != NULL)) - { - char *name = (char *) xmlNodeListGetString (doc, - name_node->xmlChildrenNode, 1); + if ((name_node != NULL) && (counter != NULL)) { + char *name = + (char *)xmlNodeListGetString(doc, name_node->xmlChildrenNode, 1); value_t value; int status; if (ds_type == DS_TYPE_GAUGE) - status = bind_xml_read_gauge (doc, counter, &value.gauge); + status = bind_xml_read_gauge(doc, counter, &value.gauge); else - status = bind_xml_read_derive (doc, counter, &value.derive); + status = bind_xml_read_derive(doc, counter, &value.derive); if (status != 0) continue; - status = (*list_callback) (name, value, current_time, user_data); + status = (*list_callback)(name, value, current_time, user_data); if (status == 0) num_entries++; - xmlFree (name); + xmlFree(name); } } - DEBUG ("bind plugin: Found %d %s for XPath expression `%s'", - num_entries, (num_entries == 1) ? "entry" : "entries", - xpath_expression); + DEBUG("bind plugin: Found %d %s for XPath expression `%s'", num_entries, + (num_entries == 1) ? "entry" : "entries", xpath_expression); xmlXPathFreeObject(xpathObj); return (0); } /* }}} int bind_parse_generic_name_value */ -/* +/* * bind_parse_generic_value_list * * Reads statistics in the form: @@ -570,35 +527,28 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ * * : * */ -static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ */ - list_callback_t list_callback, - void *user_data, - xmlDoc *doc, xmlXPathContext *xpathCtx, - time_t current_time, int ds_type) -{ +static int bind_parse_generic_value_list(const char *xpath_expression, /* {{{ */ + list_callback_t list_callback, + void *user_data, xmlDoc *doc, + xmlXPathContext *xpathCtx, + time_t current_time, int ds_type) { xmlXPathObject *xpathObj = NULL; int num_entries; - int i; xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); - if (xpathObj == NULL) - { + if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", - xpath_expression); + xpath_expression); return (-1); } num_entries = 0; /* Iterate over all matching nodes. */ - for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) - { - xmlNode *child; - + for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); + i++) { /* Iterate over all child nodes. */ - for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; - child != NULL; - child = child->next) - { + for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; + child != NULL; child = child->next) { char *node_name; value_t value; int status; @@ -606,24 +556,23 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ * if (child->type != XML_ELEMENT_NODE) continue; - node_name = (char *) child->name; + node_name = (char *)child->name; if (ds_type == DS_TYPE_GAUGE) - status = bind_xml_read_gauge (doc, child, &value.gauge); + status = bind_xml_read_gauge(doc, child, &value.gauge); else - status = bind_xml_read_derive (doc, child, &value.derive); + status = bind_xml_read_derive(doc, child, &value.derive); if (status != 0) continue; - status = (*list_callback) (node_name, value, current_time, user_data); + status = (*list_callback)(node_name, value, current_time, user_data); if (status == 0) num_entries++; } } - DEBUG ("bind plugin: Found %d %s for XPath expression `%s'", - num_entries, (num_entries == 1) ? "entry" : "entries", - xpath_expression); + DEBUG("bind plugin: Found %d %s for XPath expression `%s'", num_entries, + (num_entries == 1) ? "entry" : "entries", xpath_expression); xmlXPathFreeObject(xpathObj); @@ -641,126 +590,107 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ * * : * */ -static int bind_parse_generic_name_attr_value_list (const char *xpath_expression, /* {{{ */ - list_callback_t list_callback, - void *user_data, - xmlDoc *doc, xmlXPathContext *xpathCtx, - time_t current_time, int ds_type) -{ +static int bind_parse_generic_name_attr_value_list( + const char *xpath_expression, /* {{{ */ + list_callback_t list_callback, void *user_data, xmlDoc *doc, + xmlXPathContext *xpathCtx, time_t current_time, int ds_type) { xmlXPathObject *xpathObj = NULL; int num_entries; - int i; xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); - if (xpathObj == NULL) - { + if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", - xpath_expression); + xpath_expression); return (-1); } num_entries = 0; /* Iterate over all matching nodes. */ - for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) - { - xmlNode *child; - + for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); + i++) { /* Iterate over all child nodes. */ - for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; - child != NULL; - child = child->next) - { + for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; + child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; - if (strncmp ("counter", (char *) child->name, strlen ("counter")) != 0) + if (strncmp("counter", (char *)child->name, strlen("counter")) != 0) continue; char *attr_name; value_t value; int status; - attr_name = (char *) xmlGetProp (child, BAD_CAST "name"); - if (attr_name == NULL) - { - DEBUG ("bind plugin: found without name."); + attr_name = (char *)xmlGetProp(child, BAD_CAST "name"); + if (attr_name == NULL) { + DEBUG("bind plugin: found without name."); continue; } if (ds_type == DS_TYPE_GAUGE) - status = bind_xml_read_gauge (doc, child, &value.gauge); + status = bind_xml_read_gauge(doc, child, &value.gauge); else - status = bind_xml_read_derive (doc, child, &value.derive); + status = bind_xml_read_derive(doc, child, &value.derive); if (status != 0) continue; - status = (*list_callback) (attr_name, value, current_time, user_data); + status = (*list_callback)(attr_name, value, current_time, user_data); if (status == 0) num_entries++; } } - DEBUG ("bind plugin: Found %d %s for XPath expression `%s'", - num_entries, (num_entries == 1) ? "entry" : "entries", - xpath_expression); + DEBUG("bind plugin: Found %d %s for XPath expression `%s'", num_entries, + (num_entries == 1) ? "entry" : "entries", xpath_expression); xmlXPathFreeObject(xpathObj); return (0); } /* }}} int bind_parse_generic_name_attr_value_list */ -static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view, - time_t current_time) -{ +static int bind_xml_stats_handle_zone(int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *path_ctx, xmlNode *node, + cb_view_t *view, time_t current_time) { xmlXPathObject *path_obj; char *zone_name = NULL; - int i; size_t j; - if (version >= 3) - { - char *n = (char *) xmlGetProp (node, BAD_CAST "name"); - char *c = (char *) xmlGetProp (node, BAD_CAST "rdataclass"); - if (n && c) - { - zone_name = (char *) xmlMalloc(strlen(n) + strlen(c) + 2); + if (version >= 3) { + char *n = (char *)xmlGetProp(node, BAD_CAST "name"); + char *c = (char *)xmlGetProp(node, BAD_CAST "rdataclass"); + if (n && c) { + zone_name = (char *)xmlMalloc(strlen(n) + strlen(c) + 2); snprintf(zone_name, strlen(n) + strlen(c) + 2, "%s/%s", n, c); } xmlFree(n); xmlFree(c); - } - else - { - path_obj = xmlXPathEvalExpression (BAD_CAST "name", path_ctx); - if (path_obj == NULL) - { - ERROR ("bind plugin: xmlXPathEvalExpression failed."); + } else { + path_obj = xmlXPathEvalExpression(BAD_CAST "name", path_ctx); + if (path_obj == NULL) { + ERROR("bind plugin: xmlXPathEvalExpression failed."); return (-1); } - for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++) - { - zone_name = (char *) xmlNodeListGetString (doc, - path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1); + 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); if (zone_name != NULL) break; } - xmlXPathFreeObject (path_obj); + xmlXPathFreeObject(path_obj); } - if (zone_name == NULL) - { - ERROR ("bind plugin: Could not determine zone name."); + if (zone_name == NULL) { + ERROR("bind plugin: Could not determine zone name."); return (-1); } - for (j = 0; j < view->zones_num; j++) - { - if (strcasecmp (zone_name, view->zones[j]) == 0) + for (j = 0; j < view->zones_num; j++) { + if (strcasecmp(zone_name, view->zones[j]) == 0) break; } - xmlFree (zone_name); + xmlFree(zone_name); zone_name = NULL; if (j >= view->zones_num) @@ -768,214 +698,181 @@ static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */ zone_name = view->zones[j]; - DEBUG ("bind plugin: bind_xml_stats_handle_zone: Found zone `%s'.", - zone_name); + DEBUG("bind plugin: bind_xml_stats_handle_zone: Found zone `%s'.", zone_name); { /* Parse the tag {{{ */ char plugin_instance[DATA_MAX_NAME_LEN]; - translation_table_ptr_t table_ptr = - { - nsstats_translation_table, - nsstats_translation_table_length, - plugin_instance - }; - - ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-zone-%s", - view->name, zone_name); - - if (version == 3) - { - list_info_ptr_t list_info = - { - plugin_instance, - /* type = */ "dns_qtype" - }; - bind_parse_generic_name_attr_value_list (/* xpath = */ "counters[@type='rcode']", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, path_ctx, current_time, DS_TYPE_COUNTER); - bind_parse_generic_name_attr_value_list (/* xpath = */ "counters[@type='qtype']", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, path_ctx, current_time, DS_TYPE_COUNTER); - } - else - { - bind_parse_generic_value_list (/* xpath = */ "counters", + translation_table_ptr_t table_ptr = {nsstats_translation_table, + nsstats_translation_table_length, + plugin_instance}; + + ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-zone-%s", + view->name, zone_name); + + if (version == 3) { + list_info_ptr_t list_info = {plugin_instance, + /* type = */ "dns_qtype"}; + bind_parse_generic_name_attr_value_list( + /* xpath = */ "counters[@type='rcode']", /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, path_ctx, current_time, DS_TYPE_COUNTER); + /* user_data = */ &table_ptr, doc, path_ctx, current_time, + DS_TYPE_COUNTER); + bind_parse_generic_name_attr_value_list( + /* xpath = */ "counters[@type='qtype']", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, path_ctx, current_time, + DS_TYPE_COUNTER); + } else { + bind_parse_generic_value_list(/* xpath = */ "counters", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, path_ctx, + current_time, DS_TYPE_COUNTER); } } /* }}} */ return (0); } /* }}} int bind_xml_stats_handle_zone */ -static int bind_xml_stats_search_zones (int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view, - time_t current_time) -{ +static int bind_xml_stats_search_zones(int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *path_ctx, xmlNode *node, + cb_view_t *view, time_t current_time) { xmlXPathObject *zone_nodes = NULL; xmlXPathContext *zone_path_context; - int i; - zone_path_context = xmlXPathNewContext (doc); - if (zone_path_context == NULL) - { - ERROR ("bind plugin: xmlXPathNewContext failed."); + zone_path_context = xmlXPathNewContext(doc); + if (zone_path_context == NULL) { + ERROR("bind plugin: xmlXPathNewContext failed."); return (-1); } - zone_nodes = xmlXPathEvalExpression (BAD_CAST "zones/zone", path_ctx); - if (zone_nodes == NULL) - { - ERROR ("bind plugin: Cannot find any tags."); - xmlXPathFreeContext (zone_path_context); + zone_nodes = xmlXPathEvalExpression(BAD_CAST "zones/zone", path_ctx); + if (zone_nodes == NULL) { + ERROR("bind plugin: Cannot find any tags."); + xmlXPathFreeContext(zone_path_context); 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); + assert(node != NULL); zone_path_context->node = node; - bind_xml_stats_handle_zone (version, doc, zone_path_context, node, view, - current_time); + bind_xml_stats_handle_zone(version, doc, zone_path_context, node, view, + current_time); } - xmlXPathFreeObject (zone_nodes); - xmlXPathFreeContext (zone_path_context); + xmlXPathFreeObject(zone_nodes); + xmlXPathFreeContext(zone_path_context); return (0); } /* }}} int bind_xml_stats_search_zones */ -static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *path_ctx, xmlNode *node, time_t current_time) -{ +static int bind_xml_stats_handle_view(int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *path_ctx, xmlNode *node, + time_t current_time) { char *view_name = NULL; cb_view_t *view; - int i; size_t j; - if (version == 3) - { - view_name = (char*) xmlGetProp(node, BAD_CAST "name"); + if (version == 3) { + view_name = (char *)xmlGetProp(node, BAD_CAST "name"); - if (view_name == NULL) - { - ERROR ("bind plugin: Could not determine view name."); + if (view_name == NULL) { + ERROR("bind plugin: Could not determine view name."); return (-1); } - for (j = 0; j < views_num; j++) - { - if (strcasecmp (view_name, views[j].name) == 0) + for (j = 0; j < views_num; j++) { + if (strcasecmp(view_name, views[j].name) == 0) break; } - xmlFree (view_name); + xmlFree(view_name); view_name = NULL; - } - else - { + } else { xmlXPathObject *path_obj; - path_obj = xmlXPathEvalExpression (BAD_CAST "name", path_ctx); - if (path_obj == NULL) - { - ERROR ("bind plugin: xmlXPathEvalExpression failed."); + path_obj = xmlXPathEvalExpression(BAD_CAST "name", path_ctx); + if (path_obj == NULL) { + ERROR("bind plugin: xmlXPathEvalExpression failed."); return (-1); } - for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++) - { - view_name = (char *) xmlNodeListGetString (doc, - path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1); + 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); if (view_name != NULL) break; } - if (view_name == NULL) - { - ERROR ("bind plugin: Could not determine view name."); - xmlXPathFreeObject (path_obj); + if (view_name == NULL) { + ERROR("bind plugin: Could not determine view name."); + xmlXPathFreeObject(path_obj); return (-1); } - for (j = 0; j < views_num; j++) - { - if (strcasecmp (view_name, views[j].name) == 0) + for (j = 0; j < views_num; j++) { + if (strcasecmp(view_name, views[j].name) == 0) break; } - xmlFree (view_name); - xmlXPathFreeObject (path_obj); + xmlFree(view_name); + xmlXPathFreeObject(path_obj); view_name = NULL; path_obj = NULL; } - if (j >= views_num) return (0); view = views + j; - DEBUG ("bind plugin: bind_xml_stats_handle_view: Found view `%s'.", - view->name); + DEBUG("bind plugin: bind_xml_stats_handle_view: Found view `%s'.", + view->name); if (view->qtypes != 0) /* {{{ */ { char plugin_instance[DATA_MAX_NAME_LEN]; - list_info_ptr_t list_info = - { - plugin_instance, - /* type = */ "dns_qtype" - }; - - ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-qtypes", - view->name); - if (version == 3) - { - bind_parse_generic_name_attr_value_list (/* xpath = */ "counters[@type='resqtype']", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, path_ctx, current_time, DS_TYPE_COUNTER); - } - else - { - bind_parse_generic_name_value (/* xpath = */ "rdtype", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, path_ctx, current_time, DS_TYPE_COUNTER); + list_info_ptr_t list_info = {plugin_instance, + /* type = */ "dns_qtype"}; + + ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-qtypes", + view->name); + if (version == 3) { + bind_parse_generic_name_attr_value_list( + /* xpath = */ "counters[@type='resqtype']", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, path_ctx, current_time, + DS_TYPE_COUNTER); + } else { + bind_parse_generic_name_value(/* xpath = */ "rdtype", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, path_ctx, + current_time, DS_TYPE_COUNTER); } } /* }}} */ if (view->resolver_stats != 0) /* {{{ */ { char plugin_instance[DATA_MAX_NAME_LEN]; - translation_table_ptr_t table_ptr = - { - resstats_translation_table, - resstats_translation_table_length, - plugin_instance - }; - - ssnprintf (plugin_instance, sizeof (plugin_instance), - "%s-resolver_stats", view->name); - if (version == 3) - { - bind_parse_generic_name_attr_value_list ("counters[@type='resstats']", + translation_table_ptr_t table_ptr = {resstats_translation_table, + resstats_translation_table_length, + plugin_instance}; + + ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-resolver_stats", + view->name); + if (version == 3) { + bind_parse_generic_name_attr_value_list( + "counters[@type='resstats']", /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, path_ctx, current_time, DS_TYPE_COUNTER); - } - else - { - bind_parse_generic_name_value ("resstat", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, path_ctx, current_time, DS_TYPE_COUNTER); + /* user_data = */ &table_ptr, doc, path_ctx, current_time, + DS_TYPE_COUNTER); + } else { + bind_parse_generic_name_value("resstat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, path_ctx, + current_time, DS_TYPE_COUNTER); } } /* }}} */ @@ -983,71 +880,65 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */ if (view->cacherrsets != 0) /* {{{ */ { char plugin_instance[DATA_MAX_NAME_LEN]; - list_info_ptr_t list_info = - { - plugin_instance, - /* type = */ "dns_qtype_cached" - }; + list_info_ptr_t list_info = {plugin_instance, + /* type = */ "dns_qtype_cached"}; - ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-cache_rr_sets", - view->name); + ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-cache_rr_sets", + view->name); - bind_parse_generic_name_value (/* xpath = */ "cache/rrset", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, path_ctx, current_time, DS_TYPE_GAUGE); + bind_parse_generic_name_value(/* xpath = */ "cache/rrset", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, path_ctx, + current_time, DS_TYPE_GAUGE); } /* }}} */ if (view->zones_num > 0) - bind_xml_stats_search_zones (version, doc, path_ctx, node, view, - current_time); + bind_xml_stats_search_zones(version, doc, path_ctx, node, view, + current_time); return (0); } /* }}} int bind_xml_stats_handle_view */ -static int bind_xml_stats_search_views (int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time) -{ +static int bind_xml_stats_search_views(int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *xpathCtx, + xmlNode *statsnode, + time_t current_time) { xmlXPathObject *view_nodes = NULL; xmlXPathContext *view_path_context; - int i; - view_path_context = xmlXPathNewContext (doc); - if (view_path_context == NULL) - { - ERROR ("bind plugin: xmlXPathNewContext failed."); + view_path_context = xmlXPathNewContext(doc); + if (view_path_context == NULL) { + ERROR("bind plugin: xmlXPathNewContext failed."); return (-1); } - view_nodes = xmlXPathEvalExpression (BAD_CAST "views/view", xpathCtx); - if (view_nodes == NULL) - { - ERROR ("bind plugin: Cannot find any tags."); - xmlXPathFreeContext (view_path_context); + view_nodes = xmlXPathEvalExpression(BAD_CAST "views/view", xpathCtx); + if (view_nodes == NULL) { + ERROR("bind plugin: Cannot find any tags."); + xmlXPathFreeContext(view_path_context); return (-1); } - for (i = 0; i < view_nodes->nodesetval->nodeNr; i++) - { + for (int i = 0; i < view_nodes->nodesetval->nodeNr; i++) { xmlNode *node; node = view_nodes->nodesetval->nodeTab[i]; - assert (node != NULL); + assert(node != NULL); view_path_context->node = node; - bind_xml_stats_handle_view (version, doc, view_path_context, node, - current_time); + bind_xml_stats_handle_view(version, doc, view_path_context, node, + current_time); } - xmlXPathFreeObject (view_nodes); - xmlXPathFreeContext (view_path_context); + xmlXPathFreeObject(view_nodes); + xmlXPathFreeContext(view_path_context); return (0); } /* }}} int bind_xml_stats_search_views */ -static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */ - xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time) -{ +static void bind_xml_stats_v3(xmlDoc *doc, /* {{{ */ + xmlXPathContext *xpathCtx, xmlNode *statsnode, + time_t current_time) { /* XPath: server/counters[@type='opcode'] * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ... * Layout v3: @@ -1056,17 +947,14 @@ static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */ * : * */ - if (global_opcodes != 0) - { - list_info_ptr_t list_info = - { - /* plugin instance = */ "global-opcodes", - /* type = */ "dns_opcode" - }; - bind_parse_generic_name_attr_value_list (/* xpath = */ "server/counters[@type='opcode']", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + if (global_opcodes != 0) { + list_info_ptr_t list_info = {/* plugin instance = */ "global-opcodes", + /* type = */ "dns_opcode"}; + bind_parse_generic_name_attr_value_list( + /* xpath = */ "server/counters[@type='opcode']", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, xpathCtx, current_time, + DS_TYPE_COUNTER); } /* XPath: server/counters[@type='qtype'] @@ -1079,18 +967,15 @@ static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */ * : * */ - if (global_qtypes != 0) - { - list_info_ptr_t list_info = - { - /* plugin instance = */ "global-qtypes", - /* type = */ "dns_qtype" - }; + if (global_qtypes != 0) { + list_info_ptr_t list_info = {/* plugin instance = */ "global-qtypes", + /* type = */ "dns_qtype"}; - bind_parse_generic_name_attr_value_list (/* xpath = */ "server/counters[@type='qtype']", + bind_parse_generic_name_attr_value_list( + /* xpath = */ "server/counters[@type='qtype']", /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + /* user_data = */ &list_info, doc, xpathCtx, current_time, + DS_TYPE_COUNTER); } /* XPath: server/counters[@type='nsstat'] @@ -1109,22 +994,20 @@ static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */ * : * */ - if (global_server_stats) - { - translation_table_ptr_t table_ptr = - { - nsstats_translation_table, - nsstats_translation_table_length, - /* plugin_instance = */ "global-server_stats" - }; + if (global_server_stats) { + translation_table_ptr_t table_ptr = { + nsstats_translation_table, nsstats_translation_table_length, + /* plugin_instance = */ "global-server_stats"}; - bind_parse_generic_name_attr_value_list ("server/counters[@type='nsstat']", + bind_parse_generic_name_attr_value_list( + "server/counters[@type='nsstat']", /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + /* user_data = */ &table_ptr, doc, xpathCtx, current_time, + DS_TYPE_COUNTER); } - /* XPath: server/zonestats, server/zonestat, server/counters[@type='zonestat'] + /* XPath: server/zonestats, server/zonestat, + * server/counters[@type='zonestat'] * Variables: NotifyOutv4, NotifyOutv6, NotifyInv4, NotifyInv6, NotifyRej, * SOAOutv4, SOAOutv6, AXFRReqv4, AXFRReqv6, IXFRReqv4, IXFRReqv6, * XfrSuccess, XfrFail @@ -1135,19 +1018,16 @@ static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */ * : * */ - if (global_zone_maint_stats) - { - translation_table_ptr_t table_ptr = - { - zonestats_translation_table, - zonestats_translation_table_length, - /* plugin_instance = */ "global-zone_maint_stats" - }; + if (global_zone_maint_stats) { + translation_table_ptr_t table_ptr = { + zonestats_translation_table, zonestats_translation_table_length, + /* plugin_instance = */ "global-zone_maint_stats"}; - bind_parse_generic_name_attr_value_list ("server/counters[@type='zonestat']", + bind_parse_generic_name_attr_value_list( + "server/counters[@type='zonestat']", /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + /* user_data = */ &table_ptr, doc, xpathCtx, current_time, + DS_TYPE_COUNTER); } /* XPath: server/resstats, server/counters[@type='resstat'] @@ -1162,25 +1042,22 @@ static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */ * : * */ - if (global_resolver_stats != 0) - { - translation_table_ptr_t table_ptr = - { - resstats_translation_table, - resstats_translation_table_length, - /* plugin_instance = */ "global-resolver_stats" - }; + if (global_resolver_stats != 0) { + translation_table_ptr_t table_ptr = { + resstats_translation_table, resstats_translation_table_length, + /* plugin_instance = */ "global-resolver_stats"}; - bind_parse_generic_name_attr_value_list ("server/counters[@type='resstat']", + bind_parse_generic_name_attr_value_list( + "server/counters[@type='resstat']", /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + /* user_data = */ &table_ptr, doc, xpathCtx, current_time, + DS_TYPE_COUNTER); } } /* }}} bind_xml_stats_v3 */ -static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time) -{ +static void bind_xml_stats_v1_v2(int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *xpathCtx, xmlNode *statsnode, + time_t current_time) { /* XPath: server/requests/opcode, server/counters[@type='opcode'] * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ... * Layout V1 and V2: @@ -1190,18 +1067,14 @@ static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */ * * : */ - if (global_opcodes != 0) - { - list_info_ptr_t list_info = - { - /* plugin instance = */ "global-opcodes", - /* type = */ "dns_opcode" - }; + if (global_opcodes != 0) { + list_info_ptr_t list_info = {/* plugin instance = */ "global-opcodes", + /* type = */ "dns_opcode"}; - bind_parse_generic_name_value (/* xpath = */ "server/requests/opcode", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + bind_parse_generic_name_value(/* xpath = */ "server/requests/opcode", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); } /* XPath: server/queries-in/rdtype, server/counters[@type='qtype'] @@ -1215,18 +1088,14 @@ static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */ * * : */ - if (global_qtypes != 0) - { - list_info_ptr_t list_info = - { - /* plugin instance = */ "global-qtypes", - /* type = */ "dns_qtype" - }; + if (global_qtypes != 0) { + list_info_ptr_t list_info = {/* plugin instance = */ "global-qtypes", + /* type = */ "dns_qtype"}; - bind_parse_generic_name_value (/* xpath = */ "server/queries-in/rdtype", - /* callback = */ bind_xml_list_callback, - /* user_data = */ &list_info, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + bind_parse_generic_name_value(/* xpath = */ "server/queries-in/rdtype", + /* callback = */ bind_xml_list_callback, + /* user_data = */ &list_info, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); } /* XPath: server/nsstats, server/nsstat, server/counters[@type='nsstat'] @@ -1255,32 +1124,26 @@ static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */ * * : */ - if (global_server_stats) - { - translation_table_ptr_t table_ptr = - { - nsstats_translation_table, - nsstats_translation_table_length, - /* plugin_instance = */ "global-server_stats" - }; - - if (version == 1) - { - bind_parse_generic_value_list ("server/nsstats", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); - } - else - { - bind_parse_generic_name_value ("server/nsstat", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + if (global_server_stats) { + translation_table_ptr_t table_ptr = { + nsstats_translation_table, nsstats_translation_table_length, + /* plugin_instance = */ "global-server_stats"}; + + if (version == 1) { + bind_parse_generic_value_list("server/nsstats", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); + } else { + bind_parse_generic_name_value("server/nsstat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); } } - /* XPath: server/zonestats, server/zonestat, server/counters[@type='zonestat'] + /* XPath: server/zonestats, server/zonestat, + * server/counters[@type='zonestat'] * Variables: NotifyOutv4, NotifyOutv6, NotifyInv4, NotifyInv6, NotifyRej, * SOAOutv4, SOAOutv6, AXFRReqv4, AXFRReqv6, IXFRReqv4, IXFRReqv6, * XfrSuccess, XfrFail @@ -1301,28 +1164,21 @@ static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */ * * : */ - if (global_zone_maint_stats) - { - translation_table_ptr_t table_ptr = - { - zonestats_translation_table, - zonestats_translation_table_length, - /* plugin_instance = */ "global-zone_maint_stats" - }; - - if (version == 1) - { - bind_parse_generic_value_list ("server/zonestats", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); - } - else - { - bind_parse_generic_name_value ("server/zonestat", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + if (global_zone_maint_stats) { + translation_table_ptr_t table_ptr = { + zonestats_translation_table, zonestats_translation_table_length, + /* plugin_instance = */ "global-zone_maint_stats"}; + + if (version == 1) { + bind_parse_generic_value_list("server/zonestats", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); + } else { + bind_parse_generic_name_value("server/zonestat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); } } @@ -1348,35 +1204,27 @@ static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */ * * : */ - if (global_resolver_stats != 0) - { - translation_table_ptr_t table_ptr = - { - resstats_translation_table, - resstats_translation_table_length, - /* plugin_instance = */ "global-resolver_stats" - }; - - if (version == 1) - { - bind_parse_generic_value_list ("server/resstats", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); - } - else - { - bind_parse_generic_name_value ("server/resstat", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_COUNTER); + if (global_resolver_stats != 0) { + translation_table_ptr_t table_ptr = { + resstats_translation_table, resstats_translation_table_length, + /* plugin_instance = */ "global-resolver_stats"}; + + if (version == 1) { + bind_parse_generic_value_list("server/resstats", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); + } else { + bind_parse_generic_name_value("server/resstat", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_COUNTER); } } } /* }}} bind_xml_stats_v1_v2 */ -static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *xpathCtx, xmlNode *statsnode) -{ +static int bind_xml_stats(int version, xmlDoc *doc, /* {{{ */ + xmlXPathContext *xpathCtx, xmlNode *statsnode) { time_t current_time = 0; int status; @@ -1384,21 +1232,17 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ /* TODO: Check `server/boot-time' to recognize server restarts. */ - status = bind_xml_read_timestamp ("server/current-time", - doc, xpathCtx, ¤t_time); - if (status != 0) - { - ERROR ("bind plugin: Reading `server/current-time' failed."); + status = bind_xml_read_timestamp("server/current-time", doc, xpathCtx, + ¤t_time); + if (status != 0) { + ERROR("bind plugin: Reading `server/current-time' failed."); return (-1); } - DEBUG ("bind plugin: Current server time is %i.", (int) current_time); + DEBUG("bind plugin: Current server time is %i.", (int)current_time); - if (version == 3) - { + if (version == 3) { bind_xml_stats_v3(doc, xpathCtx, statsnode, current_time); - } - else - { + } else { bind_xml_stats_v1_v2(version, doc, xpathCtx, statsnode, current_time); } @@ -1413,48 +1257,41 @@ static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */ * 0 * */ - if (global_memory_stats != 0) - { - translation_table_ptr_t table_ptr = - { - memsummary_translation_table, - memsummary_translation_table_length, - /* plugin_instance = */ "global-memory_stats" - }; + if (global_memory_stats != 0) { + translation_table_ptr_t table_ptr = { + memsummary_translation_table, memsummary_translation_table_length, + /* plugin_instance = */ "global-memory_stats"}; - bind_parse_generic_value_list ("memory/summary", - /* callback = */ bind_xml_table_callback, - /* user_data = */ &table_ptr, - doc, xpathCtx, current_time, DS_TYPE_GAUGE); + bind_parse_generic_value_list("memory/summary", + /* callback = */ bind_xml_table_callback, + /* user_data = */ &table_ptr, doc, xpathCtx, + current_time, DS_TYPE_GAUGE); } if (views_num > 0) - bind_xml_stats_search_views (version, doc, xpathCtx, statsnode, - current_time); + bind_xml_stats_search_views(version, doc, xpathCtx, statsnode, + current_time); return 0; } /* }}} int bind_xml_stats */ -static int bind_xml (const char *data) /* {{{ */ +static int bind_xml(const char *data) /* {{{ */ { xmlDoc *doc = NULL; xmlXPathContext *xpathCtx = NULL; xmlXPathObject *xpathObj = NULL; int ret = -1; - int i; - doc = xmlParseMemory (data, strlen (data)); - if (doc == NULL) - { - ERROR ("bind plugin: xmlParseMemory failed."); + doc = xmlParseMemory(data, strlen(data)); + if (doc == NULL) { + ERROR("bind plugin: xmlParseMemory failed."); return (-1); } - xpathCtx = xmlXPathNewContext (doc); - if (xpathCtx == NULL) - { - ERROR ("bind plugin: xmlXPathNewContext failed."); - xmlFreeDoc (doc); + xpathCtx = xmlXPathNewContext(doc); + if (xpathCtx == NULL) { + ERROR("bind plugin: xmlXPathNewContext failed."); + xmlFreeDoc(doc); return (-1); } @@ -1462,52 +1299,50 @@ static int bind_xml (const char *data) /* {{{ */ // version 3.* of statistics XML (since BIND9.9) // - xpathObj = xmlXPathEvalExpression (BAD_CAST "/statistics", xpathCtx); - if (xpathObj == NULL || xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr == 0) - { - DEBUG ("bind plugin: Statistics appears not to be v3"); + xpathObj = xmlXPathEvalExpression(BAD_CAST "/statistics", xpathCtx); + if (xpathObj == NULL || xpathObj->nodesetval == NULL || + xpathObj->nodesetval->nodeNr == 0) { + DEBUG("bind plugin: Statistics appears not to be v3"); // we will fallback to v1 or v2 detection - if (xpathObj != NULL) { xmlXPathFreeObject (xpathObj); } - } - else - { - for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) - { + if (xpathObj != NULL) { + xmlXPathFreeObject(xpathObj); + } + } else { + for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++) { xmlNode *node; char *attr_version; node = xpathObj->nodesetval->nodeTab[i]; - assert (node != NULL); + assert(node != NULL); - attr_version = (char *) xmlGetProp (node, BAD_CAST "version"); - if (attr_version == NULL) - { - NOTICE ("bind plugin: Found tag doesn't have a " - "`version' attribute."); + attr_version = (char *)xmlGetProp(node, BAD_CAST "version"); + if (attr_version == NULL) { + NOTICE("bind plugin: Found tag doesn't have a " + "`version' attribute."); continue; } - DEBUG ("bind plugin: Found: ", attr_version); + DEBUG("bind plugin: Found: ", attr_version); - if (strncmp ("3.", attr_version, strlen ("3.")) != 0) - { + if (strncmp("3.", attr_version, strlen("3.")) != 0) { /* TODO: Use the complaint mechanism here. */ - NOTICE ("bind plugin: Found tag with version `%s'. " - "Unfortunately I have no clue how to parse that. " - "Please open a bug report for this.", attr_version); - xmlFree (attr_version); + NOTICE("bind plugin: Found tag with version `%s'. " + "Unfortunately I have no clue how to parse that. " + "Please open a bug report for this.", + attr_version); + xmlFree(attr_version); continue; } - ret = bind_xml_stats (3, doc, xpathCtx, node); + ret = bind_xml_stats(3, doc, xpathCtx, node); - xmlFree (attr_version); + xmlFree(attr_version); /* One node ought to be enough. */ break; } // we are finished, early-return - xmlXPathFreeObject (xpathObj); - xmlXPathFreeContext (xpathCtx); - xmlFreeDoc (doc); + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); return (ret); } @@ -1516,81 +1351,74 @@ static int bind_xml (const char *data) /* {{{ */ // versions 1.* or 2.* of statistics XML // - xpathObj = xmlXPathEvalExpression (BAD_CAST "/isc/bind/statistics", xpathCtx); - if (xpathObj == NULL) - { - ERROR ("bind plugin: Cannot find the tag."); - xmlXPathFreeContext (xpathCtx); - xmlFreeDoc (doc); + xpathObj = xmlXPathEvalExpression(BAD_CAST "/isc/bind/statistics", xpathCtx); + if (xpathObj == NULL) { + ERROR("bind plugin: Cannot find the tag."); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); return (-1); - } - else if (xpathObj->nodesetval == NULL) - { - ERROR ("bind plugin: xmlXPathEvalExpression failed."); - xmlXPathFreeObject (xpathObj); - xmlXPathFreeContext (xpathCtx); - xmlFreeDoc (doc); + } else if (xpathObj->nodesetval == NULL) { + ERROR("bind plugin: xmlXPathEvalExpression failed."); + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); return (-1); } - for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) - { + for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++) { xmlNode *node; char *attr_version; int parsed_version = 0; node = xpathObj->nodesetval->nodeTab[i]; - assert (node != NULL); + assert(node != NULL); - attr_version = (char *) xmlGetProp (node, BAD_CAST "version"); - if (attr_version == NULL) - { - NOTICE ("bind plugin: Found tag doesn't have a " - "`version' attribute."); + attr_version = (char *)xmlGetProp(node, BAD_CAST "version"); + if (attr_version == NULL) { + NOTICE("bind plugin: Found tag doesn't have a " + "`version' attribute."); continue; } - DEBUG ("bind plugin: Found: ", attr_version); + DEBUG("bind plugin: Found: ", attr_version); /* At the time this plugin was written, version "1.0" was used by * BIND 9.5.0, version "2.0" was used by BIND 9.5.1 and 9.6.0. We assume * that "1.*" and "2.*" don't introduce structural changes, so we just * check for the first two characters here. */ - if (strncmp ("1.", attr_version, strlen ("1.")) == 0) + if (strncmp("1.", attr_version, strlen("1.")) == 0) parsed_version = 1; - else if (strncmp ("2.", attr_version, strlen ("2.")) == 0) + else if (strncmp("2.", attr_version, strlen("2.")) == 0) parsed_version = 2; - else - { + else { /* TODO: Use the complaint mechanism here. */ - NOTICE ("bind plugin: Found tag with version `%s'. " - "Unfortunately I have no clue how to parse that. " - "Please open a bug report for this.", attr_version); - xmlFree (attr_version); + NOTICE("bind plugin: Found tag with version `%s'. " + "Unfortunately I have no clue how to parse that. " + "Please open a bug report for this.", + attr_version); + xmlFree(attr_version); continue; } - ret = bind_xml_stats (parsed_version, - doc, xpathCtx, node); + ret = bind_xml_stats(parsed_version, doc, xpathCtx, node); - xmlFree (attr_version); + xmlFree(attr_version); /* One node ought to be enough. */ break; } - xmlXPathFreeObject (xpathObj); - xmlXPathFreeContext (xpathCtx); - xmlFreeDoc (doc); + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); return (ret); } /* }}} int bind_xml */ -static int bind_config_set_bool (const char *name, int *var, /* {{{ */ - oconfig_item_t *ci) -{ - if ((ci->values_num != 1) || ( ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) - { - WARNING ("bind plugin: The `%s' option needs " - "exactly one boolean argument.", name); +static int bind_config_set_bool(const char *name, int *var, /* {{{ */ + oconfig_item_t *ci) { + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) { + WARNING("bind plugin: The `%s' option needs " + "exactly one boolean argument.", + name); return (-1); } @@ -1601,31 +1429,26 @@ static int bind_config_set_bool (const char *name, int *var, /* {{{ */ return 0; } /* }}} int bind_config_set_bool */ -static int bind_config_add_view_zone (cb_view_t *view, /* {{{ */ - oconfig_item_t *ci) -{ +static int bind_config_add_view_zone(cb_view_t *view, /* {{{ */ + oconfig_item_t *ci) { char **tmp; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("bind plugin: The `Zone' option needs " - "exactly one string argument."); + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { + WARNING("bind plugin: The `Zone' option needs " + "exactly one string argument."); return (-1); } - tmp = (char **) realloc (view->zones, - sizeof (char *) * (view->zones_num + 1)); - if (tmp == NULL) - { - ERROR ("bind plugin: realloc failed."); + tmp = realloc(view->zones, sizeof(char *) * (view->zones_num + 1)); + if (tmp == NULL) { + ERROR("bind plugin: realloc failed."); return (-1); } view->zones = tmp; - view->zones[view->zones_num] = strdup (ci->values[0].value.string); - if (view->zones[view->zones_num] == NULL) - { - ERROR ("bind plugin: strdup failed."); + view->zones[view->zones_num] = strdup(ci->values[0].value.string); + if (view->zones[view->zones_num] == NULL) { + ERROR("bind plugin: strdup failed."); return (-1); } view->zones_num++; @@ -1633,57 +1456,52 @@ static int bind_config_add_view_zone (cb_view_t *view, /* {{{ */ return (0); } /* }}} int bind_config_add_view_zone */ -static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */ +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)) - { - WARNING ("bind plugin: `View' blocks need exactly one string argument."); + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { + WARNING("bind plugin: `View' blocks need exactly one string argument."); return (-1); } - tmp = (cb_view_t *) realloc (views, sizeof (*views) * (views_num + 1)); - if (tmp == NULL) - { - ERROR ("bind plugin: realloc failed."); + tmp = realloc(views, sizeof(*views) * (views_num + 1)); + if (tmp == NULL) { + ERROR("bind plugin: realloc failed."); return (-1); } views = tmp; tmp = views + views_num; - memset (tmp, 0, sizeof (*tmp)); + memset(tmp, 0, sizeof(*tmp)); tmp->qtypes = 1; tmp->resolver_stats = 1; tmp->cacherrsets = 1; tmp->zones = NULL; tmp->zones_num = 0; - tmp->name = strdup (ci->values[0].value.string); - if (tmp->name == NULL) - { - ERROR ("bind plugin: strdup failed."); - sfree (views); + tmp->name = strdup(ci->values[0].value.string); + if (tmp->name == NULL) { + ERROR("bind plugin: strdup failed."); + sfree(views); 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 ("QTypes", child->key) == 0) - bind_config_set_bool ("QTypes", &tmp->qtypes, child); - else if (strcasecmp ("ResolverStats", child->key) == 0) - bind_config_set_bool ("ResolverStats", &tmp->resolver_stats, child); - else if (strcasecmp ("CacheRRSets", child->key) == 0) - bind_config_set_bool ("CacheRRSets", &tmp->cacherrsets, child); - else if (strcasecmp ("Zone", child->key) == 0) - bind_config_add_view_zone (tmp, child); - else - { - WARNING ("bind plugin: Unknown configuration option " - "`%s' in view `%s' will be ignored.", child->key, tmp->name); + if (strcasecmp("QTypes", child->key) == 0) + bind_config_set_bool("QTypes", &tmp->qtypes, child); + else if (strcasecmp("ResolverStats", child->key) == 0) + bind_config_set_bool("ResolverStats", &tmp->resolver_stats, child); + else if (strcasecmp("CacheRRSets", child->key) == 0) + bind_config_set_bool("CacheRRSets", &tmp->cacherrsets, child); + else if (strcasecmp("Zone", child->key) == 0) + bind_config_add_view_zone(tmp, child); + else { + WARNING("bind plugin: Unknown configuration option " + "`%s' in view `%s' will be ignored.", + child->key, tmp->name); } } /* for (i = 0; i < ci->children_num; i++) */ @@ -1691,122 +1509,113 @@ static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */ return (0); } /* }}} int bind_config_add_view */ -static int bind_config (oconfig_item_t *ci) /* {{{ */ +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; - if (strcasecmp ("Url", child->key) == 0) { - if ((child->values_num != 1) || (child->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING ("bind plugin: The `Url' option needs " - "exactly one string argument."); + if (strcasecmp("Url", child->key) == 0) { + if ((child->values_num != 1) || + (child->values[0].type != OCONFIG_TYPE_STRING)) { + WARNING("bind plugin: The `Url' option needs " + "exactly one string argument."); return (-1); } - sfree (url); - url = strdup (child->values[0].value.string); - } else if (strcasecmp ("OpCodes", child->key) == 0) - bind_config_set_bool ("OpCodes", &global_opcodes, child); - else if (strcasecmp ("QTypes", child->key) == 0) - bind_config_set_bool ("QTypes", &global_qtypes, child); - else if (strcasecmp ("ServerStats", child->key) == 0) - bind_config_set_bool ("ServerStats", &global_server_stats, child); - else if (strcasecmp ("ZoneMaintStats", child->key) == 0) - bind_config_set_bool ("ZoneMaintStats", &global_zone_maint_stats, child); - else if (strcasecmp ("ResolverStats", child->key) == 0) - bind_config_set_bool ("ResolverStats", &global_resolver_stats, child); - else if (strcasecmp ("MemoryStats", child->key) == 0) - bind_config_set_bool ("MemoryStats", &global_memory_stats, child); - else if (strcasecmp ("View", child->key) == 0) - bind_config_add_view (child); - else if (strcasecmp ("ParseTime", child->key) == 0) - cf_util_get_boolean (child, &config_parse_time); - else if (strcasecmp ("Timeout", child->key) == 0) - cf_util_get_int (child, &timeout); - else - { - WARNING ("bind plugin: Unknown configuration option " - "`%s' will be ignored.", child->key); + sfree(url); + url = strdup(child->values[0].value.string); + } else if (strcasecmp("OpCodes", child->key) == 0) + bind_config_set_bool("OpCodes", &global_opcodes, child); + else if (strcasecmp("QTypes", child->key) == 0) + bind_config_set_bool("QTypes", &global_qtypes, child); + else if (strcasecmp("ServerStats", child->key) == 0) + bind_config_set_bool("ServerStats", &global_server_stats, child); + else if (strcasecmp("ZoneMaintStats", child->key) == 0) + bind_config_set_bool("ZoneMaintStats", &global_zone_maint_stats, child); + else if (strcasecmp("ResolverStats", child->key) == 0) + bind_config_set_bool("ResolverStats", &global_resolver_stats, child); + else if (strcasecmp("MemoryStats", child->key) == 0) + bind_config_set_bool("MemoryStats", &global_memory_stats, child); + else if (strcasecmp("View", child->key) == 0) + bind_config_add_view(child); + else if (strcasecmp("ParseTime", child->key) == 0) + cf_util_get_boolean(child, &config_parse_time); + else if (strcasecmp("Timeout", child->key) == 0) + cf_util_get_int(child, &timeout); + else { + WARNING("bind plugin: Unknown configuration option " + "`%s' will be ignored.", + child->key); } } return (0); } /* }}} int bind_config */ -static int bind_init (void) /* {{{ */ +static int bind_init(void) /* {{{ */ { if (curl != NULL) return (0); - curl = curl_easy_init (); - if (curl == NULL) - { - ERROR ("bind plugin: bind_init: curl_easy_init failed."); + curl = curl_easy_init(); + if (curl == NULL) { + ERROR("bind plugin: bind_init: curl_easy_init failed."); return (-1); } - curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback); - curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); - curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error); - curl_easy_setopt (curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL); - curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, bind_curl_callback); + curl_easy_setopt(curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bind_curl_error); + curl_easy_setopt(curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + 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())); + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, + (timeout >= 0) ? (long)timeout : (long)CDTIME_T_TO_MS( + plugin_get_interval())); #endif - return (0); } /* }}} int bind_init */ -static int bind_read (void) /* {{{ */ +static int bind_read(void) /* {{{ */ { int status; - if (curl == NULL) - { - ERROR ("bind plugin: I don't have a CURL object."); + if (curl == NULL) { + ERROR("bind plugin: I don't have a CURL object."); return (-1); } bind_buffer_fill = 0; - if (curl_easy_perform (curl) != CURLE_OK) - { - ERROR ("bind plugin: curl_easy_perform failed: %s", - bind_curl_error); + if (curl_easy_perform(curl) != CURLE_OK) { + ERROR("bind plugin: curl_easy_perform failed: %s", bind_curl_error); return (-1); } - status = bind_xml (bind_buffer); + status = bind_xml(bind_buffer); if (status != 0) return (-1); else return (0); } /* }}} int bind_read */ -static int bind_shutdown (void) /* {{{ */ +static int bind_shutdown(void) /* {{{ */ { - if (curl != NULL) - { - curl_easy_cleanup (curl); + if (curl != NULL) { + curl_easy_cleanup(curl); curl = NULL; } return (0); } /* }}} int bind_shutdown */ -void module_register (void) -{ - plugin_register_complex_config ("bind", bind_config); - plugin_register_init ("bind", bind_init); - plugin_register_read ("bind", bind_read); - plugin_register_shutdown ("bind", bind_shutdown); +void module_register(void) { + plugin_register_complex_config("bind", bind_config); + plugin_register_init("bind", bind_init); + plugin_register_read("bind", bind_read); + plugin_register_shutdown("bind", bind_shutdown); } /* void module_register */ /* vim: set sw=2 sts=2 ts=8 et fdm=marker : */ diff --git a/src/ceph.c b/src/ceph.c index 9c53a3e7..2be17fb3 100644 --- a/src/ceph.c +++ b/src/ceph.c @@ -27,6 +27,7 @@ #define _BSD_SOURCE #include "collectd.h" + #include "common.h" #include "plugin.h" @@ -37,43 +38,45 @@ #if HAVE_YAJL_YAJL_VERSION_H #include #endif +#ifdef HAVE_SYS_CAPABILITY_H +#include +#endif +#include #include +#include #include #include #include #include #include #include -#include #include #include #include #include -#include -#include #define RETRY_AVGCOUNT -1 #if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1) -# define HAVE_YAJL_V2 1 +#define HAVE_YAJL_V2 1 #endif -#define RETRY_ON_EINTR(ret, expr) \ - while(1) { \ - ret = expr; \ - if(ret >= 0) \ - break; \ - ret = -errno; \ - if(ret != -EINTR) \ - break; \ - } +#define RETRY_ON_EINTR(ret, expr) \ + while (1) { \ + ret = expr; \ + if (ret >= 0) \ + break; \ + ret = -errno; \ + if (ret != -EINTR) \ + break; \ + } /** Timeout interval in seconds */ #define CEPH_TIMEOUT_INTERVAL 1 /** Maximum path length for a UNIX domain socket on this system */ -#define UNIX_DOMAIN_SOCK_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path)) +#define UNIX_DOMAIN_SOCK_PATH_MAX (sizeof(((struct sockaddr_un *)0)->sun_path)) /** Yajl callback returns */ #define CEPH_CB_CONTINUE 1 @@ -88,63 +91,60 @@ typedef unsigned int yajl_len_t; /** Number of types for ceph defined in types.db */ #define CEPH_DSET_TYPES_NUM 3 /** ceph types enum */ -enum ceph_dset_type_d -{ - DSET_LATENCY = 0, - DSET_BYTES = 1, - DSET_RATE = 2, - DSET_TYPE_UNFOUND = 1000 +enum ceph_dset_type_d { + DSET_LATENCY = 0, + DSET_BYTES = 1, + DSET_RATE = 2, + DSET_TYPE_UNFOUND = 1000 }; /** Valid types for ceph defined in types.db */ -const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] = - {"ceph_latency", "ceph_bytes", "ceph_rate"}; +static const char *const ceph_dset_types[CEPH_DSET_TYPES_NUM] = { + "ceph_latency", "ceph_bytes", "ceph_rate"}; /******* ceph_daemon *******/ -struct ceph_daemon -{ - /** Version of the admin_socket interface */ - uint32_t version; - /** daemon name **/ - char name[DATA_MAX_NAME_LEN]; - - /** Path to the socket that we use to talk to the ceph daemon */ - char asok_path[UNIX_DOMAIN_SOCK_PATH_MAX]; - - /** Number of counters */ - int ds_num; - /** Track ds types */ - uint32_t *ds_types; - /** Track ds names to match with types */ - char **ds_names; - - /** - * Keep track of last data for latency values so we can calculate rate - * since last poll. - */ - struct last_data **last_poll_data; - /** index of last poll data */ - int last_idx; +struct ceph_daemon { + /** Version of the admin_socket interface */ + uint32_t version; + /** daemon name **/ + char name[DATA_MAX_NAME_LEN]; + + /** Path to the socket that we use to talk to the ceph daemon */ + char asok_path[UNIX_DOMAIN_SOCK_PATH_MAX]; + + /** Number of counters */ + int ds_num; + /** Track ds types */ + uint32_t *ds_types; + /** Track ds names to match with types */ + char **ds_names; + + /** + * Keep track of last data for latency values so we can calculate rate + * since last poll. + */ + struct last_data **last_poll_data; + /** index of last poll data */ + int last_idx; }; /******* JSON parsing *******/ -typedef int (*node_handler_t)(void *, const char*, const char*); +typedef int (*node_handler_t)(void *, const char *, const char *); /** Track state and handler while parsing JSON */ -struct yajl_struct -{ - node_handler_t handler; - void * handler_arg; - - char *key; - char *stack[YAJL_MAX_DEPTH]; - size_t depth; +struct yajl_struct { + node_handler_t handler; + void *handler_arg; + + char *key; + char *stack[YAJL_MAX_DEPTH]; + size_t depth; }; typedef struct yajl_struct yajl_struct; -enum perfcounter_type_d -{ - PERFCOUNTER_LATENCY = 0x4, PERFCOUNTER_DERIVE = 0x8, +enum perfcounter_type_d { + PERFCOUNTER_LATENCY = 0x4, + PERFCOUNTER_DERIVE = 0x8, }; /** Give user option to use default (long run = since daemon started) avg */ @@ -164,425 +164,381 @@ static int convert_special_metrics = 1; 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. */ -struct values_tmp -{ - /** ceph daemon we are processing data for*/ - struct ceph_daemon *d; - /** track avgcount across counters for avgcount/sum latency pairs */ - uint64_t avgcount; - /** current index of counters - used to get type of counter */ - int index; - /** do we already have an avgcount for latency pair */ - int avgcount_exists; - /** - * similar to index, but current index of latency type counters - - * used to get last poll data of counter - */ - int latency_index; - /** - * values list - maintain across counters since - * host/plugin/plugin instance are always the same - */ - value_list_t vlist; +struct values_tmp { + /** ceph daemon we are processing data for*/ + struct ceph_daemon *d; + /** track avgcount across counters for avgcount/sum latency pairs */ + uint64_t avgcount; + /** current index of counters - used to get type of counter */ + int index; + /** do we already have an avgcount for latency pair */ + int avgcount_exists; + /** + * similar to index, but current index of latency type counters - + * used to get last poll data of counter + */ + int latency_index; + /** + * values list - maintain across counters since + * host/plugin/plugin instance are always the same + */ + value_list_t vlist; }; /** * A set of count/sum pairs to keep track of latency types and get difference * between this poll data and last poll data. */ -struct last_data -{ - char ds_name[DATA_MAX_NAME_LEN]; - double last_sum; - uint64_t last_count; +struct last_data { + char ds_name[DATA_MAX_NAME_LEN]; + double last_sum; + uint64_t last_count; }; /******* network I/O *******/ -enum cstate_t -{ - CSTATE_UNCONNECTED = 0, - CSTATE_WRITE_REQUEST, - CSTATE_READ_VERSION, - CSTATE_READ_AMT, - CSTATE_READ_JSON, +enum cstate_t { + CSTATE_UNCONNECTED = 0, + CSTATE_WRITE_REQUEST, + CSTATE_READ_VERSION, + CSTATE_READ_AMT, + CSTATE_READ_JSON, }; -enum request_type_t -{ - ASOK_REQ_VERSION = 0, - ASOK_REQ_DATA = 1, - ASOK_REQ_SCHEMA = 2, - ASOK_REQ_NONE = 1000, +enum request_type_t { + ASOK_REQ_VERSION = 0, + ASOK_REQ_DATA = 1, + ASOK_REQ_SCHEMA = 2, + ASOK_REQ_NONE = 1000, }; -struct cconn -{ - /** The Ceph daemon that we're talking to */ - struct ceph_daemon *d; +struct cconn { + /** The Ceph daemon that we're talking to */ + struct ceph_daemon *d; - /** Request type */ - uint32_t request_type; + /** Request type */ + uint32_t request_type; - /** The connection state */ - enum cstate_t state; + /** The connection state */ + enum cstate_t state; - /** The socket we use to talk to this daemon */ - int asok; + /** The socket we use to talk to this daemon */ + int asok; - /** The amount of data remaining to read / write. */ - uint32_t amt; + /** The amount of data remaining to read / write. */ + uint32_t amt; - /** Length of the JSON to read */ - uint32_t json_len; + /** Length of the JSON to read */ + uint32_t json_len; - /** Buffer containing JSON data */ - unsigned char *json; + /** Buffer containing JSON data */ + unsigned char *json; - /** Keep data important to yajl processing */ - struct yajl_struct yajl; + /** Keep data important to yajl processing */ + struct yajl_struct yajl; }; -static int ceph_cb_null(void *ctx) -{ - return CEPH_CB_CONTINUE; -} - -static int ceph_cb_boolean(void *ctx, int bool_val) -{ - return CEPH_CB_CONTINUE; -} - -#define BUFFER_ADD(dest, src) do { \ - size_t dest_size = sizeof (dest); \ - strncat ((dest), (src), dest_size - strlen (dest)); \ - (dest)[dest_size - 1] = 0; \ -} while (0) - -static int -ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len) -{ - yajl_struct *state = (yajl_struct*) ctx; - char buffer[number_len+1]; - char key[2 * DATA_MAX_NAME_LEN]; - _Bool latency_type = 0; - size_t i; - int status; - - memcpy(buffer, number_val, number_len); - buffer[sizeof(buffer) - 1] = 0; - - memset (key, 0, sizeof (key)); - for (i = 0; i < state->depth; i++) - { - if (state->stack[i] == NULL) - continue; - - if (strlen (key) != 0) - BUFFER_ADD (key, "."); - BUFFER_ADD (key, state->stack[i]); - } - - /* Special case for latency metrics. */ - if ((strcmp ("avgcount", state->key) == 0) - || (strcmp ("sum", state->key) == 0)) - { - latency_type = 1; - - /* 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 - * a single "Derive" type. To spare further confusion, keep this KPI as - * the same type of other "Bytes". Instead of keeping an "average" or - * "rate", use the "sum" in the pair and assign that to the derive - * value. */ - if (convert_special_metrics && (state->depth >= 2) - && (strcmp("filestore", state->stack[state->depth - 2]) == 0) - && (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0) - && (strcmp("avgcount", state->key) == 0)) - { - DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes"); - return CEPH_CB_CONTINUE; - } - } - else /* not a latency type */ - { - BUFFER_ADD (key, "."); - BUFFER_ADD (key, state->key); - } +static int ceph_cb_null(void *ctx) { return CEPH_CB_CONTINUE; } + +static int ceph_cb_boolean(void *ctx, int bool_val) { return CEPH_CB_CONTINUE; } + +#define BUFFER_ADD(dest, src) \ + do { \ + size_t dest_size = sizeof(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) + +static int ceph_cb_number(void *ctx, const char *number_val, + yajl_len_t number_len) { + yajl_struct *state = (yajl_struct *)ctx; + char buffer[number_len + 1]; + char key[2 * DATA_MAX_NAME_LEN] = {0}; + _Bool latency_type = 0; + int status; + + memcpy(buffer, number_val, number_len); + buffer[sizeof(buffer) - 1] = '\0'; + + for (size_t i = 0; i < state->depth; i++) { + if (state->stack[i] == NULL) + continue; + + if (strlen(key) != 0) + BUFFER_ADD(key, "."); + BUFFER_ADD(key, state->stack[i]); + } + + /* Special case for latency metrics. */ + if ((strcmp("avgcount", state->key) == 0) || + (strcmp("sum", state->key) == 0)) { + 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 + * a single "Derive" type. To spare further confusion, keep this KPI as + * the same type of other "Bytes". Instead of keeping an "average" or + * "rate", use the "sum" in the pair and assign that to the derive + * value. */ + if (convert_special_metrics && (state->depth >= 2) && + (strcmp("filestore", state->stack[state->depth - 2]) == 0) && + (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0) && + (strcmp("avgcount", state->key) == 0)) { + DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes"); + return CEPH_CB_CONTINUE; + } + } else /* not a latency type */ + { + BUFFER_ADD(key, "."); + BUFFER_ADD(key, state->key); + } + + status = state->handler(state->handler_arg, buffer, key); + if ((status == RETRY_AVGCOUNT) && latency_type) { + /* Add previously skipped part of the key, either "avgcount" or "sum", + * and try again. */ + BUFFER_ADD(key, "."); + BUFFER_ADD(key, state->key); status = state->handler(state->handler_arg, buffer, key); - if((status == RETRY_AVGCOUNT) && latency_type) - { - /* Add previously skipped part of the key, either "avgcount" or "sum", - * and try again. */ - BUFFER_ADD (key, "."); - BUFFER_ADD (key, state->key); - - status = state->handler(state->handler_arg, buffer, key); - } + } - if (status != 0) - { - ERROR("ceph plugin: JSON handler failed with status %d.", status); - return CEPH_CB_ABORT; - } + if (status != 0) { + ERROR("ceph plugin: JSON handler failed with status %d.", status); + return CEPH_CB_ABORT; + } - return CEPH_CB_CONTINUE; + return CEPH_CB_CONTINUE; } static int ceph_cb_string(void *ctx, const unsigned char *string_val, - yajl_len_t string_len) -{ - return CEPH_CB_CONTINUE; + yajl_len_t string_len) { + return CEPH_CB_CONTINUE; } -static int ceph_cb_start_map(void *ctx) -{ - yajl_struct *state = (yajl_struct*) ctx; +static int ceph_cb_start_map(void *ctx) { + yajl_struct *state = (yajl_struct *)ctx; - /* Push key to the stack */ - if (state->depth == YAJL_MAX_DEPTH) - return CEPH_CB_ABORT; + /* Push key to the stack */ + if (state->depth == YAJL_MAX_DEPTH) + return CEPH_CB_ABORT; - state->stack[state->depth] = state->key; - state->depth++; - state->key = NULL; + state->stack[state->depth] = state->key; + state->depth++; + state->key = NULL; - return CEPH_CB_CONTINUE; + return CEPH_CB_CONTINUE; } -static int ceph_cb_end_map(void *ctx) -{ - yajl_struct *state = (yajl_struct*) ctx; +static int ceph_cb_end_map(void *ctx) { + yajl_struct *state = (yajl_struct *)ctx; - /* Pop key from the stack */ - if (state->depth == 0) - return CEPH_CB_ABORT; + /* Pop key from the stack */ + if (state->depth == 0) + return CEPH_CB_ABORT; - sfree (state->key); - state->depth--; - state->key = state->stack[state->depth]; - state->stack[state->depth] = NULL; + sfree(state->key); + state->depth--; + state->key = state->stack[state->depth]; + state->stack[state->depth] = NULL; - return CEPH_CB_CONTINUE; + return CEPH_CB_CONTINUE; } -static int -ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len) -{ - yajl_struct *state = (yajl_struct*) ctx; - size_t sz = ((size_t) string_len) + 1; - - sfree (state->key); - state->key = malloc (sz); - if (state->key == NULL) - { - ERROR ("ceph plugin: malloc failed."); - return CEPH_CB_ABORT; - } +static int ceph_cb_map_key(void *ctx, const unsigned char *key, + yajl_len_t string_len) { + yajl_struct *state = (yajl_struct *)ctx; + size_t sz = ((size_t)string_len) + 1; - memmove (state->key, key, sz - 1); - state->key[sz - 1] = 0; + sfree(state->key); + state->key = malloc(sz); + if (state->key == NULL) { + ERROR("ceph plugin: malloc failed."); + return CEPH_CB_ABORT; + } - return CEPH_CB_CONTINUE; -} + memmove(state->key, key, sz - 1); + state->key[sz - 1] = 0; -static int ceph_cb_start_array(void *ctx) -{ - return CEPH_CB_CONTINUE; + return CEPH_CB_CONTINUE; } -static int ceph_cb_end_array(void *ctx) -{ - return CEPH_CB_CONTINUE; -} +static int ceph_cb_start_array(void *ctx) { return CEPH_CB_CONTINUE; } -static yajl_callbacks callbacks = { - ceph_cb_null, - ceph_cb_boolean, - NULL, - NULL, - ceph_cb_number, - ceph_cb_string, - ceph_cb_start_map, - ceph_cb_map_key, - ceph_cb_end_map, - ceph_cb_start_array, - ceph_cb_end_array -}; +static int ceph_cb_end_array(void *ctx) { return CEPH_CB_CONTINUE; } -static void ceph_daemon_print(const struct ceph_daemon *d) -{ - DEBUG("ceph plugin: name=%s, asok_path=%s", d->name, d->asok_path); +static yajl_callbacks callbacks = {ceph_cb_null, + ceph_cb_boolean, + NULL, + NULL, + ceph_cb_number, + ceph_cb_string, + ceph_cb_start_map, + ceph_cb_map_key, + ceph_cb_end_map, + ceph_cb_start_array, + ceph_cb_end_array}; + +static void ceph_daemon_print(const struct ceph_daemon *d) { + DEBUG("ceph plugin: name=%s, asok_path=%s", d->name, d->asok_path); } -static void ceph_daemons_print(void) -{ - int i; - for(i = 0; i < g_num_daemons; ++i) - { - ceph_daemon_print(g_daemons[i]); - } +static void ceph_daemons_print(void) { + 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++) - { - 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++) - { - sfree(d->ds_names[i]); - } - sfree(d->ds_types); - sfree(d->ds_names); - sfree(d); +static void ceph_daemon_free(struct ceph_daemon *d) { + 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 (int i = 0; i < d->ds_num; i++) { + sfree(d->ds_names[i]); + } + sfree(d->ds_types); + sfree(d->ds_names); + sfree(d); } /* compact_ds_name removed the special characters ":", "_", "-" and "+" from the * intput string. Characters following these special characters are capitalized. * Trailing "+" and "-" characters are replaces with the strings "Plus" and * "Minus". */ -static int compact_ds_name (char *buffer, size_t buffer_size, char const *src) -{ - char *src_copy; - size_t src_len; - char *ptr = buffer; - size_t ptr_size = buffer_size; - _Bool append_plus = 0; - _Bool append_minus = 0; - - if ((buffer == NULL) || (buffer_size <= strlen ("Minus")) || (src == NULL)) - return EINVAL; - - src_copy = strdup (src); - src_len = strlen(src); - - /* Remove trailing "+" and "-". */ - if (src_copy[src_len - 1] == '+') - { - append_plus = 1; - src_len--; - src_copy[src_len] = 0; - } - else if (src_copy[src_len - 1] == '-') - { - append_minus = 1; - src_len--; - src_copy[src_len] = 0; - } - - /* Split at special chars, capitalize first character, append to buffer. */ - char *dummy = src_copy; - char *token; - char *save_ptr = NULL; - while ((token = strtok_r (dummy, ":_-+", &save_ptr)) != NULL) - { - size_t len; - - dummy = NULL; - - token[0] = toupper ((int) token[0]); - - assert (ptr_size > 1); - - len = strlen (token); - if (len >= ptr_size) - len = ptr_size - 1; - - assert (len > 0); - assert (len < ptr_size); - - sstrncpy (ptr, token, len + 1); - ptr += len; - ptr_size -= len; - - assert (*ptr == 0); - if (ptr_size <= 1) - break; - } - - /* Append "Plus" or "Minus" if "+" or "-" has been stripped above. */ - if (append_plus || append_minus) - { - char const *append = "Plus"; - if (append_minus) - append = "Minus"; - - size_t offset = buffer_size - (strlen (append) + 1); - if (offset > strlen (buffer)) - offset = strlen (buffer); - - sstrncpy (buffer + offset, append, buffer_size - offset); - } - - sfree (src_copy); - return 0; +static int compact_ds_name(char *buffer, size_t buffer_size, char const *src) { + char *src_copy; + size_t src_len; + char *ptr = buffer; + size_t ptr_size = buffer_size; + _Bool append_plus = 0; + _Bool append_minus = 0; + + if ((buffer == NULL) || (buffer_size <= strlen("Minus")) || (src == NULL)) + return EINVAL; + + src_copy = strdup(src); + src_len = strlen(src); + + /* Remove trailing "+" and "-". */ + if (src_copy[src_len - 1] == '+') { + append_plus = 1; + src_len--; + src_copy[src_len] = 0; + } else if (src_copy[src_len - 1] == '-') { + append_minus = 1; + src_len--; + src_copy[src_len] = 0; + } + + /* Split at special chars, capitalize first character, append to buffer. */ + char *dummy = src_copy; + char *token; + char *save_ptr = NULL; + while ((token = strtok_r(dummy, ":_-+", &save_ptr)) != NULL) { + size_t len; + + dummy = NULL; + + token[0] = toupper((int)token[0]); + + assert(ptr_size > 1); + + len = strlen(token); + if (len >= ptr_size) + len = ptr_size - 1; + + assert(len > 0); + assert(len < ptr_size); + + sstrncpy(ptr, token, len + 1); + ptr += len; + ptr_size -= len; + + assert(*ptr == 0); + if (ptr_size <= 1) + break; + } + + /* Append "Plus" or "Minus" if "+" or "-" has been stripped above. */ + if (append_plus || append_minus) { + char const *append = "Plus"; + if (append_minus) + append = "Minus"; + + size_t offset = buffer_size - (strlen(append) + 1); + if (offset > strlen(buffer)) + offset = strlen(buffer); + + sstrncpy(buffer + offset, append, buffer_size - offset); + } + + sfree(src_copy); + return 0; } -static _Bool has_suffix (char const *str, char const *suffix) -{ - size_t str_len = strlen (str); - size_t suffix_len = strlen (suffix); - size_t offset; +static _Bool has_suffix(char const *str, char const *suffix) { + size_t str_len = strlen(str); + size_t suffix_len = strlen(suffix); + size_t offset; - if (suffix_len > str_len) - return 0; - offset = str_len - suffix_len; + if (suffix_len > str_len) + return 0; + offset = str_len - suffix_len; - if (strcmp (str + offset, suffix) == 0) - return 1; + if (strcmp(str + offset, suffix) == 0) + return 1; - return 0; + return 0; } /* 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; +static size_t count_parts(char const *key) { + size_t parts_num = 0; - for (ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.')) - parts_num++; + for (const char *ptr = key; ptr != NULL; ptr = strchr(ptr + 1, '.')) + parts_num++; - return parts_num; + return parts_num; } /** * Parse key to remove "type" if this is for schema and initiate compaction */ -static int parse_keys (char *buffer, size_t buffer_size, const char *key_str) -{ - char tmp[2 * buffer_size]; +static int parse_keys(char *buffer, size_t buffer_size, const char *key_str) { + char tmp[2 * buffer_size]; - if (buffer == NULL || buffer_size == 0 || key_str == NULL || strlen (key_str) == 0) - return EINVAL; + if (buffer == NULL || buffer_size == 0 || key_str == NULL || + strlen(key_str) == 0) + return EINVAL; - if ((count_parts (key_str) > 2) && has_suffix (key_str, ".type")) - { - /* strip ".type" suffix iff the key has more than two parts. */ - size_t sz = strlen (key_str) - strlen (".type") + 1; + if ((count_parts(key_str) > 2) && has_suffix(key_str, ".type")) { + /* strip ".type" suffix iff the key has more than two parts. */ + size_t sz = strlen(key_str) - strlen(".type") + 1; - if (sz > sizeof (tmp)) - sz = sizeof (tmp); - sstrncpy (tmp, key_str, sz); - } - else - { - sstrncpy (tmp, key_str, sizeof (tmp)); - } + if (sz > sizeof(tmp)) + sz = sizeof(tmp); + sstrncpy(tmp, key_str, sz); + } else { + sstrncpy(tmp, key_str, sizeof(tmp)); + } - return compact_ds_name (buffer, buffer_size, tmp); + return compact_ds_name(buffer, buffer_size, tmp); } /** @@ -590,324 +546,270 @@ static int parse_keys (char *buffer, size_t buffer_size, const char *key_str) * data processing */ static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name, - int pc_type) -{ - uint32_t type; - char ds_name[DATA_MAX_NAME_LEN]; - memset(ds_name, 0, sizeof(ds_name)); - - if(convert_special_metrics) - { - /** - * Special case for filestore:JournalWrBytes. 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 a single "Derive" - * type. To spare further confusion, keep this KPI as the same type of - * other "Bytes". Instead of keeping an "average" or "rate", use the - * "sum" in the pair and assign that to the derive value. - */ - if((strcmp(name,"filestore.journal_wr_bytes.type") == 0)) - { - pc_type = 10; - } - } + int pc_type) { + uint32_t type; + char ds_name[DATA_MAX_NAME_LEN]; - d->ds_names = realloc(d->ds_names, sizeof(char *) * (d->ds_num + 1)); - if(!d->ds_names) - { - return -ENOMEM; + if (convert_special_metrics) { + /** + * Special case for filestore:JournalWrBytes. 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 a single "Derive" + * type. To spare further confusion, keep this KPI as the same type of + * other "Bytes". Instead of keeping an "average" or "rate", use the + * "sum" in the pair and assign that to the derive value. + */ + if ((strcmp(name, "filestore.journal_wr_bytes.type") == 0)) { + pc_type = 10; } + } - d->ds_types = realloc(d->ds_types, sizeof(uint32_t) * (d->ds_num + 1)); - if(!d->ds_types) - { - return -ENOMEM; - } + d->ds_names = realloc(d->ds_names, sizeof(char *) * (d->ds_num + 1)); + if (!d->ds_names) { + return -ENOMEM; + } - d->ds_names[d->ds_num] = malloc(sizeof(char) * DATA_MAX_NAME_LEN); - if(!d->ds_names[d->ds_num]) - { - return -ENOMEM; - } + d->ds_types = realloc(d->ds_types, sizeof(uint32_t) * (d->ds_num + 1)); + if (!d->ds_types) { + return -ENOMEM; + } - type = (pc_type & PERFCOUNTER_DERIVE) ? DSET_RATE : - ((pc_type & PERFCOUNTER_LATENCY) ? DSET_LATENCY : DSET_BYTES); - d->ds_types[d->ds_num] = type; + d->ds_names[d->ds_num] = malloc(DATA_MAX_NAME_LEN); + if (!d->ds_names[d->ds_num]) { + return -ENOMEM; + } - if (parse_keys(ds_name, sizeof (ds_name), name)) - { - return 1; - } + type = (pc_type & PERFCOUNTER_DERIVE) + ? DSET_RATE + : ((pc_type & PERFCOUNTER_LATENCY) ? DSET_LATENCY : DSET_BYTES); + d->ds_types[d->ds_num] = type; - sstrncpy(d->ds_names[d->ds_num], ds_name, DATA_MAX_NAME_LEN -1); - d->ds_num = (d->ds_num + 1); + if (parse_keys(ds_name, sizeof(ds_name), name)) { + return 1; + } - return 0; + sstrncpy(d->ds_names[d->ds_num], ds_name, DATA_MAX_NAME_LEN - 1); + d->ds_num = (d->ds_num + 1); + + return 0; } /******* ceph_config *******/ -static int cc_handle_str(struct oconfig_item_s *item, char *dest, int dest_len) -{ - const char *val; - if(item->values_num != 1) - { - return -ENOTSUP; - } - if(item->values[0].type != OCONFIG_TYPE_STRING) - { - return -ENOTSUP; - } - val = item->values[0].value.string; - if(snprintf(dest, dest_len, "%s", val) > (dest_len - 1)) - { - ERROR("ceph plugin: configuration parameter '%s' is too long.\n", - item->key); - return -ENAMETOOLONG; - } - return 0; +static int cc_handle_str(struct oconfig_item_s *item, char *dest, + int dest_len) { + const char *val; + if (item->values_num != 1) { + return -ENOTSUP; + } + if (item->values[0].type != OCONFIG_TYPE_STRING) { + return -ENOTSUP; + } + val = item->values[0].value.string; + if (snprintf(dest, dest_len, "%s", val) > (dest_len - 1)) { + ERROR("ceph plugin: configuration parameter '%s' is too long.\n", + item->key); + return -ENAMETOOLONG; + } + return 0; } -static int cc_handle_bool(struct oconfig_item_s *item, int *dest) -{ - if(item->values_num != 1) - { - return -ENOTSUP; - } +static int cc_handle_bool(struct oconfig_item_s *item, int *dest) { + if (item->values_num != 1) { + return -ENOTSUP; + } - if(item->values[0].type != OCONFIG_TYPE_BOOLEAN) - { - return -ENOTSUP; - } + if (item->values[0].type != OCONFIG_TYPE_BOOLEAN) { + return -ENOTSUP; + } - *dest = (item->values[0].value.boolean) ? 1 : 0; - return 0; + *dest = (item->values[0].value.boolean) ? 1 : 0; + return 0; } -static int cc_add_daemon_config(oconfig_item_t *ci) -{ - int ret, i; - struct ceph_daemon *nd, cd; - struct ceph_daemon **tmp; - memset(&cd, 0, sizeof(struct ceph_daemon)); - - if((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - WARNING("ceph plugin: `Daemon' blocks need exactly one string " - "argument."); - return (-1); - } +static int cc_add_daemon_config(oconfig_item_t *ci) { + int ret; + struct ceph_daemon *nd, cd = {0}; + struct ceph_daemon **tmp; - ret = cc_handle_str(ci, cd.name, DATA_MAX_NAME_LEN); - if(ret) - { - return ret; - } + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { + WARNING("ceph plugin: `Daemon' blocks need exactly one string " + "argument."); + return (-1); + } - for(i=0; i < ci->children_num; i++) - { - oconfig_item_t *child = ci->children + i; - - if(strcasecmp("SocketPath", child->key) == 0) - { - ret = cc_handle_str(child, cd.asok_path, sizeof(cd.asok_path)); - if(ret) - { - return ret; - } - } - else - { - WARNING("ceph plugin: ignoring unknown option %s", child->key); - } - } - if(cd.name[0] == '\0') - { - ERROR("ceph plugin: you must configure a daemon name.\n"); - return -EINVAL; - } - else if(cd.asok_path[0] == '\0') - { - ERROR("ceph plugin(name=%s): you must configure an administrative " - "socket path.\n", cd.name); - return -EINVAL; - } - else if(!((cd.asok_path[0] == '/') || - (cd.asok_path[0] == '.' && cd.asok_path[1] == '/'))) - { - ERROR("ceph plugin(name=%s): administrative socket paths must begin " - "with '/' or './' Can't parse: '%s'\n", cd.name, cd.asok_path); - return -EINVAL; - } + ret = cc_handle_str(ci, cd.name, DATA_MAX_NAME_LEN); + if (ret) { + return ret; + } - tmp = realloc(g_daemons, (g_num_daemons+1) * sizeof(*g_daemons)); - if(tmp == NULL) - { - /* The positive return value here indicates that this is a - * runtime error, not a configuration error. */ - return ENOMEM; - } - g_daemons = tmp; + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; - nd = malloc(sizeof(*nd)); - if(!nd) - { - return ENOMEM; - } - memcpy(nd, &cd, sizeof(*nd)); - g_daemons[g_num_daemons++] = nd; - return 0; + if (strcasecmp("SocketPath", child->key) == 0) { + ret = cc_handle_str(child, cd.asok_path, sizeof(cd.asok_path)); + if (ret) { + return ret; + } + } else { + WARNING("ceph plugin: ignoring unknown option %s", child->key); + } + } + if (cd.name[0] == '\0') { + ERROR("ceph plugin: you must configure a daemon name.\n"); + return -EINVAL; + } else if (cd.asok_path[0] == '\0') { + ERROR("ceph plugin(name=%s): you must configure an administrative " + "socket path.\n", + cd.name); + return -EINVAL; + } else if (!((cd.asok_path[0] == '/') || + (cd.asok_path[0] == '.' && cd.asok_path[1] == '/'))) { + ERROR("ceph plugin(name=%s): administrative socket paths must begin " + "with '/' or './' Can't parse: '%s'\n", + cd.name, cd.asok_path); + return -EINVAL; + } + + tmp = realloc(g_daemons, (g_num_daemons + 1) * sizeof(*g_daemons)); + if (tmp == NULL) { + /* The positive return value here indicates that this is a + * runtime error, not a configuration error. */ + return ENOMEM; + } + g_daemons = tmp; + + nd = malloc(sizeof(*nd)); + if (!nd) { + return ENOMEM; + } + memcpy(nd, &cd, sizeof(*nd)); + g_daemons[g_num_daemons] = nd; + g_num_daemons++; + return 0; } -static int ceph_config(oconfig_item_t *ci) -{ - int ret, i; - - for(i = 0; i < ci->children_num; ++i) - { - oconfig_item_t *child = ci->children + i; - if(strcasecmp("Daemon", child->key) == 0) - { - ret = cc_add_daemon_config(child); - if(ret == ENOMEM) - { - ERROR("ceph plugin: Couldn't allocate memory"); - return ret; - } - else if(ret) - { - //process other daemons and ignore this one - continue; - } - } - else if(strcasecmp("LongRunAvgLatency", child->key) == 0) - { - ret = cc_handle_bool(child, &long_run_latency_avg); - if(ret) - { - return ret; - } - } - else if(strcasecmp("ConvertSpecialMetricTypes", child->key) == 0) - { - ret = cc_handle_bool(child, &convert_special_metrics); - if(ret) - { - return ret; - } - } - else - { - WARNING("ceph plugin: ignoring unknown option %s", child->key); - } +static int ceph_config(oconfig_item_t *ci) { + int ret; + + for (int i = 0; i < ci->children_num; ++i) { + oconfig_item_t *child = ci->children + i; + if (strcasecmp("Daemon", child->key) == 0) { + ret = cc_add_daemon_config(child); + if (ret == ENOMEM) { + ERROR("ceph plugin: Couldn't allocate memory"); + return ret; + } else if (ret) { + // process other daemons and ignore this one + continue; + } + } else if (strcasecmp("LongRunAvgLatency", child->key) == 0) { + ret = cc_handle_bool(child, &long_run_latency_avg); + if (ret) { + return ret; + } + } else if (strcasecmp("ConvertSpecialMetricTypes", child->key) == 0) { + ret = cc_handle_bool(child, &convert_special_metrics); + if (ret) { + return ret; + } + } else { + WARNING("ceph plugin: ignoring unknown option %s", child->key); } - return 0; + } + return 0; } /** * Parse JSON and get error message if present */ -static int -traverse_json(const unsigned char *json, uint32_t json_len, yajl_handle hand) -{ - yajl_status status = yajl_parse(hand, json, json_len); - unsigned char *msg; - - switch(status) - { - case yajl_status_error: - msg = yajl_get_error(hand, /* verbose = */ 1, - /* jsonText = */ (unsigned char *) json, - (unsigned int) json_len); - ERROR ("ceph plugin: yajl_parse failed: %s", msg); - yajl_free_error(hand, msg); - return 1; - case yajl_status_client_canceled: - return 1; - default: - return 0; - } +static int traverse_json(const unsigned char *json, uint32_t json_len, + yajl_handle hand) { + yajl_status status = yajl_parse(hand, json, json_len); + unsigned char *msg; + + switch (status) { + case yajl_status_error: + msg = yajl_get_error(hand, /* verbose = */ 1, + /* jsonText = */ (unsigned char *)json, + (unsigned int)json_len); + ERROR("ceph plugin: yajl_parse failed: %s", msg); + yajl_free_error(hand, msg); + return 1; + case yajl_status_client_canceled: + return 1; + default: + return 0; + } } /** * Add entry for each counter while parsing schema */ -static int -node_handler_define_schema(void *arg, const char *val, const char *key) -{ - struct ceph_daemon *d = (struct ceph_daemon *) arg; - int pc_type; - pc_type = atoi(val); - return ceph_daemon_add_ds_entry(d, key, pc_type); +static int node_handler_define_schema(void *arg, const char *val, + const char *key) { + struct ceph_daemon *d = (struct ceph_daemon *)arg; + int pc_type; + pc_type = atoi(val); + return ceph_daemon_add_ds_entry(d, key, pc_type); } /** * Latency counter does not yet have an entry in last poll data - add it. */ 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)); - if(!d->last_poll_data[d->last_idx]) - { - return -ENOMEM; - } - sstrncpy(d->last_poll_data[d->last_idx]->ds_name,ds_n, - sizeof(d->last_poll_data[d->last_idx]->ds_name)); - d->last_poll_data[d->last_idx]->last_sum = cur_sum; - d->last_poll_data[d->last_idx]->last_count = cur_count; - d->last_idx = (d->last_idx + 1); - return 0; + uint64_t cur_count) { + 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; + } + sstrncpy(d->last_poll_data[d->last_idx]->ds_name, ds_n, + sizeof(d->last_poll_data[d->last_idx]->ds_name)); + d->last_poll_data[d->last_idx]->last_sum = cur_sum; + d->last_poll_data[d->last_idx]->last_count = cur_count; + d->last_idx = (d->last_idx + 1); + return 0; } /** * Update latency counter or add new entry if it doesn't exist */ static int update_last(struct ceph_daemon *d, const char *ds_n, int index, - double cur_sum, uint64_t cur_count) -{ - if((d->last_idx > index) && (strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0)) - { - d->last_poll_data[index]->last_sum = cur_sum; - d->last_poll_data[index]->last_count = cur_count; - return 0; - } - - if(!d->last_poll_data) - { - d->last_poll_data = malloc(1 * sizeof(struct last_data *)); - if(!d->last_poll_data) - { - return -ENOMEM; - } - } - else - { - struct last_data **tmp_last = realloc(d->last_poll_data, - ((d->last_idx+1) * sizeof(struct last_data *))); - if(!tmp_last) - { - return -ENOMEM; - } - d->last_poll_data = tmp_last; - } - return add_last(d, ds_n, cur_sum, cur_count); + double cur_sum, uint64_t cur_count) { + if ((d->last_idx > index) && + (strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0)) { + d->last_poll_data[index]->last_sum = cur_sum; + d->last_poll_data[index]->last_count = cur_count; + return 0; + } + + if (!d->last_poll_data) { + d->last_poll_data = malloc(sizeof(*d->last_poll_data)); + if (!d->last_poll_data) { + return -ENOMEM; + } + } else { + struct last_data **tmp_last = realloc( + d->last_poll_data, ((d->last_idx + 1) * sizeof(struct last_data *))); + if (!tmp_last) { + return -ENOMEM; + } + d->last_poll_data = tmp_last; + } + return add_last(d, ds_n, cur_sum, cur_count); } /** * If using index guess failed (shouldn't happen, but possible if counters * get rearranged), resort to searching for counter name */ -static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n) -{ - int i = 0; - for(; i < d->last_idx; i++) - { - if(strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0) - { - return i; - } +static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n) { + for (int i = 0; i < d->last_idx; i++) { + if (strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0) { + return i; } - return -1; + } + return -1; } /** @@ -915,699 +817,627 @@ static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n) * if last poll data exists */ static double get_last_avg(struct ceph_daemon *d, const char *ds_n, int index, - double cur_sum, uint64_t cur_count) -{ - double result = -1.1, sum_delt = 0.0; - uint64_t count_delt = 0; - int tmp_index = 0; - if(d->last_idx > index) - { - if(strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0) - { - tmp_index = index; - } - //test previous index - else if((index > 0) && (strcmp(d->last_poll_data[index-1]->ds_name, ds_n) == 0)) - { - tmp_index = (index - 1); - } - else - { - tmp_index = backup_search_for_last_avg(d, ds_n); - } - - if((tmp_index > -1) && (cur_count > d->last_poll_data[tmp_index]->last_count)) - { - sum_delt = (cur_sum - d->last_poll_data[tmp_index]->last_sum); - count_delt = (cur_count - d->last_poll_data[tmp_index]->last_count); - result = (sum_delt / count_delt); - } - } - - if(result == -1.1) - { - result = NAN; - } - if(update_last(d, ds_n, tmp_index, cur_sum, cur_count) == -ENOMEM) - { - return -ENOMEM; - } - return result; + double cur_sum, uint64_t cur_count) { + double result = -1.1, sum_delt = 0.0; + uint64_t count_delt = 0; + int tmp_index = 0; + if (d->last_idx > index) { + if (strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0) { + tmp_index = index; + } + // test previous index + else if ((index > 0) && + (strcmp(d->last_poll_data[index - 1]->ds_name, ds_n) == 0)) { + tmp_index = (index - 1); + } else { + tmp_index = backup_search_for_last_avg(d, ds_n); + } + + if ((tmp_index > -1) && + (cur_count > d->last_poll_data[tmp_index]->last_count)) { + sum_delt = (cur_sum - d->last_poll_data[tmp_index]->last_sum); + count_delt = (cur_count - d->last_poll_data[tmp_index]->last_count); + result = (sum_delt / count_delt); + } + } + + if (result == -1.1) { + result = NAN; + } + if (update_last(d, ds_n, tmp_index, cur_sum, cur_count) == -ENOMEM) { + return -ENOMEM; + } + return result; } /** * If using index guess failed, resort to searching for counter name */ -static uint32_t backup_search_for_type(struct ceph_daemon *d, char *ds_name) -{ - int idx = 0; - for(; idx < d->ds_num; idx++) - { - if(strcmp(d->ds_names[idx], ds_name) == 0) - { - return d->ds_types[idx]; - } +static uint32_t backup_search_for_type(struct ceph_daemon *d, char *ds_name) { + for (int i = 0; i < d->ds_num; i++) { + if (strcmp(d->ds_names[i], ds_name) == 0) { + return d->ds_types[i]; } - return DSET_TYPE_UNFOUND; + } + return DSET_TYPE_UNFOUND; } /** * Process counter data and dispatch values */ -static int node_handler_fetch_data(void *arg, const char *val, const char *key) -{ - value_t uv; - double tmp_d; - uint64_t tmp_u; - struct values_tmp *vtmp = (struct values_tmp*) arg; - uint32_t type = 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)) - { - return 1; - } - - if(index >= vtmp->d->ds_num) - { - //don't overflow bounds of array - index = (vtmp->d->ds_num - 1); - } - - /** - * counters should remain in same order we parsed schema... we maintain the - * index variable to keep track of current point in list of counters. first - * use index to guess point in array for retrieving type. if that doesn't - * work, use the old way to get the counter type - */ - if(strcmp(ds_name, vtmp->d->ds_names[index]) == 0) - { - //found match - type = vtmp->d->ds_types[index]; - } - else if((index > 0) && (strcmp(ds_name, vtmp->d->ds_names[index-1]) == 0)) - { - //try previous key - type = vtmp->d->ds_types[index-1]; - } - - if(type == DSET_TYPE_UNFOUND) - { - //couldn't find right type by guessing, check the old way - type = backup_search_for_type(vtmp->d, ds_name); - } - - switch(type) - { - case DSET_LATENCY: - if(vtmp->avgcount_exists == -1) - { - sscanf(val, "%" PRIu64, &vtmp->avgcount); - vtmp->avgcount_exists = 0; - //return after saving avgcount - don't dispatch value - //until latency calculation - return 0; - } - else - { - double sum, result; - sscanf(val, "%lf", &sum); - - if(vtmp->avgcount == 0) - { - vtmp->avgcount = 1; - } - - /** User wants latency values as long run avg */ - if(long_run_latency_avg) - { - result = (sum / vtmp->avgcount); - } - else - { - result = get_last_avg(vtmp->d, ds_name, vtmp->latency_index, sum, vtmp->avgcount); - if(result == -ENOMEM) - { - return -ENOMEM; - } - } - - uv.gauge = result; - vtmp->avgcount_exists = -1; - vtmp->latency_index = (vtmp->latency_index + 1); - } - break; - case DSET_BYTES: - sscanf(val, "%lf", &tmp_d); - uv.gauge = tmp_d; - break; - case DSET_RATE: - sscanf(val, "%" PRIu64, &tmp_u); - uv.derive = tmp_u; - break; - case DSET_TYPE_UNFOUND: - default: - ERROR("ceph plugin: ds %s was not properly initialized.", ds_name); - return -1; - } +static int node_handler_fetch_data(void *arg, const char *val, + const char *key) { + value_t uv; + double tmp_d; + uint64_t tmp_u; + struct values_tmp *vtmp = (struct values_tmp *)arg; + uint32_t type = DSET_TYPE_UNFOUND; + int index = vtmp->index; + + char ds_name[DATA_MAX_NAME_LEN]; + + if (parse_keys(ds_name, sizeof(ds_name), key)) { + return 1; + } + + if (index >= vtmp->d->ds_num) { + // don't overflow bounds of array + index = (vtmp->d->ds_num - 1); + } + + /** + * counters should remain in same order we parsed schema... we maintain the + * index variable to keep track of current point in list of counters. first + * use index to guess point in array for retrieving type. if that doesn't + * work, use the old way to get the counter type + */ + if (strcmp(ds_name, vtmp->d->ds_names[index]) == 0) { + // found match + type = vtmp->d->ds_types[index]; + } else if ((index > 0) && + (strcmp(ds_name, vtmp->d->ds_names[index - 1]) == 0)) { + // try previous key + type = vtmp->d->ds_types[index - 1]; + } + + if (type == DSET_TYPE_UNFOUND) { + // couldn't find right type by guessing, check the old way + type = backup_search_for_type(vtmp->d, ds_name); + } + + switch (type) { + case DSET_LATENCY: + if (vtmp->avgcount_exists == -1) { + sscanf(val, "%" PRIu64, &vtmp->avgcount); + vtmp->avgcount_exists = 0; + // return after saving avgcount - don't dispatch value + // until latency calculation + return 0; + } else { + double sum, result; + sscanf(val, "%lf", &sum); + + if (vtmp->avgcount == 0) { + vtmp->avgcount = 1; + } + + /** User wants latency values as long run avg */ + if (long_run_latency_avg) { + result = (sum / vtmp->avgcount); + } else { + result = get_last_avg(vtmp->d, ds_name, vtmp->latency_index, sum, + vtmp->avgcount); + if (result == -ENOMEM) { + return -ENOMEM; + } + } + + uv.gauge = result; + vtmp->avgcount_exists = -1; + vtmp->latency_index = (vtmp->latency_index + 1); + } + break; + case DSET_BYTES: + sscanf(val, "%lf", &tmp_d); + uv.gauge = tmp_d; + break; + case DSET_RATE: + sscanf(val, "%" PRIu64, &tmp_u); + uv.derive = tmp_u; + break; + case DSET_TYPE_UNFOUND: + default: + ERROR("ceph plugin: ds %s was not properly initialized.", ds_name); + return -1; + } - sstrncpy(vtmp->vlist.type, ceph_dset_types[type], sizeof(vtmp->vlist.type)); - sstrncpy(vtmp->vlist.type_instance, ds_name, sizeof(vtmp->vlist.type_instance)); - vtmp->vlist.values = &uv; - vtmp->vlist.values_len = 1; + sstrncpy(vtmp->vlist.type, ceph_dset_types[type], sizeof(vtmp->vlist.type)); + sstrncpy(vtmp->vlist.type_instance, ds_name, + sizeof(vtmp->vlist.type_instance)); + vtmp->vlist.values = &uv; + vtmp->vlist.values_len = 1; - vtmp->index = (vtmp->index + 1); - plugin_dispatch_values(&vtmp->vlist); + vtmp->index = (vtmp->index + 1); + plugin_dispatch_values(&vtmp->vlist); - return 0; + return 0; } -static int cconn_connect(struct cconn *io) -{ - struct sockaddr_un address; - int flags, fd, err; - if(io->state != CSTATE_UNCONNECTED) - { - ERROR("ceph plugin: cconn_connect: io->state != CSTATE_UNCONNECTED"); - return -EDOM; - } - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if(fd < 0) - { - err = -errno; - ERROR("ceph plugin: cconn_connect: socket(PF_UNIX, SOCK_STREAM, 0) " - "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); - RETRY_ON_EINTR(err, - connect(fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un))); - if(err < 0) - { - ERROR("ceph plugin: cconn_connect: connect(%d) failed: error %d", - fd, err); - close(fd); - return err; - } - - flags = fcntl(fd, F_GETFL, 0); - if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) - { - err = -errno; - ERROR("ceph plugin: cconn_connect: fcntl(%d, O_NONBLOCK) error %d", - fd, err); - close(fd); - return err; - } - io->asok = fd; - io->state = CSTATE_WRITE_REQUEST; - io->amt = 0; - io->json_len = 0; - io->json = NULL; - return 0; +static int cconn_connect(struct cconn *io) { + struct sockaddr_un address = {0}; + int flags, fd, err; + if (io->state != CSTATE_UNCONNECTED) { + ERROR("ceph plugin: cconn_connect: io->state != CSTATE_UNCONNECTED"); + return -EDOM; + } + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + err = -errno; + ERROR("ceph plugin: cconn_connect: socket(PF_UNIX, SOCK_STREAM, 0) " + "failed: error %d", + err); + return err; + } + address.sun_family = AF_UNIX; + snprintf(address.sun_path, sizeof(address.sun_path), "%s", io->d->asok_path); + RETRY_ON_EINTR(err, connect(fd, (struct sockaddr *)&address, + sizeof(struct sockaddr_un))); + if (err < 0) { + ERROR("ceph plugin: cconn_connect: connect(%d) failed: error %d", fd, err); + close(fd); + return err; + } + + flags = fcntl(fd, F_GETFL, 0); + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) { + err = -errno; + ERROR("ceph plugin: cconn_connect: fcntl(%d, O_NONBLOCK) error %d", fd, + err); + close(fd); + return err; + } + io->asok = fd; + io->state = CSTATE_WRITE_REQUEST; + io->amt = 0; + io->json_len = 0; + io->json = NULL; + return 0; } -static void cconn_close(struct cconn *io) -{ - io->state = CSTATE_UNCONNECTED; - if(io->asok != -1) - { - int res; - RETRY_ON_EINTR(res, close(io->asok)); - } - io->asok = -1; - io->amt = 0; - io->json_len = 0; - sfree(io->json); - io->json = NULL; +static void cconn_close(struct cconn *io) { + io->state = CSTATE_UNCONNECTED; + if (io->asok != -1) { + int res; + RETRY_ON_EINTR(res, close(io->asok)); + } + io->asok = -1; + io->amt = 0; + io->json_len = 0; + sfree(io->json); + io->json = NULL; } /* Process incoming JSON counter data */ -static int -cconn_process_data(struct cconn *io, yajl_struct *yajl, yajl_handle hand) -{ - int ret; - struct values_tmp *vtmp = calloc(1, sizeof(struct values_tmp) * 1); - if(!vtmp) - { - return -ENOMEM; - } - - vtmp->vlist = (value_list_t)VALUE_LIST_INIT; - sstrncpy(vtmp->vlist.host, hostname_g, sizeof(vtmp->vlist.host)); - sstrncpy(vtmp->vlist.plugin, "ceph", sizeof(vtmp->vlist.plugin)); - sstrncpy(vtmp->vlist.plugin_instance, io->d->name, sizeof(vtmp->vlist.plugin_instance)); - - vtmp->d = io->d; - vtmp->avgcount_exists = -1; - vtmp->latency_index = 0; - vtmp->index = 0; - yajl->handler_arg = vtmp; - ret = traverse_json(io->json, io->json_len, hand); - sfree(vtmp); - return ret; +static int cconn_process_data(struct cconn *io, yajl_struct *yajl, + yajl_handle hand) { + int ret; + struct values_tmp *vtmp = calloc(1, sizeof(struct values_tmp) * 1); + if (!vtmp) { + return -ENOMEM; + } + + vtmp->vlist = (value_list_t)VALUE_LIST_INIT; + sstrncpy(vtmp->vlist.host, hostname_g, sizeof(vtmp->vlist.host)); + sstrncpy(vtmp->vlist.plugin, "ceph", sizeof(vtmp->vlist.plugin)); + sstrncpy(vtmp->vlist.plugin_instance, io->d->name, + sizeof(vtmp->vlist.plugin_instance)); + + vtmp->d = io->d; + vtmp->avgcount_exists = -1; + vtmp->latency_index = 0; + vtmp->index = 0; + yajl->handler_arg = vtmp; + ret = traverse_json(io->json, io->json_len, hand); + sfree(vtmp); + return ret; } /** * Initiate JSON parsing and print error if one occurs */ -static int cconn_process_json(struct cconn *io) -{ - if((io->request_type != ASOK_REQ_DATA) && - (io->request_type != ASOK_REQ_SCHEMA)) - { - return -EDOM; - } +static int cconn_process_json(struct cconn *io) { + if ((io->request_type != ASOK_REQ_DATA) && + (io->request_type != ASOK_REQ_SCHEMA)) { + return -EDOM; + } - int result = 1; - yajl_handle hand; - yajl_status status; + int result = 1; + yajl_handle hand; + yajl_status status; - hand = yajl_alloc(&callbacks, + hand = yajl_alloc(&callbacks, #if HAVE_YAJL_V2 - /* alloc funcs = */ NULL, + /* alloc funcs = */ NULL, #else - /* alloc funcs = */ NULL, NULL, + /* alloc funcs = */ NULL, NULL, #endif - /* context = */ (void *)(&io->yajl)); - - if(!hand) - { - ERROR ("ceph plugin: yajl_alloc failed."); - return ENOMEM; - } - - io->yajl.depth = 0; - - switch(io->request_type) - { - case ASOK_REQ_DATA: - io->yajl.handler = node_handler_fetch_data; - result = cconn_process_data(io, &io->yajl, hand); - break; - case ASOK_REQ_SCHEMA: - //init daemon specific variables - io->d->ds_num = 0; - io->d->last_idx = 0; - io->d->last_poll_data = NULL; - io->yajl.handler = node_handler_define_schema; - io->yajl.handler_arg = io->d; - result = traverse_json(io->json, io->json_len, hand); - break; - } - - if(result) - { - goto done; - } + /* context = */ (void *)(&io->yajl)); + + if (!hand) { + ERROR("ceph plugin: yajl_alloc failed."); + return ENOMEM; + } + + io->yajl.depth = 0; + + switch (io->request_type) { + case ASOK_REQ_DATA: + io->yajl.handler = node_handler_fetch_data; + result = cconn_process_data(io, &io->yajl, hand); + break; + case ASOK_REQ_SCHEMA: + // init daemon specific variables + io->d->ds_num = 0; + io->d->last_idx = 0; + io->d->last_poll_data = NULL; + io->yajl.handler = node_handler_define_schema; + io->yajl.handler_arg = io->d; + result = traverse_json(io->json, io->json_len, hand); + break; + } + + if (result) { + goto done; + } #if HAVE_YAJL_V2 - status = yajl_complete_parse(hand); + status = yajl_complete_parse(hand); #else - status = yajl_parse_complete(hand); + status = yajl_parse_complete(hand); #endif - if (status != yajl_status_ok) - { - unsigned char *errmsg = yajl_get_error (hand, /* verbose = */ 0, - /* jsonText = */ NULL, /* jsonTextLen = */ 0); - ERROR ("ceph plugin: yajl_parse_complete failed: %s", - (char *) errmsg); - yajl_free_error (hand, errmsg); - yajl_free (hand); - return 1; - } - - done: - yajl_free (hand); - return result; + if (status != yajl_status_ok) { + unsigned char *errmsg = + yajl_get_error(hand, /* verbose = */ 0, + /* jsonText = */ NULL, /* jsonTextLen = */ 0); + ERROR("ceph plugin: yajl_parse_complete failed: %s", (char *)errmsg); + yajl_free_error(hand, errmsg); + yajl_free(hand); + return 1; + } + +done: + yajl_free(hand); + return result; } -static int cconn_validate_revents(struct cconn *io, int revents) -{ - if(revents & POLLERR) - { - ERROR("ceph plugin: cconn_validate_revents(name=%s): got POLLERR", - io->d->name); - return -EIO; - } - switch (io->state) - { - case CSTATE_WRITE_REQUEST: - return (revents & POLLOUT) ? 0 : -EINVAL; - case CSTATE_READ_VERSION: - case CSTATE_READ_AMT: - case CSTATE_READ_JSON: - return (revents & POLLIN) ? 0 : -EINVAL; - default: - ERROR("ceph plugin: cconn_validate_revents(name=%s) got to " - "illegal state on line %d", io->d->name, __LINE__); - return -EDOM; - } +static int cconn_validate_revents(struct cconn *io, int revents) { + if (revents & POLLERR) { + ERROR("ceph plugin: cconn_validate_revents(name=%s): got POLLERR", + io->d->name); + return -EIO; + } + switch (io->state) { + case CSTATE_WRITE_REQUEST: + return (revents & POLLOUT) ? 0 : -EINVAL; + case CSTATE_READ_VERSION: + case CSTATE_READ_AMT: + case CSTATE_READ_JSON: + return (revents & POLLIN) ? 0 : -EINVAL; + default: + ERROR("ceph plugin: cconn_validate_revents(name=%s) got to " + "illegal state on line %d", + io->d->name, __LINE__); + return -EDOM; + } } /** Handle a network event for a connection */ -static int cconn_handle_event(struct cconn *io) -{ - int ret; - switch (io->state) - { - case CSTATE_UNCONNECTED: - ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal " - "state on line %d", io->d->name, __LINE__); - - return -EDOM; - case CSTATE_WRITE_REQUEST: - { - char cmd[32]; - snprintf(cmd, sizeof(cmd), "%s%d%s", "{ \"prefix\": \"", - io->request_type, "\" }\n"); - size_t cmd_len = strlen(cmd); - RETRY_ON_EINTR(ret, - write(io->asok, ((char*)&cmd) + io->amt, cmd_len - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,amt=%d,ret=%d)", - io->d->name, io->state, io->amt, ret); - if(ret < 0) - { - return ret; - } - io->amt += ret; - if(io->amt >= cmd_len) - { - io->amt = 0; - switch (io->request_type) - { - case ASOK_REQ_VERSION: - io->state = CSTATE_READ_VERSION; - break; - default: - io->state = CSTATE_READ_AMT; - break; - } - } - return 0; - } - case CSTATE_READ_VERSION: - { - RETRY_ON_EINTR(ret, - read(io->asok, ((char*)(&io->d->version)) + io->amt, - sizeof(io->d->version) - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", - io->d->name, io->state, ret); - if(ret < 0) - { - return ret; - } - io->amt += ret; - if(io->amt >= sizeof(io->d->version)) - { - io->d->version = ntohl(io->d->version); - if(io->d->version != 1) - { - ERROR("ceph plugin: cconn_handle_event(name=%s) not " - "expecting version %d!", io->d->name, io->d->version); - return -ENOTSUP; - } - DEBUG("ceph plugin: cconn_handle_event(name=%s): identified as " - "version %d", io->d->name, io->d->version); - io->amt = 0; - cconn_close(io); - io->request_type = ASOK_REQ_SCHEMA; - } - return 0; - } - case CSTATE_READ_AMT: - { - RETRY_ON_EINTR(ret, - read(io->asok, ((char*)(&io->json_len)) + io->amt, - sizeof(io->json_len) - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", - io->d->name, io->state, ret); - if(ret < 0) - { - return ret; - } - io->amt += ret; - if(io->amt >= sizeof(io->json_len)) - { - io->json_len = ntohl(io->json_len); - io->amt = 0; - io->state = CSTATE_READ_JSON; - io->json = calloc(1, io->json_len + 1); - if(!io->json) - { - ERROR("ceph plugin: error callocing io->json"); - return -ENOMEM; - } - } - return 0; - } - case CSTATE_READ_JSON: - { - RETRY_ON_EINTR(ret, - read(io->asok, io->json + io->amt, io->json_len - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", - io->d->name, io->state, ret); - if(ret < 0) - { - return ret; - } - io->amt += ret; - if(io->amt >= io->json_len) - { - ret = cconn_process_json(io); - if(ret) - { - return ret; - } - cconn_close(io); - io->request_type = ASOK_REQ_NONE; - } - return 0; - } - default: - ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal " - "state on line %d", io->d->name, __LINE__); - return -EDOM; +static int cconn_handle_event(struct cconn *io) { + int ret; + switch (io->state) { + case CSTATE_UNCONNECTED: + ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal " + "state on line %d", + io->d->name, __LINE__); + + return -EDOM; + case CSTATE_WRITE_REQUEST: { + char cmd[32]; + snprintf(cmd, sizeof(cmd), "%s%d%s", "{ \"prefix\": \"", io->request_type, + "\" }\n"); + size_t cmd_len = strlen(cmd); + RETRY_ON_EINTR( + ret, write(io->asok, ((char *)&cmd) + io->amt, cmd_len - io->amt)); + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,amt=%d,ret=%d)", + io->d->name, io->state, io->amt, ret); + if (ret < 0) { + return ret; + } + io->amt += ret; + if (io->amt >= cmd_len) { + io->amt = 0; + switch (io->request_type) { + case ASOK_REQ_VERSION: + io->state = CSTATE_READ_VERSION; + break; + default: + io->state = CSTATE_READ_AMT; + break; + } } -} - -static int cconn_prepare(struct cconn *io, struct pollfd* fds) -{ - int ret; - if(io->request_type == ASOK_REQ_NONE) - { - /* The request has already been serviced. */ - return 0; + return 0; + } + case CSTATE_READ_VERSION: { + RETRY_ON_EINTR(ret, read(io->asok, ((char *)(&io->d->version)) + io->amt, + sizeof(io->d->version) - io->amt)); + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", + io->d->name, io->state, ret); + if (ret < 0) { + return ret; + } + io->amt += ret; + if (io->amt >= sizeof(io->d->version)) { + io->d->version = ntohl(io->d->version); + if (io->d->version != 1) { + ERROR("ceph plugin: cconn_handle_event(name=%s) not " + "expecting version %d!", + io->d->name, io->d->version); + return -ENOTSUP; + } + DEBUG("ceph plugin: cconn_handle_event(name=%s): identified as " + "version %d", + io->d->name, io->d->version); + io->amt = 0; + cconn_close(io); + io->request_type = ASOK_REQ_SCHEMA; } - else if((io->request_type == ASOK_REQ_DATA) && (io->d->ds_num == 0)) - { - /* If there are no counters to report on, don't bother - * connecting */ - return 0; + return 0; + } + case CSTATE_READ_AMT: { + RETRY_ON_EINTR(ret, read(io->asok, ((char *)(&io->json_len)) + io->amt, + sizeof(io->json_len) - io->amt)); + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", + io->d->name, io->state, ret); + if (ret < 0) { + return ret; + } + io->amt += ret; + if (io->amt >= sizeof(io->json_len)) { + io->json_len = ntohl(io->json_len); + io->amt = 0; + io->state = CSTATE_READ_JSON; + io->json = calloc(1, io->json_len + 1); + if (!io->json) { + ERROR("ceph plugin: error callocing io->json"); + return -ENOMEM; + } } - - switch (io->state) - { - case CSTATE_UNCONNECTED: - ret = cconn_connect(io); - if(ret > 0) - { - return -ret; - } - else if(ret < 0) - { - return ret; - } - fds->fd = io->asok; - fds->events = POLLOUT; - return 1; - case CSTATE_WRITE_REQUEST: - fds->fd = io->asok; - fds->events = POLLOUT; - return 1; - case CSTATE_READ_VERSION: - case CSTATE_READ_AMT: - case CSTATE_READ_JSON: - fds->fd = io->asok; - fds->events = POLLIN; - return 1; - default: - ERROR("ceph plugin: cconn_prepare(name=%s) got to illegal state " - "on line %d", io->d->name, __LINE__); - return -EDOM; + return 0; + } + case CSTATE_READ_JSON: { + RETRY_ON_EINTR(ret, + read(io->asok, io->json + io->amt, io->json_len - io->amt)); + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", + io->d->name, io->state, ret); + if (ret < 0) { + return ret; + } + io->amt += ret; + if (io->amt >= io->json_len) { + ret = cconn_process_json(io); + if (ret) { + return ret; + } + cconn_close(io); + io->request_type = ASOK_REQ_NONE; } + return 0; + } + default: + ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal " + "state on line %d", + io->d->name, __LINE__); + return -EDOM; + } +} + +static int cconn_prepare(struct cconn *io, struct pollfd *fds) { + int ret; + if (io->request_type == ASOK_REQ_NONE) { + /* The request has already been serviced. */ + return 0; + } else if ((io->request_type == ASOK_REQ_DATA) && (io->d->ds_num == 0)) { + /* If there are no counters to report on, don't bother + * connecting */ + return 0; + } + + switch (io->state) { + case CSTATE_UNCONNECTED: + ret = cconn_connect(io); + if (ret > 0) { + return -ret; + } else if (ret < 0) { + return ret; + } + fds->fd = io->asok; + fds->events = POLLOUT; + return 1; + case CSTATE_WRITE_REQUEST: + fds->fd = io->asok; + fds->events = POLLOUT; + return 1; + case CSTATE_READ_VERSION: + case CSTATE_READ_AMT: + case CSTATE_READ_JSON: + fds->fd = io->asok; + fds->events = POLLIN; + return 1; + default: + ERROR("ceph plugin: cconn_prepare(name=%s) got to illegal state " + "on line %d", + io->d->name, __LINE__); + return -EDOM; + } } /** Returns the difference between two struct timevals in milliseconds. * On overflow, we return max/min int. */ -static int milli_diff(const struct timeval *t1, const struct timeval *t2) -{ - int64_t ret; - int sec_diff = t1->tv_sec - t2->tv_sec; - int usec_diff = t1->tv_usec - t2->tv_usec; - ret = usec_diff / 1000; - ret += (sec_diff * 1000); - return (ret > INT_MAX) ? INT_MAX : ((ret < INT_MIN) ? INT_MIN : (int)ret); +static int milli_diff(const struct timeval *t1, const struct timeval *t2) { + int64_t ret; + int sec_diff = t1->tv_sec - t2->tv_sec; + int usec_diff = t1->tv_usec - t2->tv_usec; + ret = usec_diff / 1000; + ret += (sec_diff * 1000); + return (ret > INT_MAX) ? INT_MAX : ((ret < INT_MIN) ? INT_MIN : (int)ret); } /** This handles the actual network I/O to talk to the Ceph daemons. */ -static int cconn_main_loop(uint32_t request_type) -{ - int i, ret, some_unreachable = 0; - struct timeval end_tv; - struct cconn io_array[g_num_daemons]; - - DEBUG("ceph plugin: entering cconn_main_loop(request_type = %d)", request_type); - - /* create cconn array */ - memset(io_array, 0, sizeof(io_array)); - for(i = 0; i < g_num_daemons; ++i) - { - io_array[i].d = g_daemons[i]; - io_array[i].request_type = request_type; - io_array[i].state = CSTATE_UNCONNECTED; - } - - /** Calculate the time at which we should give up */ - gettimeofday(&end_tv, NULL); - end_tv.tv_sec += CEPH_TIMEOUT_INTERVAL; - - while (1) - { - int nfds, diff; - struct timeval tv; - struct cconn *polled_io_array[g_num_daemons]; - struct pollfd fds[g_num_daemons]; - memset(fds, 0, sizeof(fds)); - nfds = 0; - for(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", - io->d->name, i, io->state, ret); - cconn_close(io); - io->request_type = ASOK_REQ_NONE; - some_unreachable = 1; - } - else if(ret == 1) - { - polled_io_array[nfds++] = io_array + i; - } - } - if(nfds == 0) - { - /* finished */ - ret = 0; - goto done; - } - gettimeofday(&tv, NULL); - diff = milli_diff(&end_tv, &tv); - if(diff <= 0) - { - /* Timed out */ - ret = -ETIMEDOUT; - WARNING("ceph plugin: cconn_main_loop: timed out."); - goto done; - } - RETRY_ON_EINTR(ret, poll(fds, nfds, diff)); - if(ret < 0) - { - ERROR("ceph plugin: poll(2) error: %d", ret); - goto done; - } - for(i = 0; i < nfds; ++i) - { - struct cconn *io = polled_io_array[i]; - int revents = fds[i].revents; - if(revents == 0) - { - /* do nothing */ - } - else if(cconn_validate_revents(io, revents)) - { - WARNING("ceph plugin: cconn(name=%s,i=%d,st=%d): " +static int cconn_main_loop(uint32_t request_type) { + int ret, some_unreachable = 0; + struct timeval end_tv; + struct cconn io_array[g_num_daemons]; + + DEBUG("ceph plugin: entering cconn_main_loop(request_type = %d)", + request_type); + + /* create cconn array */ + memset(io_array, 0, sizeof(io_array)); + for (size_t i = 0; i < g_num_daemons; ++i) { + io_array[i].d = g_daemons[i]; + io_array[i].request_type = request_type; + io_array[i].state = CSTATE_UNCONNECTED; + } + + /** Calculate the time at which we should give up */ + gettimeofday(&end_tv, NULL); + end_tv.tv_sec += CEPH_TIMEOUT_INTERVAL; + + while (1) { + int nfds, diff; + struct timeval tv; + struct cconn *polled_io_array[g_num_daemons]; + struct pollfd fds[g_num_daemons]; + memset(fds, 0, sizeof(fds)); + nfds = 0; + 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=%zu,st=%d)=%d", + io->d->name, i, io->state, ret); + cconn_close(io); + io->request_type = ASOK_REQ_NONE; + some_unreachable = 1; + } else if (ret == 1) { + polled_io_array[nfds++] = io_array + i; + } + } + if (nfds == 0) { + /* finished */ + ret = 0; + goto done; + } + gettimeofday(&tv, NULL); + diff = milli_diff(&end_tv, &tv); + if (diff <= 0) { + /* Timed out */ + ret = -ETIMEDOUT; + WARNING("ceph plugin: cconn_main_loop: timed out."); + goto done; + } + RETRY_ON_EINTR(ret, poll(fds, nfds, diff)); + if (ret < 0) { + ERROR("ceph plugin: poll(2) error: %d", ret); + goto done; + } + 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)) { + WARNING("ceph plugin: cconn(name=%s,i=%d,st=%d): " "revents validation error: " - "revents=0x%08x", io->d->name, i, io->state, revents); - cconn_close(io); - io->request_type = ASOK_REQ_NONE; - some_unreachable = 1; - } - else - { - ret = cconn_handle_event(io); - if(ret) - { - WARNING("ceph plugin: cconn_handle_event(name=%s," - "i=%d,st=%d): error %d", io->d->name, i, io->state, ret); - cconn_close(io); - io->request_type = ASOK_REQ_NONE; - some_unreachable = 1; - } - } + "revents=0x%08x", + io->d->name, i, io->state, revents); + cconn_close(io); + io->request_type = ASOK_REQ_NONE; + some_unreachable = 1; + } else { + ret = cconn_handle_event(io); + if (ret) { + WARNING("ceph plugin: cconn_handle_event(name=%s," + "i=%d,st=%d): error %d", + io->d->name, i, io->state, ret); + cconn_close(io); + io->request_type = ASOK_REQ_NONE; + some_unreachable = 1; } - } - done: for(i = 0; i < g_num_daemons; ++i) - { - cconn_close(io_array + i); - } - if(some_unreachable) - { - DEBUG("ceph plugin: cconn_main_loop: some Ceph daemons were unreachable."); - } - else - { - DEBUG("ceph plugin: cconn_main_loop: reached all Ceph daemons :)"); - } - return ret; + } + } + } +done: + for (size_t i = 0; i < g_num_daemons; ++i) { + cconn_close(io_array + i); + } + if (some_unreachable) { + DEBUG("ceph plugin: cconn_main_loop: some Ceph daemons were unreachable."); + } else { + DEBUG("ceph plugin: cconn_main_loop: reached all Ceph daemons :)"); + } + return ret; } -static int ceph_read(void) -{ - return cconn_main_loop(ASOK_REQ_DATA); -} +static int ceph_read(void) { return cconn_main_loop(ASOK_REQ_DATA); } /******* lifecycle *******/ -static int ceph_init(void) -{ - int ret; - ceph_daemons_print(); +static int ceph_init(void) { +#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 - ret = cconn_main_loop(ASOK_REQ_VERSION); + ceph_daemons_print(); - return (ret) ? ret : 0; + if (g_num_daemons < 1) { + ERROR("ceph plugin: No daemons configured. See the \"Daemon\" config " + "option."); + return ENOENT; + } + + return cconn_main_loop(ASOK_REQ_VERSION); } -static int ceph_shutdown(void) -{ - int i; - for(i = 0; i < g_num_daemons; ++i) - { - ceph_daemon_free(g_daemons[i]); - } - sfree(g_daemons); - g_daemons = NULL; - g_num_daemons = 0; - DEBUG("ceph plugin: finished ceph_shutdown"); - return 0; +static int ceph_shutdown(void) { + for (size_t i = 0; i < g_num_daemons; ++i) { + ceph_daemon_free(g_daemons[i]); + } + sfree(g_daemons); + g_daemons = NULL; + g_num_daemons = 0; + DEBUG("ceph plugin: finished ceph_shutdown"); + return 0; } -void module_register(void) -{ - plugin_register_complex_config("ceph", ceph_config); - plugin_register_init("ceph", ceph_init); - plugin_register_read("ceph", ceph_read); - plugin_register_shutdown("ceph", ceph_shutdown); +void module_register(void) { + plugin_register_complex_config("ceph", ceph_config); + plugin_register_init("ceph", ceph_init); + plugin_register_read("ceph", ceph_read); + plugin_register_shutdown("ceph", ceph_shutdown); } /* vim: set sw=4 sts=4 et : */ diff --git a/src/ceph_test.c b/src/ceph_test.c index ae67125f..3da4098c 100644 --- a/src/ceph_test.c +++ b/src/ceph_test.c @@ -22,22 +22,19 @@ #include "ceph.c" /* sic */ #include "testing.h" -struct case_s -{ - char *key; - char *value; +struct case_s { + const char *key; + const char *value; }; typedef struct case_s case_t; -struct test_s -{ +struct test_s { case_t *cases; - size_t cases_num; + size_t cases_num; }; typedef struct test_s test_t; -static int test_handler(void *user, char const *val, char const *key) -{ +static int test_handler(void *user, char const *val, char const *key) { test_t *t = user; size_t i; @@ -45,25 +42,26 @@ static int test_handler(void *user, char const *val, char const *key) _Bool ok; /* special case for latency metrics. */ - if (strcmp ("filestore.example_latency", key) == 0) + if (strcmp("filestore.example_latency", key) == 0) return RETRY_AVGCOUNT; - snprintf (status, sizeof (status), "unexpected call: test_handler(\"%s\") = \"%s\"", key, val); + snprintf(status, sizeof(status), + "unexpected call: test_handler(\"%s\") = \"%s\"", key, val); ok = 0; - for (i = 0; i < t->cases_num; i++) - { - if (strcmp (key, t->cases[i].key) != 0) + for (i = 0; i < t->cases_num; i++) { + if (strcmp(key, t->cases[i].key) != 0) continue; - if (strcmp (val, t->cases[i].value) != 0) - { - snprintf (status, sizeof (status), "test_handler(\"%s\") = \"%s\", want \"%s\"", key, val, t->cases[i].value); + if (strcmp(val, t->cases[i].value) != 0) { + snprintf(status, sizeof(status), + "test_handler(\"%s\") = \"%s\", want \"%s\"", key, val, + t->cases[i].value); ok = 0; break; } - snprintf (status, sizeof (status), "test_handler(\"%s\") = \"%s\"", key, val); + snprintf(status, sizeof(status), "test_handler(\"%s\") = \"%s\"", key, val); ok = 1; break; } @@ -72,9 +70,9 @@ static int test_handler(void *user, char const *val, char const *key) return ok ? 0 : -1; } -DEF_TEST(traverse_json) -{ - char const *json = "{\n" +DEF_TEST(traverse_json) { + char const *json = + "{\n" " \"WBThrottle\": {\n" " \"bytes_dirtied\": {\n" " \"type\": 2,\n" @@ -119,69 +117,71 @@ DEF_TEST(traverse_json) " }\n" "}\n"; case_t cases[] = { - {"WBThrottle.bytes_dirtied.type", "2"}, - {"WBThrottle.bytes_wb.type", "2"}, - {"WBThrottle.ios_dirtied.type", "2"}, - {"WBThrottle.ios_wb.type", "2"}, - {"WBThrottle.inodes_dirtied.type", "2"}, - {"WBThrottle.inodes_wb.type", "10"}, - {"filestore.journal_wr_bytes", "3117"}, - {"filestore.example_latency.avgcount", "42"}, - {"filestore.example_latency.sum", "4711"}, + {"WBThrottle.bytes_dirtied.type", "2"}, + {"WBThrottle.bytes_wb.type", "2"}, + {"WBThrottle.ios_dirtied.type", "2"}, + {"WBThrottle.ios_wb.type", "2"}, + {"WBThrottle.inodes_dirtied.type", "2"}, + {"WBThrottle.inodes_wb.type", "10"}, + {"filestore.journal_wr_bytes", "3117"}, + {"filestore.example_latency.avgcount", "42"}, + {"filestore.example_latency.sum", "4711"}, }; - test_t t = {cases, STATIC_ARRAY_SIZE (cases)}; + test_t t = {cases, STATIC_ARRAY_SIZE(cases)}; yajl_struct ctx = {test_handler, &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 (yajl_complete_parse (hndl)); + hndl = yajl_alloc(&callbacks, NULL, &ctx); + 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 (yajl_parse_complete (hndl)); + hndl = yajl_alloc(&callbacks, NULL, NULL, &ctx); + 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) -{ +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"}, - {"foo:bar", "FooBar"}, - {"foo:bar+", "FooBarPlus"}, - {"foo:bar-", "FooBarMinus"}, - {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+", "AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPlus"}, - {"aa.bb.cc.dd.ee.ff", "Aa.bb.cc.dd.ee.ff"}, - {"aa.bb.cc.dd.ee.ff.type", "Aa.bb.cc.dd.ee.ff"}, - {"aa.type", "Aa.type"}, - {"WBThrottle.bytes_dirtied.type", "WBThrottle.bytesDirtied"}, + {"WBThrottle.bytes_dirtied.description.bytes_wb.description.ios_dirtied." + "description.ios_wb.type", + "WBThrottle.bytesDirtied.description.bytesWb.description.iosDirt"}, + {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, + {"foo:bar", "FooBar"}, + {"foo:bar+", "FooBarPlus"}, + {"foo:bar-", "FooBarMinus"}, + {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+", + "AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPlus"}, + {"aa.bb.cc.dd.ee.ff", "Aa.bb.cc.dd.ee.ff"}, + {"aa.bb.cc.dd.ee.ff.type", "Aa.bb.cc.dd.ee.ff"}, + {"aa.type", "Aa.type"}, + {"WBThrottle.bytes_dirtied.type", "WBThrottle.bytesDirtied"}, }; size_t i; - for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) - { - char got[DATA_MAX_NAME_LEN]; + for (i = 0; i < STATIC_ARRAY_SIZE(cases); i++) { + char got[64]; - memset (got, 0, sizeof (got)); - - CHECK_ZERO (parse_keys (got, sizeof (got), cases[i].str)); - - CHECK_ZERO (strcmp (got, cases[i].want)); + CHECK_ZERO(parse_keys(got, sizeof(got), cases[i].str)); + EXPECT_EQ_STR(cases[i].want, got); } return 0; } -int main (void) -{ +int main(void) { RUN_TEST(traverse_json); RUN_TEST(parse_keys); diff --git a/src/cgroups.c b/src/cgroups.c index 6d419722..97ec64b6 100644 --- a/src/cgroups.c +++ b/src/cgroups.c @@ -22,124 +22,110 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" -#include "configfile.h" -#include "utils_mount.h" #include "utils_ignorelist.h" +#include "utils_mount.h" -static char const *config_keys[] = -{ - "CGroup", - "IgnoreSelected" -}; -static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); +static char const *config_keys[] = {"CGroup", "IgnoreSelected"}; +static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static ignorelist_t *il_cgroup = NULL; -__attribute__ ((nonnull(1))) -__attribute__ ((nonnull(2))) -static void cgroups_submit_one (char const *plugin_instance, - char const *type_instance, 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, "cgroups", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, plugin_instance, - sizeof (vl.plugin_instance)); - sstrncpy (vl.type, "cpu", sizeof (vl.type)); - sstrncpy (vl.type_instance, type_instance, - sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); +__attribute__((nonnull(1))) __attribute__((nonnull(2))) static void +cgroups_submit_one(char const *plugin_instance, char const *type_instance, + 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, "cgroups", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance)); + sstrncpy(vl.type, "cpu", sizeof(vl.type)); + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); + + plugin_dispatch_values(&vl); } /* void cgroups_submit_one */ /* * This callback reads the user/system CPU time for each cgroup. */ -static int read_cpuacct_procs (const char *dirname, char const *cgroup_name, - void *user_data) -{ - char abs_path[PATH_MAX]; - struct stat statbuf; - char buf[1024]; - int status; - - FILE *fh; - - if (ignorelist_match (il_cgroup, cgroup_name)) - return (0); - - ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, cgroup_name); - - status = lstat (abs_path, &statbuf); - if (status != 0) - { - ERROR ("cgroups plugin: stat (\"%s\") failed.", - abs_path); - return (-1); - } - - /* We are only interested in directories, so skip everything else. */ - if (!S_ISDIR (statbuf.st_mode)) - return (0); - - ssnprintf (abs_path, sizeof (abs_path), "%s/%s/cpuacct.stat", - dirname, cgroup_name); - fh = fopen (abs_path, "r"); - if (fh == NULL) - { - char errbuf[1024]; - ERROR ("cgroups plugin: fopen (\"%s\") failed: %s", - abs_path, - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); - } - - while (fgets (buf, sizeof (buf), fh) != NULL) - { - char *fields[8]; - int numfields = 0; - char *key; - size_t key_len; - value_t value; - - /* Expected format: - * - * user: 12345 - * system: 23456 - * - * Or: - * - * user 12345 - * system 23456 - */ - strstripnewline (buf); - numfields = strsplit (buf, fields, STATIC_ARRAY_SIZE (fields)); - if (numfields != 2) - continue; - - key = fields[0]; - key_len = strlen (key); - if (key_len < 2) - continue; - - /* Strip colon off the first column, if found */ - if (key[key_len - 1] == ':') - key[key_len - 1] = 0; - - status = parse_value (fields[1], &value, DS_TYPE_DERIVE); - if (status != 0) - continue; - - cgroups_submit_one (cgroup_name, key, value); - } - - fclose (fh); - return (0); +static int read_cpuacct_procs(const char *dirname, char const *cgroup_name, + void *user_data) { + char abs_path[PATH_MAX]; + struct stat statbuf; + char buf[1024]; + int status; + + FILE *fh; + + if (ignorelist_match(il_cgroup, cgroup_name)) + return (0); + + ssnprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, cgroup_name); + + status = lstat(abs_path, &statbuf); + if (status != 0) { + ERROR("cgroups plugin: stat (\"%s\") failed.", abs_path); + return (-1); + } + + /* We are only interested in directories, so skip everything else. */ + if (!S_ISDIR(statbuf.st_mode)) + return (0); + + ssnprintf(abs_path, sizeof(abs_path), "%s/%s/cpuacct.stat", dirname, + cgroup_name); + fh = fopen(abs_path, "r"); + if (fh == NULL) { + char errbuf[1024]; + ERROR("cgroups plugin: fopen (\"%s\") failed: %s", abs_path, + sstrerror(errno, errbuf, sizeof(errbuf))); + return (-1); + } + + while (fgets(buf, sizeof(buf), fh) != NULL) { + char *fields[8]; + int numfields = 0; + char *key; + size_t key_len; + value_t value; + + /* Expected format: + * + * user: 12345 + * system: 23456 + * + * Or: + * + * user 12345 + * system 23456 + */ + strstripnewline(buf); + numfields = strsplit(buf, fields, STATIC_ARRAY_SIZE(fields)); + if (numfields != 2) + continue; + + key = fields[0]; + key_len = strlen(key); + if (key_len < 2) + continue; + + /* Strip colon off the first column, if found */ + if (key[key_len - 1] == ':') + key[key_len - 1] = 0; + + status = parse_value(fields[1], &value, DS_TYPE_DERIVE); + if (status != 0) + continue; + + cgroups_submit_one(cgroup_name, key, value); + } + + fclose(fh); + return (0); } /* int read_cpuacct_procs */ /* @@ -147,110 +133,95 @@ static int read_cpuacct_procs (const char *dirname, char const *cgroup_name, * wherever cpuacct is mounted on the system). Calls walk_directory with the * read_cpuacct_procs callback on every folder it finds, such as "system". */ -static int read_cpuacct_root (const char *dirname, const char *filename, - void *user_data) -{ - char abs_path[PATH_MAX]; - struct stat statbuf; - int status; - - ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, filename); - - status = lstat (abs_path, &statbuf); - if (status != 0) - { - ERROR ("cgroups plugin: stat (%s) failed.", abs_path); - return (-1); - } - - if (S_ISDIR (statbuf.st_mode)) - { - status = walk_directory (abs_path, read_cpuacct_procs, - /* user_data = */ NULL, - /* include_hidden = */ 0); - return (status); - } - - return (0); +static int read_cpuacct_root(const char *dirname, const char *filename, + void *user_data) { + char abs_path[PATH_MAX]; + struct stat statbuf; + int status; + + ssnprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename); + + status = lstat(abs_path, &statbuf); + if (status != 0) { + ERROR("cgroups plugin: stat (%s) failed.", abs_path); + return (-1); + } + + if (S_ISDIR(statbuf.st_mode)) { + status = walk_directory(abs_path, read_cpuacct_procs, + /* user_data = */ NULL, + /* include_hidden = */ 0); + return (status); + } + + return (0); } -static int cgroups_init (void) -{ - if (il_cgroup == NULL) - il_cgroup = ignorelist_create (1); +static int cgroups_init(void) { + if (il_cgroup == NULL) + il_cgroup = ignorelist_create(1); - return (0); + return (0); } -static int cgroups_config (const char *key, const char *value) -{ - cgroups_init (); - - if (strcasecmp (key, "CGroup") == 0) - { - if (ignorelist_add (il_cgroup, value)) - return (1); - return (0); - } - else if (strcasecmp (key, "IgnoreSelected") == 0) - { - if (IS_TRUE (value)) - ignorelist_set_invert (il_cgroup, 0); - else - ignorelist_set_invert (il_cgroup, 1); - return (0); - } - - return (-1); +static int cgroups_config(const char *key, const char *value) { + cgroups_init(); + + if (strcasecmp(key, "CGroup") == 0) { + if (ignorelist_add(il_cgroup, value)) + return (1); + return (0); + } else if (strcasecmp(key, "IgnoreSelected") == 0) { + if (IS_TRUE(value)) + ignorelist_set_invert(il_cgroup, 0); + else + ignorelist_set_invert(il_cgroup, 1); + return (0); + } + + return (-1); } -static int cgroups_read (void) -{ - cu_mount_t *mnt_list; - cu_mount_t *mnt_ptr; - _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) - { - /* Find the cgroup mountpoint which contains the cpuacct - * controller. */ - if ((strcmp(mnt_ptr->type, "cgroup") != 0) - || !cu_mount_checkoption(mnt_ptr->options, - "cpuacct", /* full = */ 1)) - continue; - - walk_directory (mnt_ptr->dir, read_cpuacct_root, - /* user_data = */ NULL, - /* include_hidden = */ 0); - cgroup_found = 1; - /* It doesn't make sense to check other cpuacct mount-points - * (if any), they contain the same data. */ - break; - } - - cu_mount_freelist (mnt_list); - - if (!cgroup_found) - { - WARNING ("cgroups plugin: Unable to find cgroup " - "mount-point with the \"cpuacct\" option."); - return (-1); - } - - return (0); +static int cgroups_read(void) { + cu_mount_t *mnt_list = NULL; + _Bool cgroup_found = 0; + + if (cu_mount_getlist(&mnt_list) == NULL) { + ERROR("cgroups plugin: cu_mount_getlist failed."); + return (-1); + } + + 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. */ + if ((strcmp(mnt_ptr->type, "cgroup") != 0) || + !cu_mount_checkoption(mnt_ptr->options, "cpuacct", /* full = */ 1)) + continue; + + walk_directory(mnt_ptr->dir, read_cpuacct_root, + /* user_data = */ NULL, + /* include_hidden = */ 0); + cgroup_found = 1; + /* It doesn't make sense to check other cpuacct mount-points + * (if any), they contain the same data. */ + break; + } + + cu_mount_freelist(mnt_list); + + if (!cgroup_found) { + WARNING("cgroups plugin: Unable to find cgroup " + "mount-point with the \"cpuacct\" option."); + return (-1); + } + + return (0); } /* int cgroup_read */ -void module_register (void) -{ - plugin_register_config ("cgroups", cgroups_config, - config_keys, config_keys_num); - plugin_register_init ("cgroups", cgroups_init); - plugin_register_read ("cgroups", cgroups_read); +void module_register(void) { + plugin_register_config("cgroups", cgroups_config, config_keys, + config_keys_num); + plugin_register_init("cgroups", cgroups_init); + plugin_register_read("cgroups", cgroups_read); } /* void module_register */ diff --git a/src/chrony.c b/src/chrony.c new file mode 100644 index 00000000..a10e5f68 --- /dev/null +++ b/src/chrony.c @@ -0,0 +1,1014 @@ +/* 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 /* struct addrinfo */ +#endif +#if HAVE_ARPA_INET_H +#include /* 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 aade08a4..afa7e48a 100644 --- a/src/collectd-java.pod +++ b/src/collectd-java.pod @@ -620,6 +620,11 @@ sets the type instance instead. I<(optional)> Works like the option of the same name directly beneath the I block, but sets the type instance instead. I<(optional)> +=item B I + +When set, overrides the default setting for the I field +(C). + =item B B|B Set this to true if the returned attribute is a I. If set to diff --git a/src/collectd-lua.pod b/src/collectd-lua.pod new file mode 100644 index 00000000..7a256550 --- /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 + +=head1 SYNOPSIS + + LoadPlugin lua + # ... + + BasePath "/path/to/your/lua/scripts" + Script "script1.lua" + Script "script2.lua" + + +=head1 DESCRIPTION + +The C 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 (see +L) and provides a lot more functionality, too. + +The minimum required Lua version is I<5.1>. + +=head1 CONFIGURATION + +=over 4 + +=item B I + +Loads the Lua plugin. + +=item B I + +The directory the C looks in to find script B