]> arthur.barton.de Git - netdata.git/commitdiff
Merge pull request #1916 from l2isbad/MySQLService_class
authorCosta Tsaousis <costa@tsaousis.gr>
Mon, 13 Mar 2017 08:41:29 +0000 (10:41 +0200)
committerGitHub <noreply@github.com>
Mon, 13 Mar 2017 08:41:29 +0000 (10:41 +0200)
MySQLService class added + rewritten mysql_plugin

46 files changed:
CMakeLists.txt
Makefile.am
README.md
conf.d/Makefile.am
conf.d/python.d/nsd.conf [new file with mode: 0644]
conf.d/stream.conf
configs.signatures
configure.ac
m4/ax_c_lto.m4 [new file with mode: 0644]
netdata-installer.sh
node.d/snmp.node.js
plugins.d/alarm-notify.sh
python.d/Makefile.am
python.d/README.md
python.d/nsd.chart.py [new file with mode: 0644]
python.d/tomcat.chart.py
src/Makefile.am
src/appconfig.c
src/appconfig.h
src/apps_plugin.c
src/avl.c
src/avl.h
src/clocks.c
src/common.h
src/dictionary.c
src/dictionary.h
src/freeipmi_plugin.c
src/global_statistics.c
src/health.c
src/health.h
src/health_json.c
src/health_log.c
src/locks.h [new file with mode: 0644]
src/log.h
src/main.c
src/registry.c
src/registry_init.c
src/registry_internals.h
src/rrd.h
src/rrd2json.c
src/rrd2json.h
src/rrdhost.c
src/rrdpush.c
src/rrdset.c
src/web_api_v1.c
web/index.html

index 705077f994e12f16bfa5cade9043545b7577d158..d848c5c84e03c6a07a506fd2d9d3ca82a0ea5300 100755 (executable)
@@ -144,7 +144,7 @@ set(NETDATA_SOURCE_FILES
         src/web_client.h
         src/web_server.c
         src/web_server.h
-        )
+        src/locks.h)
 
 set(APPS_PLUGIN_SOURCE_FILES
         src/appconfig.c
index e78bbbbd5e69aee62a72df7034c14a3a68f6d073..3ccf82f8f5e8d76ab149749943df1feec8c7e64e 100644 (file)
@@ -23,8 +23,18 @@ EXTRA_DIST = \
        .eslintignore \
        .eslintrc \
        .travis \
-       m4/ax_check_enable_debug.m4 \
-       m4/ax_c_statement_expressions.m4 \
+       m4/jemalloc.m4 \
+    m4/ax_c___atomic.m4 \
+    m4/ax_check_enable_debug.m4 \
+    m4/ax_c_mallinfo.m4 \
+    m4/ax_gcc_func_attribute.m4 \
+    m4/ax_check_compile_flag.m4 \
+    m4/ax_c_statement_expressions.m4 \
+    m4/ax_pthread.m4 \
+    m4/ax_c_lto.m4 \
+    m4/ax_c_mallopt.m4 \
+    m4/tcmalloc.m4 \
+    m4/ax_c__generic.m4 \
        autogen.sh \
        README.md \
        LICENSE.md \
@@ -48,6 +58,8 @@ SUBDIRS = \
 dist_noinst_DATA= \
        diagrams/config.puml \
        diagrams/registry.puml \
+       diagrams/netdata-for-ephemeral-nodes.xml \
+       diagrams/netdata-proxies-example.xml \
        configs.signatures \
        Dockerfile \
        netdata.spec \
index 240ab32be600590da0c7072e5da0076b261595f0..3d73b9ecce452c2a9c340e71990c5014501f133a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# netdata [![Build Status](https://travis-ci.org/firehol/netdata.svg?branch=master)](https://travis-ci.org/firehol/netdata) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9140/badge.svg)](https://scan.coverity.com/projects/firehol-netdata) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a994873f30d045b9b4b83606c3eb3498)](https://www.codacy.com/app/netdata/netdata?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=firehol/netdata&amp;utm_campaign=Badge_Grade) [![Code Climate](https://codeclimate.com/github/firehol/netdata/badges/gpa.svg)](https://codeclimate.com/github/firehol/netdata) [![Docker Pulls](https://img.shields.io/docker/pulls/titpetric/netdata.svg)](https://hub.docker.com/r/titpetric/netdata/) [![Twitter Follow](https://img.shields.io/twitter/follow/linuxnetdata.svg?style=social&label=netdata%20on%20twitter)](https://twitter.com/linuxnetdata)
+# netdata [![Build Status](https://travis-ci.org/firehol/netdata.svg?branch=master)](https://travis-ci.org/firehol/netdata) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9140/badge.svg)](https://scan.coverity.com/projects/firehol-netdata) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a994873f30d045b9b4b83606c3eb3498)](https://www.codacy.com/app/netdata/netdata?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=firehol/netdata&amp;utm_campaign=Badge_Grade) [![Code Climate](https://codeclimate.com/github/firehol/netdata/badges/gpa.svg)](https://codeclimate.com/github/firehol/netdata)
 > *New to netdata? Here is a live demo: [http://my-netdata.io](http://my-netdata.io)*
 
 **netdata** is a system for **distributed real-time performance and health monitoring**.
@@ -10,12 +10,16 @@ _netdata is **fast** and **efficient**, designed to permanently run on all syste
 (**physical** & **virtual** servers, **containers**, **IoT** devices), without
 disrupting their core function._
 
+netdata runs on **Linux**, **FreeBSD**, and **MacOS**.
+
+[![Twitter Follow](https://img.shields.io/twitter/follow/linuxnetdata.svg?style=social&label=New%20-%20stay%20in%20touch%20-%20follow%20netdata%20on%20twitter)](https://twitter.com/linuxnetdata)
+
 ---
 
 ## User base
 
 *Since May 16th 2016 (the date the [global public netdata registry](https://github.com/firehol/netdata/wiki/mynetdata-menu-item) was released):*<br/>
-[![User Base](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&label=user%20base&units=null&value_color=blue&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Monitored Servers](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&label=servers%20monitored&units=null&value_color=orange&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Sessions Served](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&label=sessions%20served&units=null&value_color=yellowgreen&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry)
+[![User Base](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&label=user%20base&units=null&value_color=blue&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Monitored Servers](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&label=servers%20monitored&units=null&value_color=orange&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Sessions Served](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&label=sessions%20served&units=null&value_color=yellowgreen&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Docker Pulls](https://img.shields.io/docker/pulls/titpetric/netdata.svg)](https://hub.docker.com/r/titpetric/netdata/)
 
 *in the last 24 hours:*<br/>
 [![New Users Today](http://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&after=-86400&options=unaligned&group=incremental-sum&label=new%20users%20today&units=null&value_color=blue&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![New Machines Today](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&group=incremental-sum&after=-86400&options=unaligned&label=servers%20added%20today&units=null&value_color=orange&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry) [![Sessions Today](https://registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&after=-86400&group=incremental-sum&options=unaligned&label=sessions%20served%20today&units=null&value_color=yellowgreen&precision=0&v42)](https://registry.my-netdata.io/#menu_netdata_submenu_registry)
@@ -60,6 +64,7 @@ Netdata is featured at <b><a href="https://octoverse.github.com/" target="_blank
    with just 1% CPU utilization of a single core, a few MB of RAM and no disk I/O at all
    
  - **Sophisticated alarming**<br/>
+   hundreds of alarms, **out of the box**!<br/>
    supports dynamic thresholds, hysteresis, alarm templates,
    multiple role-based notification methods (such as email, slack.com,
    pushover.net, pushbullet.com, telegram.org, twilio.com, messagebird.com)
@@ -89,8 +94,12 @@ Netdata is featured at <b><a href="https://octoverse.github.com/" target="_blank
  - **scales to infinity**<br/>
    requiring minimal central resources
    
- - **back-ends supported**<br/>
-   can archive its metrics on `graphite` or `opentsdb`, in the same or lower detail
+ - **several operating modes**<br/>
+   autonomous host monitoring, headless data collector, forwarding proxy, store and forward proxy, central multi-host monitoring, in all possible configurations.
+   Each node may have different metrics retention policy and run with or without health monitoring.
+   
+ - **time-series back-ends supported**<br/>
+   can archive its metrics on `graphite`, `opentsdb`, `prometheus`, json document DBs, in the same or lower detail
    (lower: to prevent it from congesting these servers due to the amount of data collected)
 
 ![netdata](https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif)
@@ -99,7 +108,7 @@ Netdata is featured at <b><a href="https://octoverse.github.com/" target="_blank
 
 ## What does it monitor?
 
-netdata monitors several thousands of metrics per device.
+netdata collects several thousands of metrics per device.
 All these metrics are collected and visualized in real-time.
 
 > _Almost all metrics are auto-detected, without any configuration._
@@ -107,13 +116,13 @@ All these metrics are collected and visualized in real-time.
 This is a list of what it currently monitors:
 
 - **CPU**<br/>
-  usage, interrupts, softirqs, frequency, total and per core
+  usage, interrupts, softirqs, frequency, total and per core, CPU states
 
 - **Memory**<br/>
   RAM, swap and kernel memory usage, KSM (Kernel Samepage Merging), NUMA
 
 - **Disks**<br/>
-  per disk: I/O, operations, backlog, utilization, space
+  per disk: I/O, operations, backlog, utilization, space, software RAID (md)
 
    ![sda](https://cloud.githubusercontent.com/assets/2662304/14093195/c882bbf4-f554-11e5-8863-1788d643d2c0.gif)
 
@@ -189,6 +198,9 @@ This is a list of what it currently monitors:
 - **Tomcat**<br/>
   accesses, threads, free memory, volume
 
+- **web server log files**<br/>
+  extracting in real-time, web server performance metrics and applying several health checks
+
 - **mySQL databases**<br/>
   multiple servers, each showing: bandwidth, queries/s, handlers, locks, issues,
   tmp operations, connections, binlog metrics, threads, innodb metrics, and more
@@ -201,12 +213,21 @@ This is a list of what it currently monitors:
 - **Redis databases**<br/>
   multiple servers, each showing: operations, hit rate, memory, keys, clients, slaves
 
+- **mongodb**<br/>
+  operations, clients, transactions, cursors, connections, asserts, locks, etc
+
 - **memcached databases**<br/>
   multiple servers, each showing: bandwidth, connections, items
 
+- **elasticsearch**<br/>
+  search and index performance, latency, timings, cluster statistics, threads statistics, etc
+
 - **ISC Bind name servers**<br/>
   multiple servers, each showing: clients, requests, queries, updates, failures and several per view metrics
 
+- **NSD name servers**<br/>
+  queries, zones, protocols, query types, transfers, etc.
+
 - **Postfix email servers**<br/>
   message queue (entries, size)
 
@@ -215,14 +236,26 @@ This is a list of what it currently monitors:
 
 - **Dovecot** POP3/IMAP servers<br/>
 
+- **ISC dhcpd**<br/>
+  pools utilization, leases, etc.
+
 - **IPFS**<br/>
   bandwidth, peers
 
 - **Squid proxy servers**<br/>
   multiple servers, each showing: clients bandwidth and requests, servers bandwidth and requests
 
+- **HAproxy**<br/>
+  bandwidth, sessions, backends, etc
+
+- **varnish**<br/>
+  threads, sessions, hits, objects, backends, etc
+
+- **OpenVPN**<br/>
+  status per tunnel
+
 - **Hardware sensors**<br/>
-  temperature, voltage, fans, power, humidity
+  `lm_sensors` and `IPMI`: temperature, voltage, fans, power, humidity
 
 - **NUT and APC UPSes**<br/>
   load, charge, battery voltage, temperature, utility metrics, output metrics
@@ -233,6 +266,9 @@ This is a list of what it currently monitors:
 - **hddtemp**<br/>
   disk temperatures
 
+- **smartd**<br/>
+  disk S.M.A.R.T. values
+
 - **SNMP devices**<br/>
   can be monitored too (although you will need to configure these)
 
index 47f6573c79632d36e7a10c530438db80ee5840f6..efe1f2a6e34d0af98c2153340d809b37f9859543 100644 (file)
@@ -43,6 +43,7 @@ dist_pythonconfig_DATA = \
     python.d/mongodb.conf \
     python.d/mysql.conf \
     python.d/nginx.conf \
+    python.d/nsd.conf \
     python.d/ovpn_status_log.conf \
     python.d/phpfpm.conf \
     python.d/postfix.conf \
diff --git a/conf.d/python.d/nsd.conf b/conf.d/python.d/nsd.conf
new file mode 100644 (file)
index 0000000..7566fe8
--- /dev/null
@@ -0,0 +1,86 @@
+# netdata python.d.plugin configuration for nsd
+#
+# This file is in YaML format. Generally the format is:
+#
+# name: value
+#
+# There are 2 sections:
+#  - global variables
+#  - one or more JOBS
+#
+# JOBS allow you to collect values from multiple sources.
+# Each source will have its own set of charts.
+#
+# JOB parameters have to be indented (using spaces only, example below).
+
+# ----------------------------------------------------------------------
+# Global Variables
+# These variables set the defaults for all JOBs, however each JOB
+# may define its own, overriding the defaults.
+
+# update_every sets the default data collection frequency.
+# If unset, the python.d.plugin default is used.
+# nsd-control is slow, so once every 30 seconds
+# update_every: 30
+
+# priority controls the order of charts at the netdata dashboard.
+# Lower numbers move the charts towards the top of the page.
+# If unset, the default for python.d.plugin is used.
+# priority: 60000
+
+# retries sets the number of retries to be made in case of failures.
+# If unset, the default for python.d.plugin is used.
+# Attempts to restore the service are made once every update_every
+# and only if the module has collected values in the past.
+# retries: 5
+
+# ----------------------------------------------------------------------
+# JOBS (data collection sources)
+#
+# The default JOBS share the same *name*. JOBS with the same name
+# are mutually exclusive. Only one of them will be allowed running at
+# any time. This allows autodetection to try several alternatives and
+# pick the one that works.
+#
+# Any number of jobs is supported.
+#
+# All python.d.plugin JOBS (for all its modules) support a set of
+# predefined parameters. These are:
+#
+# job_name:
+#     name: myname     # the JOB's name as it will appear at the
+#                      # dashboard (by default is the job_name)
+#                      # JOBs sharing a name are mutually exclusive
+#     update_every: 1  # the JOB's data collection frequency
+#     priority: 60000  # the JOB's order on the dashboard
+#     retries: 5       # the JOB's number of restoration attempts
+#
+# Additionally to the above, nsd also supports the following:
+#
+#     command: 'nsd-control stats_noreset' # the command to run
+#
+
+# ----------------------------------------------------------------------
+# IMPORTANT Information
+#
+# Netdata must have permissions to run `nsd-control stats_noreset` command
+#
+# - Example-1 (use "sudo")
+# 1. sudoers (e.g. visudo -f /etc/sudoers.d/netdata)
+#       Defaults:netdata   !requiretty
+#       netdata ALL=(ALL)  NOPASSWD: /usr/sbin/nsd-control stats_noreset
+# 2. etc/netdata/python.d/nsd.conf
+#       local:
+#         update_every: 30
+#         command: 'sudo /usr/sbin/nsd-control stats_noreset'
+#
+# - Example-2 (add "netdata" user to "nsd" group)
+# usermod -aG nsd netdata
+#
+
+# ----------------------------------------------------------------------
+# AUTO-DETECTION JOBS
+
+local:
+  update_every: 30
+  command: 'nsd-control stats_noreset'
index 641faaae77f782ec87ce9aeee86b0f239bcff32c..0ebdccb8aec0a4a34bc60965ccedf4057b23a263 100644 (file)
@@ -7,32 +7,49 @@
 # You can generate API keys, with the linux command: uuidgen
 #
 # -----------------------------------------------------------------------------
-# 1. SLAVE NETDATA - THE ONE THAT WILL BE SENDING METRICS
+# 1. ON SLAVE NETDATA - THE ONE THAT WILL BE SENDING METRICS
 
 [stream]
+    # Enable this on slaves, to have them send metrics.
        enabled = no
 
-       # where to send metrics to?
-       # A space separated list of IP:PORT is accepted. The first available will
-       # get the metrics.
-       # IPv6 addresses should be [IP]:PORT
+       # The destination to send metrics to.
+       # A space separated list of:
+       #         [PROTOCOL:]HOST[%INTERFACE][:PORT]
+       # The first available will get the metrics.
+       # PROTOCOL = tcp or udp (only tcp is supported by masters)
+       # HOST = an IPv4, IPv6 IP, or a hostname.
+       #        IPv6 IPs should be given with brackets [ip:address]
+       # INTERFACE = the network interface to use
+       # PORT = the port number or service name (/etc/services)
+       # This communication is not HTTP (cannot be proxied by web proxies).
        destination =
 
        # The API_KEY to use (as the sender)
        api key =
 
-       # other options (uncomment and set)
+    # The timeout to connect and send metrics
+       timeout seconds = 60
 
-       # timeout seconds = 60
-       # default port = 19999
-       # buffer size bytes = 1048576
-       # reconnect delay seconds = 5
-       # initial clock resync iterations = 60
-       # free orphan hosts after seconds = 3600
+       # If the destination line above does specify a port, use this
+       default port = 19999
+
+       # The buffer to use for sending metrics.
+       # 1MB by default is good for 2-3 seconds of data, so increase this
+       # if you expect latencies.
+       buffer size bytes = 1048576
+
+       # If the connection fails, or it disconnects,
+       # retry after that many seconds.
+       reconnect delay seconds = 5
+
+       # Attempt to sync the clock the of the master with the clock of the
+       # slave for that many iterations, when starting.
+       initial clock resync iterations = 60
 
 
 # -----------------------------------------------------------------------------
-# 2. MASTER NETDATA - THE ONE THAT WILL BE RECEIVING METRICS
+# 2. ON MASTER NETDATA - THE ONE THAT WILL BE RECEIVING METRICS
 #
 #    You can have one API key per slave, or the same API key for all slaves.
 #
 
 
 # -----------------------------------------------------------------------------
+# 3. ON MASTER NETDATA - THE ONE THAT WILL BE RECEIVING METRICS
+#
+# THIS IS OPTIONAL - YOU DON'T NEED IT BY DEFAULT
+# It only exists to give you finer control of the master settings for each
+# slave host, when the same API key is used by many netdata slaves / proxies.
+#
 # Each netdata has a unique GUID - generated the first time netdata starts.
 # You can find it at /var/lib/netdata/registry/netdata.public.unique.id
-# The host sending data will have one. If it is static and you can find it,
+# The host sending data will have one. If the host is not ephemeral,
 # you can give settings for each specific host here.
 
 [MACHINE_GUID]
     # enable this host: yes | no
+    # When disabled, the master will not receive metrics for this host.
     # THIS IS NOT A SECURITY MECHANISM - AN ATTACKER CAN SET ANY OTHER GUID.
     # Use only the API key for security.
     enabled = no
index 9a312989a8d4a0d055bbdca4597fba11d9b35824..593628dac05dcc0e26523ea6a10c41a1563e10b8 100644 (file)
@@ -149,6 +149,7 @@ declare -A configs_signatures=(
   ['573398335c0c71c075fa57f702bce287']='health.d/disks.conf'
   ['5829812db29598db5857c9f433e96fef']='python.d/apache.conf'
   ['58e835b7176865ec5a6f59f7aba832bf']='health.d/named.conf'
+  ['598f9814966a9e2fe48e8218151d3fa6']='stream.conf'
   ['5b917d894bb6a755d59264e9d48e9d56']='fping.conf'
   ['5bbef0708f5eff4d4a53aaf35fc48a62']='health.d/disks.conf'
   ['5bf51bb24fb41db9b1e448bd060d3f8c']='apps_groups.conf'
@@ -231,6 +232,8 @@ declare -A configs_signatures=(
   ['845023f9b4a526aa0e6493756dbe6034']='health.d/squid.conf'
   ['846ce94bfeeb90c0dc6a89e8d25f1a68']='health.d/named.conf'
   ['8490f690d97adacc4e2096df82e7e8a5']='charts.d/cpufreq.conf'
+  ['871bbeea33b83ea9755600b6d574919c']='python.d/web_log.conf'
+  ['87224d2f2b87646f3c0d38cc1eb30112']='python.d/nsd.conf'
   ['8810140ce9c09af1d18b9602c4003904']='health_alarm_notify.conf'
   ['88f77865f75c9fb61c97d700bd4561ee']='python.d/mysql.conf'
   ['8989b5e2f4ef9cd278ef58be0fae4074']='health.d/disks.conf'
@@ -382,6 +385,7 @@ declare -A configs_signatures=(
   ['e734c5951a8764d4d9de046dd7cf7407']='health.d/softnet.conf'
   ['e7bc22a1942cffbd2b1b0cfd119ee328']='health.d/ipfs.conf'
   ['e8ec8046c7007af6ca3e8c51e62c99f8']='health.d/disks.conf'
+  ['ea1a96c42ad464c354fb250e3408c3e8']='stream.conf'
   ['eaa7beb935cae9c48a40fb934eb105a7']='health.d/web_log.conf'
   ['eb5168f0b516bc982aac45e59da6e52e']='health.d/nginx.conf'
   ['eb748d6fb69d11b0d29c5794657e206c']='health.d/qos.conf'
index 81af5a0a1edd66930480a371c6a1dca0a590729a..ddbc28e44fa2736d94eaa473a44fd12f8c9773c4 100644 (file)
@@ -101,6 +101,12 @@ AC_ARG_ENABLE(
     ,
     [enable_x86_sse="yes"]
 )
+AC_ARG_ENABLE(
+    [lto],
+    [AS_HELP_STRING([--disable-lto], [Link Time Optimizations @<:@default enabled@:>@])],
+    ,
+    [enable_lto="detect"]
+)
 
 
 # -----------------------------------------------------------------------------
@@ -145,6 +151,7 @@ AC_CHECK_HEADERS_ONCE([sys/prctl.h])
 # -----------------------------------------------------------------------------
 # operating system detection
 
+AC_MSG_CHECKING([operating system])
 case "$host_os" in
 freebsd*)
     build_target=freebsd
@@ -161,33 +168,7 @@ esac
 AM_CONDITIONAL([FREEBSD], [test "${build_target}" = "freebsd"])
 AM_CONDITIONAL([MACOS], [test "${build_target}" = "macos"])
 AM_CONDITIONAL([LINUX], [test "${build_target}" = "linux"])
-
-
-# -----------------------------------------------------------------------------
-# compiler options
-
-AC_ARG_VAR([SSE_CANDIDATE], [C compiler flags for SSE])
-AS_CASE([$host_cpu],
-    [i?86], [SSE_CANDIDATE="yes"]
-)
-AC_SUBST([SSE_CANDIDATE])
-if test "${SSE_CANDIDATE}" = "yes" -a "${enable_x86_sse}" = "yes"; then
-    opt="-msse2 -mfpmath=sse"
-    AX_CHECK_COMPILE_FLAG($opt, [CFLAGS="$CFLAGS $opt"], [])
-fi
-
-if test "${GCC}" = "yes"; then
-    AC_DEFINE_UNQUOTED([likely(x)], [__builtin_expect(!!(x), 1)], [gcc branch optimization])
-    AC_DEFINE_UNQUOTED([unlikely(x)], [__builtin_expect(!!(x), 0)], [gcc branch optimization])
-else
-    AC_DEFINE_UNQUOTED([likely(x)], [(x)], [gcc branch optimization])
-    AC_DEFINE_UNQUOTED([unlikely(x)], [(x)], [gcc branch optimization])
-fi
-
-if test "${enable_pedantic}" = "yes"; then
-    enable_strict="yes"
-    CFLAGS="${CFLAGS} -pedantic -Wall -Wextra -Wno-long-long"
-fi
+AC_MSG_RESULT([${build_target}])
 
 
 # -----------------------------------------------------------------------------
@@ -199,27 +180,6 @@ CFLAGS="${CFLAGS} ${PTHREAD_CFLAGS}"
 CC="${PTHREAD_CC}"
 
 
-# -----------------------------------------------------------------------------
-# memory allocation library
-
-AC_MSG_CHECKING([for memory allocator])
-TS_CHECK_JEMALLOC
-if test "$has_jemalloc" = "1"; then
-    AC_DEFINE([ENABLE_JEMALLOC], [1], [compile and link with jemalloc])
-    AC_MSG_RESULT([jemalloc])
-else
-    TS_CHECK_TCMALLOC
-    if test "$has_tcmalloc" = "1"; then
-        AC_DEFINE([ENABLE_TCMALLOC], [1], [compile and link with tcmalloc])
-        AC_MSG_RESULT([tcmalloc])
-    else
-        AC_MSG_RESULT([system])
-        AC_C_MALLOPT
-        AC_C_MALLINFO
-    fi
-fi
-
-
 # -----------------------------------------------------------------------------
 # libm
 
@@ -283,6 +243,54 @@ OPTIONAL_UUID_CLFAGS="${UUID_CFLAGS}"
 OPTIONAL_UUID_LIBS="${UUID_LIBS}"
 
 
+# -----------------------------------------------------------------------------
+# compiler options
+
+AC_ARG_VAR([SSE_CANDIDATE], [C compiler flags for SSE])
+AS_CASE([$host_cpu],
+    [i?86], [SSE_CANDIDATE="yes"]
+)
+AC_SUBST([SSE_CANDIDATE])
+if test "${SSE_CANDIDATE}" = "yes" -a "${enable_x86_sse}" = "yes"; then
+    opt="-msse2 -mfpmath=sse"
+    AX_CHECK_COMPILE_FLAG(${opt}, [CFLAGS="${CFLAGS} ${opt}"], [])
+fi
+
+if test "${GCC}" = "yes"; then
+    AC_DEFINE_UNQUOTED([likely(x)], [__builtin_expect(!!(x), 1)], [gcc branch optimization])
+    AC_DEFINE_UNQUOTED([unlikely(x)], [__builtin_expect(!!(x), 0)], [gcc branch optimization])
+else
+    AC_DEFINE_UNQUOTED([likely(x)], [(x)], [gcc branch optimization])
+    AC_DEFINE_UNQUOTED([unlikely(x)], [(x)], [gcc branch optimization])
+fi
+
+if test "${enable_pedantic}" = "yes"; then
+    enable_strict="yes"
+    CFLAGS="${CFLAGS} -pedantic -Wall -Wextra -Wno-long-long"
+fi
+
+
+# -----------------------------------------------------------------------------
+# memory allocation library
+
+AC_MSG_CHECKING([for memory allocator])
+TS_CHECK_JEMALLOC
+if test "$has_jemalloc" = "1"; then
+    AC_DEFINE([ENABLE_JEMALLOC], [1], [compile and link with jemalloc])
+    AC_MSG_RESULT([jemalloc])
+else
+    TS_CHECK_TCMALLOC
+    if test "$has_tcmalloc" = "1"; then
+        AC_DEFINE([ENABLE_TCMALLOC], [1], [compile and link with tcmalloc])
+        AC_MSG_RESULT([tcmalloc])
+    else
+        AC_MSG_RESULT([system])
+        AC_C_MALLOPT
+        AC_C_MALLINFO
+    fi
+fi
+
+
 # -----------------------------------------------------------------------------
 # libcap
 
@@ -387,6 +395,34 @@ AC_MSG_RESULT([${enable_plugin_nfacct}])
 AM_CONDITIONAL([ENABLE_PLUGIN_NFACCT], [test "${enable_plugin_nfacct}" = "yes"])
 
 
+# -----------------------------------------------------------------------------
+# Link-Time-Optimization
+
+if test "${enable_lto}" != "no"; then
+    opt="-flto"
+    AX_CHECK_COMPILE_FLAG(${opt}, [have_lto=yes], [have_lto=no])
+fi
+if test "${have_lto}" = "yes"; then
+    oCFLAGS="${CFLAGS}"
+    CFLAGS="${CFLAGS} -flto ${OPTIONAL_MATH_CLFAGS} ${OPTIONAL_NFACCT_CLFAGS} ${OPTIONAL_ZLIB_CLFAGS} ${OPTIONAL_UUID_CLFAGS} ${OPTIONAL_LIBCAP_CFLAGS} ${OPTIONAL_IPMIMONITORING_CFLAGS}"
+    ac_cv_c_lto_cross_compile="${enable_lto}"
+    test "${ac_cv_c_lto_cross_compile}" != "yes" && ac_cv_c_lto_cross_compile="no"
+    AC_C_LTO
+    CFLAGS="${oCFLAGS}"
+    test "${ac_cv_c_lto}" != "yes" && have_lto="no"
+fi
+test "${enable_lto}" = "yes" -a "${have_lto}" != "yes" && \
+    AC_MSG_ERROR([LTO is required but is not available.])
+AC_MSG_CHECKING([if LTO should be enabled])
+if test "${enable_lto}" != "no" -a "${have_lto}" = "yes"; then
+    enable_lto="yes"
+    CFLAGS="${CFLAGS} -flto"
+else
+    enable_lto="no"
+fi
+AC_MSG_RESULT([${enable_lto}])
+
+
 # -----------------------------------------------------------------------------
 
 AC_DEFINE_UNQUOTED([NETDATA_USER], ["${with_user}"], [use this user to drop privileged])
diff --git a/m4/ax_c_lto.m4 b/m4/ax_c_lto.m4
new file mode 100644 (file)
index 0000000..7e6bc01
--- /dev/null
@@ -0,0 +1,21 @@
+# AC_C_LTO
+# -------------
+# Define HAVE_LTO if -flto works.
+AN_IDENTIFIER([lto], [AC_C_LTO])
+AC_DEFUN([AC_C_LTO],
+[AC_CACHE_CHECK([if -flto builds executables], ac_cv_c_lto,
+[AC_RUN_IFELSE(
+   [AC_LANG_SOURCE(
+      [[#include <stdio.h>
+        int main(int argc, char **argv) {
+          return 0;
+        }
+      ]])],
+   [ac_cv_c_lto=yes],
+   [ac_cv_c_lto=no],
+   [ac_cv_c_lto=${ac_cv_c_lto_cross_compile}])])
+if test "${ac_cv_c_lto}" = "yes"; then
+  AC_DEFINE([HAVE_LTO], 1,
+           [Define to 1 if -flto works.])
+fi
+])# AC_C_LTO
index 9957e95b59003343f34947ef49b62f5a57cfbd85..c49ef32ceb2d14dbc2f4b486351e4db00b7c871c 100755 (executable)
@@ -104,6 +104,12 @@ Valid <installer options> are:
         Enable/disable the FreeIPMI plugin.
         Default: enable it when libipmimonitoring is available.
 
+   --enable-lto
+   --disable-lto
+
+        Enable/disable Link-Time-Optimization
+        Default: enabled
+
    --zlib-is-really-here
    --libs-are-really-here
 
@@ -199,6 +205,14 @@ do
         then
         NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --disable-plugin-freeipmi"
         shift 1
+    elif [ "$1" = "--enable-lto" ]
+        then
+        NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --enable-lto"
+        shift 1
+    elif [ "$1" = "--disable-lto" ]
+        then
+        NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --disable-lto"
+        shift 1
     elif [ "$1" = "--help" -o "$1" = "-h" ]
         then
         usage
@@ -577,6 +591,7 @@ NETDATA_ADDED_TO_NGINX=0
 NETDATA_ADDED_TO_VARNISH=0
 NETDATA_ADDED_TO_HAPROXY=0
 NETDATA_ADDED_TO_ADM=0
+NETDATA_ADDED_TO_NSD=0
 if [ ${UID} -eq 0 ]
     then
     portable_add_group netdata
@@ -586,6 +601,7 @@ if [ ${UID} -eq 0 ]
     portable_add_user_to_group varnish  netdata && NETDATA_ADDED_TO_VARNISH=1
     portable_add_user_to_group haproxy  netdata && NETDATA_ADDED_TO_HAPROXY=1
     portable_add_user_to_group adm      netdata && NETDATA_ADDED_TO_ADM=1
+    portable_add_user_to_group nsd      netdata && NETDATA_ADDED_TO_NSD=1
     run_ok
 else
     run_failed "The installer does not run as root."
@@ -1238,6 +1254,15 @@ if [ $? -eq 0 -a "${NETDATA_ADDED_TO_ADM}" = "1" ]
     echo "   gpasswd -d netdata adm"
 fi
 
+getent group nsd > /dev/null
+if [ $? -eq 0 -a "${NETDATA_ADDED_TO_NSD}" = "1" ]
+    then
+    echo
+    echo "You may also want to remove the netdata user from the nsd group"
+    echo "by running:"
+    echo "   gpasswd -d netdata nsd"
+fi
+
 
 UNINSTALL
 chmod 750 netdata-uninstaller.sh
index c0974bda6df38c68518f24320dc924446e6fd397..57b37ffa082aed225e6bdfd7498f9d8e6573e562 100644 (file)
@@ -272,7 +272,7 @@ netdata.processors.snmp = {
                         if(__DEBUG === true)
                             netdata.debug(service.module.name + ': ' + service.name + ': found ' + service.module.name + ' value of OIDs ' + varbinds[i].oid + " = " + varbinds[i].value);
 
-                        if(varbinds[i].type === net_snmp.ObjectType.OctetString)
+                        if(varbinds[i].type === net_snmp.ObjectType.OctetString && service.snmp_oids_index[varbinds[i].oid].type !== 'title')
                             value = parseFloat(varbinds[i].value) * 1000;
                         else
                             value = varbinds[i].value;
index 45d90563888d5dcd176154228c9c72275a317df6..d0188fe3b11b5361810b62a791ece461f43d6d49 100755 (executable)
@@ -142,20 +142,27 @@ info="${18}"       # a short description of the alarm
 value_string="${19}"        # friendly value (with units)
 old_value_string="${20}"    # friendly old value (with units)
 
+# -----------------------------------------------------------------------------
+# find a suitable hostname to use, if netdata did not supply a hostname
+
+[ -z "${host}" ] && host="${NETDATA_HOSTNAME}"
+[ -z "${host}" ] && host="${NETDATA_REGISTRY_HOSTNAME}"
+[ -z "${host}" ] && host="$(hostname 2>/dev/null)"
+
 # -----------------------------------------------------------------------------
 # screen statuses we don't need to send a notification
 
 # don't do anything if this is not WARNING, CRITICAL or CLEAR
 if [ "${status}" != "WARNING" -a "${status}" != "CRITICAL" -a "${status}" != "CLEAR" ]
 then
-    info "not sending notification for ${status} on '${chart}.${name}'"
+    info "not sending notification for ${status} of '${host}.${chart}.${name}'"
     exit 1
 fi
 
 # don't do anything if this is CLEAR, but it was not WARNING or CRITICAL
 if [ "${old_status}" != "WARNING" -a "${old_status}" != "CRITICAL" -a "${status}" = "CLEAR" ]
 then
-    info "not sending notification for ${status} on '${chart}.${name}' (last status was ${old_status})"
+    info "not sending notification for ${status} of '${host}.${chart}.${name}' (last status was ${old_status})"
     exit 1
 fi
 
@@ -532,16 +539,9 @@ if [   "${SEND_EMAIL}"          != "YES" \
     -a "${SEND_PD}"             != "YES" \
     ]
     then
-    fatal "All notification methods are disabled. Not sending notification to '${roles}' for '${name}' = '${value}' of chart '${chart}' for status '${status}'."
+    fatal "All notification methods are disabled. Not sending notification for host '${host}', chart '${chart}' to '${roles}' for '${name}' = '${value}' for status '${status}'."
 fi
 
-# -----------------------------------------------------------------------------
-# find a suitable hostname to use, if netdata did not supply a hostname
-
-[ -z "${host}" ] && host="${NETDATA_HOSTNAME}"
-[ -z "${host}" ] && host="${NETDATA_REGISTRY_HOSTNAME}"
-[ -z "${host}" ] && host="$(hostname 2>/dev/null)"
-
 # -----------------------------------------------------------------------------
 # get the date the alarm happened
 
@@ -803,10 +803,10 @@ send_pd() {
             retval=$?
             if [ ${retval} -eq 0 ]
                 then
-                    info "sent pagerduty.com notification using service key ${PD_SERVICE_KEY::-26}....: ${d}"
+                    info "sent pagerduty.com notification for host ${host} ${chart}.${name} using service key ${PD_SERVICE_KEY::-26}....: ${d}"
                     sent=$((sent + 1))
                 else
-                    error "failed to send pagerduty.com notification using service key ${PD_SERVICE_KEY::-26}.... (error code ${retval}): ${d}"
+                    error "failed to send pagerduty.com notification for ${host} ${chart}.${name} using service key ${PD_SERVICE_KEY::-26}.... (error code ${retval}): ${d}"
             fi
         done
 
index 588b924ae30a3c1c2343dd2b77bd1a98a162c170..bfe28ff2803bf5526cd09d3d8999fef55917e91b 100644 (file)
@@ -33,6 +33,7 @@ dist_python_DATA = \
     mongodb.chart.py \
     mysql.chart.py \
     nginx.chart.py \
+    nsd.chart.py \
     ovpn_status_log.chart.py \
     phpfpm.chart.py \
     postfix.chart.py \
index d21d2d83ecea730d71aca1e0798b68cf670b1d58..cee2078f2f0c0607dab5aa30e8efe3c0b75307da 100644 (file)
@@ -1017,6 +1017,61 @@ When no configuration file is found, module tries to parse `/var/log/nginx/acces
 
 ---
 
+# nsd
+
+Module uses the `nsd-control stats_noreset` command to provide `nsd` statistics.
+
+**Requirements:**
+ * Version of `nsd` must be 4.0+
+ * Netdata must have permissions to run `nsd-control stats_noreset`
+
+It produces:
+
+1. **Queries**
+ * queries
+
+2. **Zones**
+ * master
+ * slave
+
+3. **Protocol**
+ * udp
+ * udp6
+ * tcp
+ * tcp6
+
+4. **Query Type**
+ * A
+ * NS
+ * CNAME
+ * SOA
+ * PTR
+ * HINFO
+ * MX
+ * NAPTR
+ * TXT
+ * AAAA
+ * SRV
+ * ANY
+
+5. **Transfer**
+ * NOTIFY
+ * AXFR
+
+6. **Return Code**
+ * NOERROR
+ * FORMERR
+ * SERVFAIL
+ * NXDOMAIN
+ * NOTIMP
+ * REFUSED
+ * YXDOMAIN
+
+
+Configuration is not needed.
+
+---
+
 # ovpn_status_log
 
 Module monitor openvpn-status log file. 
diff --git a/python.d/nsd.chart.py b/python.d/nsd.chart.py
new file mode 100644 (file)
index 0000000..68bb4f2
--- /dev/null
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+# Description: NSD `nsd-control stats_noreset` netdata python.d module
+# Author: <383c57 at gmail.com>
+
+
+from base import ExecutableService
+import re
+
+# default module values (can be overridden per job in `config`)
+priority = 60000
+retries = 5
+update_every = 30
+
+# charts order (can be overridden if you want less charts, or different order)
+ORDER = ['queries', 'zones', 'protocol', 'type', 'transfer', 'rcode']
+
+CHARTS = {
+    'queries': {
+        'options': [
+            None, "queries", 'queries/s', 'queries', 'nsd.queries', 'line'],
+        'lines': [
+            ['num_queries', 'queries', 'incremental'],]},
+    'zones': {
+        'options': [
+            None, "zones", 'zones', 'zones', 'nsd.zones', 'stacked'],
+        'lines': [
+            ['zone_master', 'master', 'absolute'],
+            ['zone_slave', 'slave', 'absolute'],]},
+    'protocol': {
+        'options': [
+            None, "protocol", 'queries/s', 'protocol', 'nsd.protocols', 'stacked'],
+        'lines': [
+            ['num_udp', 'udp', 'incremental'],
+            ['num_udp6', 'udp6', 'incremental'],
+            ['num_tcp', 'tcp', 'incremental'],
+            ['num_tcp6', 'tcp6', 'incremental'],]},
+    'type': {
+        'options': [
+            None, "query type", 'queries/s', 'query type', 'nsd.type', 'stacked'],
+        'lines': [
+            ['num_type_A', 'A', 'incremental'],
+            ['num_type_NS', 'NS', 'incremental'],
+            ['num_type_CNAME', 'CNAME', 'incremental'],
+            ['num_type_SOA', 'SOA', 'incremental'],
+            ['num_type_PTR', 'PTR', 'incremental'],
+            ['num_type_HINFO', 'HINFO', 'incremental'],
+            ['num_type_MX', 'MX', 'incremental'],
+            ['num_type_NAPTR', 'NAPTR', 'incremental'],
+            ['num_type_TXT', 'TXT', 'incremental'],
+            ['num_type_AAAA', 'AAAA', 'incremental'],
+            ['num_type_SRV', 'SRV', 'incremental'],
+            ['num_type_TYPE255', 'ANY', 'incremental'],]},
+    'transfer': {
+        'options': [
+            None, "transfer", 'queries/s', 'transfer', 'nsd.transfer', 'stacked'],
+        'lines': [
+            ['num_opcode_NOTIFY', 'NOTIFY', 'incremental'],
+            ['num_type_TYPE252', 'AXFR', 'incremental'],]},
+    'rcode': {
+        'options': [
+            None, "return code", 'queries/s', 'return code', 'nsd.rcode', 'stacked'],
+        'lines': [
+            ['num_rcode_NOERROR', 'NOERROR', 'incremental'],
+            ['num_rcode_FORMERR', 'FORMERR', 'incremental'],
+            ['num_rcode_SERVFAIL', 'SERVFAIL', 'incremental'],
+            ['num_rcode_NXDOMAIN', 'NXDOMAIN', 'incremental'],
+            ['num_rcode_NOTIMP', 'NOTIMP', 'incremental'],
+            ['num_rcode_REFUSED', 'REFUSED', 'incremental'],
+            ['num_rcode_YXDOMAIN', 'YXDOMAIN', 'incremental'],]}
+}
+
+
+class Service(ExecutableService):
+    def __init__(self, configuration=None, name=None):
+        ExecutableService.__init__(
+            self, configuration=configuration, name=name)
+        self.command = "nsd-control stats_noreset"
+        self.order = ORDER
+        self.definitions = CHARTS
+        self.regex = re.compile(r'([A-Za-z0-9.]+)=(\d+)')
+
+    def _get_data(self):
+        lines = self._get_raw_data()
+        if not lines:
+            return None
+
+        r = self.regex
+        stats = dict((k.replace('.', '_'), int(v))
+                     for k, v in r.findall(''.join(lines)))
+        stats.setdefault('num_opcode_NOTIFY', 0)
+        stats.setdefault('num_type_TYPE252', 0)
+        stats.setdefault('num_type_TYPE255', 0)
+        return stats
index 154e4e4ba69ca8ea766c861eabc9a1491ce3a025..c20f85e1ecd2818a6b87386e1f2e8d1c368f7591 100644 (file)
@@ -51,10 +51,6 @@ class Service(UrlService):
         self.definitions = CHARTS
 
     def check(self):
-        if not self.url.endswith('manager/status?XML=true'):
-            self.error('Bad url(%s). Must be http://<ip.address>:<port>/manager/status?XML=true' % self.url)
-            return False
-
         netloc = urlparse(self.url).netloc.rpartition(':')
         if netloc[1] == ':': port = netloc[2]
         else: port = 80
index 5f907893ea86e8f3447e2022ee00f0f1ac8ebb1c..1c1dd33856e155706af1885c07b8508eadafc8ad 100644 (file)
@@ -38,74 +38,120 @@ plugins_PROGRAMS += freeipmi.plugin
 endif
 
 netdata_SOURCES = \
-       appconfig.c appconfig.h \
-       adaptive_resortable_list.c adaptive_resortable_list.h \
-       avl.c avl.h \
-       backends.c backends.h \
-       clocks.c clocks.h \
-       common.c common.h \
-       daemon.c daemon.h \
-       dictionary.c dictionary.h \
-       eval.c eval.h \
-       global_statistics.c global_statistics.h \
-       health.c health.h health_log.c health_config.c health_json.c \
+       adaptive_resortable_list.c \
+       adaptive_resortable_list.h \
+       appconfig.c \
+       appconfig.h \
+       avl.c \
+       avl.h \
+       backends.c \
+       backends.h \
+       clocks.c \
+       clocks.h \
+       common.c \
+       common.h \
+       daemon.c \
+       daemon.h \
+       dictionary.c \
+       dictionary.h \
+       eval.c \
+       eval.h \
+       global_statistics.c \
+       global_statistics.h \
+       health.c \
+       health.h \
+       health_config.c \
+       health_json.c \
+       health_log.c \
        inlined.h \
-       log.c log.h \
-       main.c main.h \
-       plugin_checks.c plugin_checks.h \
-       plugin_idlejitter.c plugin_idlejitter.h \
-       plugin_nfacct.c plugin_nfacct.h \
-       plugin_tc.c plugin_tc.h \
-       plugins_d.c plugins_d.h \
-       popen.c popen.h \
-       socket.c socket.h \
-       simple_pattern.c simple_pattern.h \
-       sys_fs_cgroup.c \
-       sys_devices_system_edac_mc.c \
-       sys_devices_system_node.c \
-       procfile.c procfile.h \
-       proc_self_mountinfo.c proc_self_mountinfo.h \
-       registry.c registry.h \
-       registry_internals.c registry_internals.h \
-       registry_url.c registry_url.h \
-       registry_person.c registry_person.h \
-       registry_machine.c registry_machine.h \
-       registry_init.c \
+       locks.h \
+       log.c \
+       log.h \
+       main.c \
+       main.h \
+       plugin_checks.c \
+       plugin_checks.h \
+       plugin_idlejitter.c \
+       plugin_idlejitter.h \
+       plugin_nfacct.c \
+       plugin_nfacct.h \
+       plugin_tc.c \
+       plugin_tc.h \
+       plugins_d.c \
+       plugins_d.h \
+       popen.c \
+       popen.h \
+       proc_self_mountinfo.c \
+       proc_self_mountinfo.h \
+       procfile.c \
+       procfile.h \
+       registry.c \
+       registry.h \
        registry_db.c \
+       registry_init.c \
+       registry_internals.c \
+       registry_internals.h \
        registry_log.c \
-       rrd.c rrd.h \
+       registry_machine.c \
+       registry_machine.h \
+       registry_person.c \
+       registry_person.h \
+       registry_url.c \
+       registry_url.h \
+       rrd.c \
+       rrd.h \
+       rrd2json.c \
+       rrd2json.h \
+       rrd2json_api_old.c \
+       rrd2json_api_old.h \
+       rrdcalc.c \
+       rrdcalctemplate.c \
        rrddim.c \
+       rrddimvar.c \
        rrdfamily.c \
        rrdhost.c \
+       rrdpush.c \
+       rrdpush.h \
        rrdset.c \
-       rrdcalc.c \
-       rrdcalctemplate.c \
-       rrdvar.c \
-       rrddimvar.c \
        rrdsetvar.c \
-       rrd2json.c rrd2json.h \
-       rrd2json_api_old.c rrd2json_api_old.h \
-       rrdpush.c rrdpush.h \
-       storage_number.c storage_number.h \
-       unit_test.c unit_test.h \
+       rrdvar.c \
+       simple_pattern.c \
+       simple_pattern.h \
+       socket.c \
+       socket.h \
+       storage_number.c \
+       storage_number.h \
+       sys_devices_system_edac_mc.c \
+       sys_devices_system_node.c \
+       sys_fs_cgroup.c \
+       unit_test.c \
+       unit_test.h \
        url.c url.h \
-       web_api_old.c web_api_old.h \
-       web_api_v1.c web_api_v1.h \
-       web_buffer.c web_buffer.h \
-       web_buffer_svg.c web_buffer_svg.h \
-       web_client.c web_client.h \
-       web_server.c web_server.h \
+       web_api_old.c \
+       web_api_old.h \
+       web_api_v1.c \
+       web_api_v1.h \
+       web_buffer.c \
+       web_buffer.h \
+       web_buffer_svg.c \
+       web_buffer_svg.h \
+       web_client.c \
+       web_client.h \
+       web_server.c \
+       web_server.h \
        $(NULL)
 
 if FREEBSD
 netdata_SOURCES += \
-       plugin_freebsd.c plugin_freebsd.h \
+       plugin_freebsd.c \
+       plugin_freebsd.h \
        freebsd_sysctl.c \
        $(NULL)
 else
 if MACOS
 netdata_SOURCES += \
-       plugin_macos.c plugin_macos.h \
+       plugin_macos.c \
+       plugin_macos.h \
        macos_sysctl.c \
        macos_mach_smi.c \
        macos_fw.c \
@@ -113,8 +159,10 @@ netdata_SOURCES += \
 else
 netdata_SOURCES += \
        ipc.c ipc.h \
-       plugin_proc.c plugin_proc.h \
-       plugin_proc_diskspace.c plugin_proc_diskspace.h \
+       plugin_proc.c \
+       plugin_proc.h \
+       plugin_proc_diskspace.c \
+       plugin_proc_diskspace.h \
        proc_diskstats.c \
        proc_interrupts.c \
        proc_softirqs.c \
index 50e4c31fbdcb017d81874c5af7efabc258365f69..71ff4b75e255a36977685aa049e6d28d43da7691 100644 (file)
@@ -36,7 +36,7 @@ struct section {
     struct config_option *values;
     avl_tree_lock values_index;
 
-    pthread_mutex_t mutex;  // this locks only the writers, to ensure atomic updates
+    netdata_mutex_t mutex;  // this locks only the writers, to ensure atomic updates
                             // readers are protected using the rwlock in avl_tree_lock
 };
 
@@ -44,7 +44,7 @@ static int appconfig_section_compare(void *a, void *b);
 
 struct config netdata_config = {
         .sections = NULL,
-        .mutex = PTHREAD_MUTEX_INITIALIZER,
+        .mutex = NETDATA_MUTEX_INITIALIZER,
         .index = {
             { NULL, appconfig_section_compare },
             AVL_LOCK_INITIALIZER
@@ -53,7 +53,7 @@ struct config netdata_config = {
 
 struct config stream_config = {
         .sections = NULL,
-        .mutex = PTHREAD_MUTEX_INITIALIZER,
+        .mutex = NETDATA_MUTEX_INITIALIZER,
         .index = {
                 { NULL, appconfig_section_compare },
                 AVL_LOCK_INITIALIZER
@@ -64,19 +64,19 @@ struct config stream_config = {
 // locking
 
 static inline void appconfig_wrlock(struct config *root) {
-    pthread_mutex_lock(&root->mutex);
+    netdata_mutex_lock(&root->mutex);
 }
 
 static inline void appconfig_unlock(struct config *root) {
-    pthread_mutex_unlock(&root->mutex);
+    netdata_mutex_unlock(&root->mutex);
 }
 
 static inline void config_section_wrlock(struct section *co) {
-    pthread_mutex_lock(&co->mutex);
+    netdata_mutex_lock(&co->mutex);
 }
 
 static inline void config_section_unlock(struct section *co) {
-    pthread_mutex_unlock(&co->mutex);
+    netdata_mutex_unlock(&co->mutex);
 }
 
 
index 15bba80786e8f5c353183f093d6f91ff378ad7a6..45cc8cfd5215d18303abbb407091a58998db3379 100644 (file)
@@ -18,7 +18,7 @@
 
 struct config {
     struct section *sections;
-    pthread_mutex_t mutex;
+    netdata_mutex_t mutex;
     avl_tree_lock index;
 };
 
index 338e6afbd3ef52184c445795a9808b32ef9a8cb8..bea06c3c84030d07cf2c2260bb6ca2c4df678d10 100644 (file)
@@ -3199,7 +3199,7 @@ static void parse_args(int argc, char **argv)
             }
         }
 
-        if(strcmp("version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0) {
+        if(strcmp("version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0 || strcmp("-V", argv[i]) == 0) {
             printf("apps.plugin %s\n", VERSION);
             exit(0);
         }
@@ -3269,7 +3269,7 @@ static void parse_args(int argc, char **argv)
                     "\n"
                     " This program is a data collector plugin for netdata.\n"
                     "\n"
-                    " Valid command line options:\n"
+                    " Available command line options:\n"
                     "\n"
                     " SECONDS           set the data collection frequency\n"
                     "\n"
@@ -3292,7 +3292,7 @@ static void parse_args(int argc, char **argv)
                     "                   apps_groups.conf\n"
                     "                   (default NAME=groups)\n"
                     "\n"
-                    " version           print program version and exit\n"
+                    " version or -v or -V print program version and exit\n"
                     "\n"
                     , VERSION
             );
index 1ec1b8ad221bc31bf4adc8636512a97db9ccbb6f..0ea119a7c8cd9bfd5a251cf3213a749cce8488f6 100644 (file)
--- a/src/avl.c
+++ b/src/avl.c
@@ -315,9 +315,9 @@ int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *da
 void avl_read_lock(avl_tree_lock *t) {
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-    pthread_mutex_lock(&t->mutex);
+    netdata_mutex_lock(&t->mutex);
 #else
-    pthread_rwlock_rdlock(&t->rwlock);
+    netdata_rwlock_rdlock(&t->rwlock);
 #endif
 #endif /* AVL_WITHOUT_PTHREADS */
 }
@@ -325,9 +325,9 @@ void avl_read_lock(avl_tree_lock *t) {
 void avl_write_lock(avl_tree_lock *t) {
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-    pthread_mutex_lock(&t->mutex);
+    netdata_mutex_lock(&t->mutex);
 #else
-    pthread_rwlock_wrlock(&t->rwlock);
+    netdata_rwlock_wrlock(&t->rwlock);
 #endif
 #endif /* AVL_WITHOUT_PTHREADS */
 }
@@ -335,9 +335,9 @@ void avl_write_lock(avl_tree_lock *t) {
 void avl_unlock(avl_tree_lock *t) {
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-    pthread_mutex_unlock(&t->mutex);
+    netdata_mutex_unlock(&t->mutex);
 #else
-    pthread_rwlock_unlock(&t->rwlock);
+    netdata_rwlock_unlock(&t->rwlock);
 #endif
 #endif /* AVL_WITHOUT_PTHREADS */
 }
@@ -352,9 +352,9 @@ void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)) {
     int lock;
 
 #ifdef AVL_LOCK_WITH_MUTEX
-    lock = pthread_mutex_init(&t->mutex, NULL);
+    lock = netdata_mutex_init(&t->mutex, NULL);
 #else
-    lock = pthread_rwlock_init(&t->rwlock, NULL);
+    lock = netdata_rwlock_init(&t->rwlock);
 #endif
 
     if(lock != 0)
index d30be0dd85cc7e5d5918b610da9f8446b08dd623..19648cd1db8ed1d719ee5e47390d8d54e2b4399f 100644 (file)
--- a/src/avl.h
+++ b/src/avl.h
@@ -13,9 +13,9 @@
 // #define AVL_LOCK_WITH_MUTEX 1
 
 #ifdef AVL_LOCK_WITH_MUTEX
-#define AVL_LOCK_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define AVL_LOCK_INITIALIZER NETDATA_MUTEX_INITIALIZER
 #else /* AVL_LOCK_WITH_MUTEX */
-#define AVL_LOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+#define AVL_LOCK_INITIALIZER NETDATA_RWLOCK_INITIALIZER
 #endif /* AVL_LOCK_WITH_MUTEX */
 
 #else /* AVL_WITHOUT_PTHREADS */
@@ -41,9 +41,9 @@ typedef struct avl_tree_lock {
 
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-    pthread_mutex_t mutex;
+    netdata_mutex_t mutex;
 #else /* AVL_LOCK_WITH_MUTEX */
-    pthread_rwlock_t rwlock;
+    netdata_rwlock_t rwlock;
 #endif /* AVL_LOCK_WITH_MUTEX */
 #endif /* AVL_WITHOUT_PTHREADS */
 } avl_tree_lock;
index 4a2c37f2923648f80a24953280f35af4bded9ddd..879ebf911790e1efd892558efab5c0351509b693 100644 (file)
@@ -27,8 +27,13 @@ static inline usec_t now_usec(clockid_t clk_id) {
 
 static inline int now_timeval(clockid_t clk_id, struct timeval *tv) {
     struct timespec ts;
-    if(unlikely(clock_gettime(clk_id, &ts) == -1))
+
+    if(unlikely(clock_gettime(clk_id, &ts) == -1)) {
+        tv->tv_sec = 0;
+        tv->tv_usec = 0;
         return -1;
+    }
+
     tv->tv_sec = ts.tv_sec;
     tv->tv_usec = (suseconds_t)((ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC);
     return 0;
index f53cc5571f2206e705ce6528ab5bfc0c3389256f..f2c764b53495389e6e17752c3e82261281b0a7df 100644 (file)
 // ----------------------------------------------------------------------------
 // netdata include files
 
-#include "simple_pattern.h"
-#include "avl.h"
 #include "clocks.h"
 #include "log.h"
+#include "locks.h"
+#include "simple_pattern.h"
+#include "avl.h"
 #include "global_statistics.h"
 #include "storage_number.h"
 #include "web_buffer.h"
index fb9efeedb564258b24c16e5b7f0774fdc278fc23..512b4bbe6c182bf92d3161c488d3e1b89c5b9d28 100644 (file)
@@ -31,21 +31,21 @@ static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
 static inline void dictionary_read_lock(DICTIONARY *dict) {
     if(likely(dict->rwlock)) {
         // debug(D_DICTIONARY, "Dictionary READ lock");
-        pthread_rwlock_rdlock(dict->rwlock);
+        netdata_rwlock_rdlock(dict->rwlock);
     }
 }
 
 static inline void dictionary_write_lock(DICTIONARY *dict) {
     if(likely(dict->rwlock)) {
         // debug(D_DICTIONARY, "Dictionary WRITE lock");
-        pthread_rwlock_wrlock(dict->rwlock);
+        netdata_rwlock_wrlock(dict->rwlock);
     }
 }
 
 static inline void dictionary_unlock(DICTIONARY *dict) {
     if(likely(dict->rwlock)) {
         // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
-        pthread_rwlock_unlock(dict->rwlock);
+        netdata_rwlock_unlock(dict->rwlock);
     }
 }
 
@@ -135,8 +135,8 @@ DICTIONARY *dictionary_create(uint8_t flags) {
         dict->stats = callocz(1, sizeof(struct dictionary_stats));
 
     if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
-        dict->rwlock = callocz(1, sizeof(pthread_rwlock_t));
-        pthread_rwlock_init(dict->rwlock, NULL);
+        dict->rwlock = callocz(1, sizeof(netdata_rwlock_t));
+        netdata_rwlock_init(dict->rwlock);
     }
 
     avl_init(&dict->values_index, name_value_compare);
@@ -158,8 +158,10 @@ void dictionary_destroy(DICTIONARY *dict) {
     if(dict->stats)
         freez(dict->stats);
 
-    if(dict->rwlock)
+    if(dict->rwlock) {
+        netdata_rwlock_destroy(dict->rwlock);
         freez(dict->rwlock);
+    }
 
     freez(dict);
 }
index 6bebbfa857083d08722493bdc0150822bf336a22..f028dbb30e39f81b182e993237d243bac0f4557c 100644 (file)
@@ -24,7 +24,7 @@ typedef struct dictionary {
     uint8_t flags;
 
     struct dictionary_stats *stats;
-    pthread_rwlock_t *rwlock;
+    netdata_rwlock_t *rwlock;
 } DICTIONARY;
 
 #define DICTIONARY_FLAG_DEFAULT                 0x00000000
index 78a3a6f5192330218399f4875056c0c686265dcd..4459de7cac48845dce507b700380af8835299c2b 100644 (file)
@@ -1434,7 +1434,11 @@ int main (int argc, char **argv) {
             }
         }
 
-        if(strcmp("debug", argv[i]) == 0) {
+        if(strcmp("version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0 || strcmp("-V", argv[i]) == 0) {
+            printf("freeipmi.plugin %s\n", VERSION);
+            exit(0);
+        }
+        else if(strcmp("debug", argv[i]) == 0) {
             debug = 1;
             continue;
         }
@@ -1449,21 +1453,55 @@ int main (int argc, char **argv) {
         else if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
             fprintf(stderr,
                     "\n"
-                    "netdata freeipmi.plugin " VERSION "\n"
-                    "Usage:\n"
+                    " netdata freeipmi.plugin %s\n"
+                    " Copyright (C) 2016-2017 Costa Tsaousis <costa@tsaousis.gr>\n"
+                    " Released under GNU General Public License v3 or later.\n"
+                    " All rights reserved.\n"
+                    "\n"
+                    " This program is a data collector plugin for netdata.\n"
+                    "\n"
+                    " Available command line options:\n"
+                    "\n"
+                    "  SECONDS                 data collection frequency\n"
+                    "                          minimum: %d\n"
+                    "\n"
+                    "  debug                   enable verbose output\n"
+                    "                          default: disabled\n"
+                    "\n"
+                    "  sel\n"
+                    "  no-sel                  enable/disable SEL collection\n"
+                    "                          default: %s\n"
+                    "\n"
+                    "  hostname HOST\n"
+                    "  username USER\n"
+                    "  password PASS           connect to remote IPMI host\n"
+                    "                          default: local IPMI processor\n"
+                    "\n"
+                    "  sdr-cache-dir PATH      directory for SDR cache files\n"
+                    "                          default: %s\n"
+                    "\n"
+                    "  sensor-config-file FILE filename to read sensor configuration\n"
+                    "                          default: %s\n"
+                    "\n"
+                    "  -v\n"
+                    "  -V\n"
+                    "  version                 print version and exit\n"
+                    "\n"
+                    " Linux kernel module for IPMI is CPU hungry.\n"
+                    " On Linux run this to lower kipmiN CPU utilization:\n"
+                    " # echo 10 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us\n"
+                    "\n"
+                    " or create: /etc/modprobe.d/ipmi.conf with these contents:\n"
+                    " options ipmi_si kipmid_max_busy_us=10\n"
                     "\n"
-                    "  freeipmi.plugin [OPTIONS]\n"
+                    " For more information:\n"
+                    " https://github.com/firehol/netdata/wiki/monitoring-IPMI\n"
                     "\n"
-                    "Available options:\n"
-                    "  NUMBER, sets the data collection frequency\n"
-                    "  debug, enables verbose output\n"
-                    "  sel, enable SEL collection (it is on by default)\n"
-                    "  no-sel, disable SEL collection\n"
-                    "  hostname X, sets the remote host to connect to\n"
-                    "  username X, sets the username to authenticate at the remote host\n"
-                    "  password X, sets the password to authenticate at the remote host\n"
-                    "  sdr-cache-dir X, sets the directory to save SDR cache files\n"
-                    "  sensor-config-file X, set the filename to read sensor configuration\n"
+                    , VERSION
+                    , netdata_update_every
+                    , netdata_do_sel?"enabled":"disabled"
+                    , sdr_cache_directory?sdr_cache_directory:"system default"
+                    , sensor_config_file?sensor_config_file:"system default"
             );
             exit(1);
         }
index c3d63043e13967a6efbb48fcfb4734d271c3f078..2ccdf6801480d2064390513bf0616be47c71a7f7 100644 (file)
@@ -10,14 +10,14 @@ volatile struct global_statistics global_statistics = {
         .compressed_content_size = 0
 };
 
-pthread_mutex_t global_statistics_mutex = PTHREAD_MUTEX_INITIALIZER;
+netdata_mutex_t global_statistics_mutex = NETDATA_MUTEX_INITIALIZER;
 
 inline void global_statistics_lock(void) {
-    pthread_mutex_lock(&global_statistics_mutex);
+    netdata_mutex_lock(&global_statistics_mutex);
 }
 
 inline void global_statistics_unlock(void) {
-    pthread_mutex_unlock(&global_statistics_mutex);
+    netdata_mutex_unlock(&global_statistics_mutex);
 }
 
 void finished_web_request_statistics(uint64_t dt,
index 57210c77b321344e9a930f1c5489f06543696666..46b27db6fbfdacc871ceb13ab63cbc9f4b75e4e6 100644 (file)
@@ -208,7 +208,7 @@ static inline void health_alarm_log_process(RRDHOST *host) {
     uint32_t first_waiting = (host->health_log.alarms)?host->health_log.alarms->unique_id:0;
     time_t now = now_realtime_sec();
 
-    pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
 
     ALARM_ENTRY *ae;
     for(ae = host->health_log.alarms; ae && ae->unique_id >= stop_at_id ; ae = ae->next) {
@@ -228,13 +228,13 @@ static inline void health_alarm_log_process(RRDHOST *host) {
     // remember this for the next iteration
     stop_at_id = first_waiting;
 
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 
     if(host->health_log.count <= host->health_log.max)
         return;
 
     // cleanup excess entries in the log
-    pthread_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
 
     ALARM_ENTRY *last = NULL;
     unsigned int count = host->health_log.max * 2 / 3;
@@ -256,7 +256,7 @@ static inline void health_alarm_log_process(RRDHOST *host) {
         host->health_log.count--;
     }
 
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 }
 
 static inline int rrdcalc_isrunnable(RRDCALC *rc, time_t now, time_t *next_run) {
index f8e2903234144d9b2eb823d2e0c3dd15ada323ab..7028a914b2581e0bb798a5fd1d77732d02021d3a 100644 (file)
@@ -334,7 +334,7 @@ typedef struct alarm_log {
     unsigned int count;
     unsigned int max;
     ALARM_ENTRY *alarms;
-    pthread_rwlock_t alarm_log_rwlock;
+    netdata_rwlock_t alarm_log_rwlock;
 } ALARM_LOG;
 
 #include "rrd.h"
index 4d24d5d11f075c77f0cd12bbbea515b7ca9164b1..a9697aaa75760551e7299597550442b2902819e6 100644 (file)
@@ -85,7 +85,7 @@ static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, R
 }
 
 void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after) {
-    pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
 
     buffer_strcat(wb, "[");
 
@@ -101,7 +101,7 @@ void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after) {
 
     buffer_strcat(wb, "\n]\n");
 
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 }
 
 static inline void health_rrdcalc2json_nolock(RRDHOST *host, BUFFER *wb, RRDCALC *rc) {
index 990894efd2eab0a843c9c8a4b67c27ca2c536aee..95abcfe5f48a00b1d049d5de2f8d8c1118a42355 100644 (file)
@@ -129,7 +129,7 @@ inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filena
     size_t line = 0, len = 0;
     ssize_t loaded = 0, updated = 0, errored = 0, duplicate = 0;
 
-    pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
 
     while((s = fgets_trim_len(buf, 65536, fp, &len))) {
         host->health_log_entries_written++;
@@ -297,7 +297,7 @@ inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filena
         }
     }
 
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 
     freez(buf);
 
@@ -404,14 +404,14 @@ inline void health_alarm_log(
         ae->non_clear_duration += ae->duration;
 
     // link it
-    pthread_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
     ae->next = host->health_log.alarms;
     host->health_log.alarms = ae;
     host->health_log.count++;
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 
     // match previous alarms
-    pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
     ALARM_ENTRY *t;
     for(t = host->health_log.alarms ; t ; t = t->next) {
         if(t != ae && t->alarm_id == ae->alarm_id) {
@@ -431,7 +431,7 @@ inline void health_alarm_log(
             break;
         }
     }
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 
     health_alarm_log_save(host, ae);
 }
@@ -453,7 +453,7 @@ inline void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae) {
 inline void health_alarm_log_free(RRDHOST *host) {
     rrdhost_check_wrlock(host);
 
-    pthread_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
 
     ALARM_ENTRY *ae;
     while((ae = host->health_log.alarms)) {
@@ -461,5 +461,5 @@ inline void health_alarm_log_free(RRDHOST *host) {
         health_alarm_log_free_one_nochecks_nounlink(ae);
     }
 
-    pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
 }
diff --git a/src/locks.h b/src/locks.h
new file mode 100644 (file)
index 0000000..76533f6
--- /dev/null
@@ -0,0 +1,294 @@
+#ifndef NETDATA_LOCKS_H
+#define NETDATA_LOCKS_H
+
+// ----------------------------------------------------------------------------
+// mutex
+
+typedef pthread_mutex_t netdata_mutex_t;
+
+#define NETDATA_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+static inline int __netdata_mutex_init(netdata_mutex_t *mutex) {
+    int ret = pthread_mutex_init(mutex, NULL);
+    if(unlikely(ret != 0))
+        error("MUTEX_LOCK: failed to initialize (code %d).", ret);
+    return ret;
+}
+
+static inline int __netdata_mutex_lock(netdata_mutex_t *mutex) {
+    int ret = pthread_mutex_lock(mutex);
+    if(unlikely(ret != 0))
+        error("MUTEX_LOCK: failed to get lock (code %d)", ret);
+    return ret;
+}
+
+static inline int __netdata_mutex_trylock(netdata_mutex_t *mutex) {
+    int ret = pthread_mutex_trylock(mutex);
+    return ret;
+}
+
+static inline int __netdata_mutex_unlock(netdata_mutex_t *mutex) {
+    int ret = pthread_mutex_unlock(mutex);
+    if(unlikely(ret != 0))
+        error("MUTEX_LOCK: failed to unlock (code %d).", ret);
+    return ret;
+}
+
+#ifdef NETDATA_INTERNAL_CHECKS
+
+static inline int netdata_mutex_init_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_init(0x%p) from %lu@%s, %s()", mutex, line, file, function);
+    }
+
+    int ret = __netdata_mutex_init(mutex);
+
+    debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_init(0x%p) = %d in %llu usec, from %lu@%s, %s()", mutex, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_mutex_lock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_lock(0x%p) from %lu@%s, %s()", mutex, line, file, function);
+    }
+
+    int ret = __netdata_mutex_lock(mutex);
+
+    debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_lock(0x%p) = %d in %llu usec, from %lu@%s, %s()", mutex, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_mutex_trylock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_trylock(0x%p) from %lu@%s, %s()", mutex, line, file, function);
+    }
+
+    int ret = __netdata_mutex_trylock(mutex);
+
+    debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_trylock(0x%p) = %d in %llu usec, from %lu@%s, %s()", mutex, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_mutex_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_unlock(0x%p) from %lu@%s, %s()", mutex, line, file, function);
+    }
+
+    int ret = __netdata_mutex_unlock(mutex);
+
+    debug(D_LOCKS, "MUTEX_LOCK: netdata_mutex_unlock(0x%p) = %d in %llu usec, from %lu@%s, %s()", mutex, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+#define netdata_mutex_init(mutex)    netdata_mutex_init_debug(__FILE__, __FUNCTION__, __LINE__, mutex)
+#define netdata_mutex_lock(mutex)    netdata_mutex_lock_debug(__FILE__, __FUNCTION__, __LINE__, mutex)
+#define netdata_mutex_trylock(mutex) netdata_mutex_trylock_debug(__FILE__, __FUNCTION__, __LINE__, mutex)
+#define netdata_mutex_unlock(mutex)  netdata_mutex_unlock_debug(__FILE__, __FUNCTION__, __LINE__, mutex)
+
+#else // !NETDATA_INTERNAL_CHECKS
+
+#define netdata_mutex_init(mutex)    __netdata_mutex_init(mutex)
+#define netdata_mutex_lock(mutex)    __netdata_mutex_lock(mutex)
+#define netdata_mutex_trylock(mutex) __netdata_mutex_trylock(mutex)
+#define netdata_mutex_unlock(mutex)  __netdata_mutex_unlock(mutex)
+
+#endif // NETDATA_INTERNAL_CHECKS
+
+
+// ----------------------------------------------------------------------------
+// r/w lock
+
+typedef pthread_rwlock_t netdata_rwlock_t;
+
+#define NETDATA_RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+
+static inline int __netdata_rwlock_destroy(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_destroy(rwlock);
+    if(unlikely(ret != 0))
+        error("RW_LOCK: failed to destroy lock (code %d)", ret);
+    return ret;
+}
+
+static inline int __netdata_rwlock_init(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_init(rwlock, NULL);
+    if(unlikely(ret != 0))
+        error("RW_LOCK: failed to initialize lock (code %d)", ret);
+    return ret;
+}
+
+static inline int __netdata_rwlock_rdlock(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_rdlock(rwlock);
+    if(unlikely(ret != 0))
+        error("RW_LOCK: failed to obtain read lock (code %d)", ret);
+    return ret;
+}
+
+static inline int __netdata_rwlock_wrlock(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_wrlock(rwlock);
+    if(unlikely(ret != 0))
+        error("RW_LOCK: failed to obtain write lock (code %d)", ret);
+    return ret;
+}
+
+static inline int __netdata_rwlock_unlock(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_unlock(rwlock);
+    if(unlikely(ret != 0))
+        error("RW_LOCK: failed to release lock (code %d)", ret);
+    return ret;
+}
+
+static inline int __netdata_rwlock_tryrdlock(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_tryrdlock(rwlock);
+    return ret;
+}
+
+static inline int __netdata_rwlock_trywrlock(netdata_rwlock_t *rwlock) {
+    int ret = pthread_rwlock_trywrlock(rwlock);
+    return ret;
+}
+
+
+#ifdef NETDATA_INTERNAL_CHECKS
+
+static inline int netdata_rwlock_destroy_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_destroy(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_destroy(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_destroy(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_rwlock_init_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_init(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_init(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_init(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_rwlock_rdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_rdlock(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_rdlock(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_rdlock(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_rwlock_wrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_wrlock(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_wrlock(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_wrlock(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_rwlock_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_unlock(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_unlock(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_unlock(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_rwlock_tryrdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_tryrdlock(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_tryrdlock(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_tryrdlock(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+static inline int netdata_rwlock_trywrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock) {
+    usec_t start = 0;
+
+    if(unlikely(debug_flags & D_LOCKS)) {
+        start = now_boottime_usec();
+        debug(D_LOCKS, "RW_LOCK: netdata_rwlock_trywrlock(0x%p) from %lu@%s, %s()", rwlock, line, file, function);
+    }
+
+    int ret = __netdata_rwlock_trywrlock(rwlock);
+
+    debug(D_LOCKS, "RW_LOCK: netdata_rwlock_trywrlock(0x%p) = %d in %llu usec, from %lu@%s, %s()", rwlock, ret, now_boottime_usec() - start, line, file, function);
+
+    return ret;
+}
+
+#define netdata_rwlock_destroy(rwlock)   netdata_rwlock_destroy_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+#define netdata_rwlock_init(rwlock)      netdata_rwlock_init_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+#define netdata_rwlock_rdlock(rwlock)    netdata_rwlock_rdlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+#define netdata_rwlock_wrlock(rwlock)    netdata_rwlock_wrlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+#define netdata_rwlock_unlock(rwlock)    netdata_rwlock_unlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+#define netdata_rwlock_tryrdlock(rwlock) netdata_rwlock_tryrdlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+#define netdata_rwlock_trywrlock(rwlock) netdata_rwlock_trywrlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock)
+
+#else // !NETDATA_INTERNAL_CHECKS
+
+#define netdata_rwlock_destroy(rwlock)    __netdata_rwlock_destroy(rwlock)
+#define netdata_rwlock_init(rwlock)       __netdata_rwlock_init(rwlock)
+#define netdata_rwlock_rdlock(rwlock)     __netdata_rwlock_rdlock(rwlock)
+#define netdata_rwlock_wrlock(rwlock)     __netdata_rwlock_wrlock(rwlock)
+#define netdata_rwlock_unlock(rwlock)     __netdata_rwlock_unlock(rwlock)
+#define netdata_rwlock_tryrdlock(rwlock)  __netdata_rwlock_tryrdlock(rwlock)
+#define netdata_rwlock_trywrlock(rwlock)  __netdata_rwlock_trywrlock(rwlock)
+
+#endif // NETDATA_INTERNAL_CHECKS
+
+#endif //NETDATA_LOCKS_H
index 24b971e2cf7c44a51e5434ecd81671e207ec05fd..d8ff0654bc21fcbf92b2724ac8132a2e2abca8c7 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -27,6 +27,7 @@
 #define D_HEALTH            0x0000000000800000
 #define D_CONNECT_TO        0x0000000001000000
 #define D_RRDHOST           0x0000000002000000
+#define D_LOCKS             0x0000000004000000
 #define D_SYSTEM            0x8000000000000000
 
 //#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
index 86bd8604be39ba7b6687ed584f4ab88760e5e01c..20722a58f0cd60d8362de62499c9420f589ad2cd 100644 (file)
@@ -230,6 +230,7 @@ struct option_def options[] = {
     { 't', "The internal clock of netdata.",              "seconds",     "1"},
     { 'u', "Run as user.",                                "username",    "netdata"},
     { 'v', "Print netdata version and exit.",             NULL,          NULL},
+    { 'V', "Print netdata version and exit.",             NULL,          NULL},
     { 'W', "See Advanced options below.",                 "options",     NULL},
 };
 
@@ -614,6 +615,7 @@ int main(int argc, char **argv) {
                     config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg);
                     break;
                 case 'v':
+                case 'V':
                     printf("%s %s\n", program_name, program_version);
                     return 0;
                 case 'W':
index ec6fb83bad37309d188d30d830e6daa98e1f0f51..ed9be984881d770d29c873285207cb2f076ca8f8 100644 (file)
 // REGISTRY concurrency locking
 
 static inline void registry_lock(void) {
-    pthread_mutex_lock(&registry.lock);
+    netdata_mutex_lock(&registry.lock);
 }
 
 static inline void registry_unlock(void) {
-    pthread_mutex_unlock(&registry.lock);
+    netdata_mutex_unlock(&registry.lock);
 }
 
 
index 0916726046415e280ac1bc3485a9f445c0464615..2a41d36eef13c8af8ce7be462855c6ec8b6c5fc8 100644 (file)
@@ -68,7 +68,7 @@ int registry_init(void) {
     registry.machines_urls_memory = 0;
 
     // initialize locks
-    pthread_mutex_init(&registry.lock, NULL);
+    netdata_mutex_init(&registry.lock);
 
     // create dictionaries
     registry.persons = dictionary_create(DICTIONARY_FLAGS);
index 27c2fe0745de4e1b5d09680eae75a4eea058b919..433f04a66273db2f81b82d46dc9060db00f80e29 100644 (file)
@@ -56,7 +56,7 @@ struct registry {
 
     avl_tree registry_urls_root_index;
 
-    pthread_mutex_t lock;
+    netdata_mutex_t lock;
 };
 
 extern int regenerate_guid(const char *guid, char *result);
index 2b872ed7dccacb6b312fd4cbbe17622303f44834..7843c80381e3c4fa10ae429f0ce8dda3fc777ac3 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -273,7 +273,7 @@ struct rrdset {
     char *cache_dir;                                // the directory to store dimensions
     char cache_filename[FILENAME_MAX+1];            // the filename to store this set
 
-    pthread_rwlock_t rrdset_rwlock;                 // protects dimensions linked list
+    netdata_rwlock_t rrdset_rwlock;                 // protects dimensions linked list
 
     size_t counter;                                 // the number of times we added values to this database
     size_t counter_done;                            // the number of times rrdset_done() has been called
@@ -325,9 +325,10 @@ struct rrdset {
 };
 typedef struct rrdset RRDSET;
 
-#define rrdset_rdlock(st) pthread_rwlock_rdlock(&((st)->rrdset_rwlock))
-#define rrdset_wrlock(st) pthread_rwlock_wrlock(&((st)->rrdset_rwlock))
-#define rrdset_unlock(st) pthread_rwlock_unlock(&((st)->rrdset_rwlock))
+#define rrdset_rdlock(st) netdata_rwlock_rdlock(&((st)->rrdset_rwlock))
+#define rrdset_wrlock(st) netdata_rwlock_wrlock(&((st)->rrdset_rwlock))
+#define rrdset_unlock(st) netdata_rwlock_unlock(&((st)->rrdset_rwlock))
+
 
 // ----------------------------------------------------------------------------
 // these loop macros make sure the linked list is accessed with the right lock
@@ -393,7 +394,7 @@ struct rrdhost {
     volatile int rrdpush_error_shown:1;             // 1 when we have logged a communication error
     int rrdpush_socket;                             // the fd of the socket to the remote host, or -1
     pthread_t rrdpush_thread;                       // the sender thread
-    pthread_mutex_t rrdpush_mutex;                  // exclusive access to rrdpush_buffer
+    netdata_mutex_t rrdpush_mutex;                  // exclusive access to rrdpush_buffer
     int rrdpush_pipe[2];                            // collector to sender thread communication
     BUFFER *rrdpush_buffer;                         // collector fills it, sender sends them
 
@@ -439,7 +440,7 @@ struct rrdhost {
     // ------------------------------------------------------------------------
     // locks
 
-    pthread_rwlock_t rrdhost_rwlock;                // lock for this RRDHOST (protects rrdset_root linked list)
+    netdata_rwlock_t rrdhost_rwlock;                // lock for this RRDHOST (protects rrdset_root linked list)
 
     avl_tree_lock rrdset_root_index;                // the host's charts index (by id)
     avl_tree_lock rrdset_root_index_name;           // the host's charts index (by name)
@@ -452,9 +453,9 @@ struct rrdhost {
 typedef struct rrdhost RRDHOST;
 extern RRDHOST *localhost;
 
-#define rrdhost_rdlock(h) pthread_rwlock_rdlock(&((h)->rrdhost_rwlock))
-#define rrdhost_wrlock(h) pthread_rwlock_wrlock(&((h)->rrdhost_rwlock))
-#define rrdhost_unlock(h) pthread_rwlock_unlock(&((h)->rrdhost_rwlock))
+#define rrdhost_rdlock(host) netdata_rwlock_rdlock(&((host)->rrdhost_rwlock))
+#define rrdhost_wrlock(host) netdata_rwlock_wrlock(&((host)->rrdhost_rwlock))
+#define rrdhost_unlock(host) netdata_rwlock_unlock(&((host)->rrdhost_rwlock))
 
 // ----------------------------------------------------------------------------
 // these loop macros make sure the linked list is accessed with the right lock
@@ -469,10 +470,11 @@ extern RRDHOST *localhost;
 // ----------------------------------------------------------------------------
 // global lock for all RRDHOSTs
 
-extern pthread_rwlock_t rrd_rwlock;
-#define rrd_rdlock() pthread_rwlock_rdlock(&rrd_rwlock)
-#define rrd_wrlock() pthread_rwlock_wrlock(&rrd_rwlock)
-#define rrd_unlock() pthread_rwlock_unlock(&rrd_rwlock)
+extern netdata_rwlock_t rrd_rwlock;
+
+#define rrd_rdlock() netdata_rwlock_rdlock(&rrd_rwlock)
+#define rrd_wrlock() netdata_rwlock_wrlock(&rrd_rwlock)
+#define rrd_unlock() netdata_rwlock_unlock(&rrd_rwlock)
 
 // ----------------------------------------------------------------------------
 
@@ -497,20 +499,20 @@ extern RRDHOST *rrdhost_find_or_create(
         , char *rrdpush_api_key
 );
 
-#ifdef NETDATA_INTERNAL_CHECKS
-extern void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line);
-extern void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line);
-extern void rrdset_check_rdlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line);
-extern void rrdset_check_wrlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line);
-extern void rrd_check_rdlock_int(const char *file, const char *function, const unsigned long line);
-extern void rrd_check_wrlock_int(const char *file, const char *function, const unsigned long line);
-
-#define rrdhost_check_rdlock(host) rrdhost_check_rdlock_int(host, __FILE__, __FUNCTION__, __LINE__)
-#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__)
-#define rrdset_check_rdlock(st) rrdset_check_rdlock_int(st, __FILE__, __FUNCTION__, __LINE__)
-#define rrdset_check_wrlock(st) rrdset_check_wrlock_int(st, __FILE__, __FUNCTION__, __LINE__)
-#define rrd_check_rdlock() rrd_check_rdlock_int(__FILE__, __FUNCTION__, __LINE__)
-#define rrd_check_wrlock() rrd_check_wrlock_int(__FILE__, __FUNCTION__, __LINE__)
+#if defined(NETDATA_INTERNAL_CHECKS) && defined(NETDATA_VERIFY_LOCKS)
+extern void __rrdhost_check_wrlock(RRDHOST *host, const char *file, const char *function, const unsigned long line);
+extern void __rrdhost_check_rdlock(RRDHOST *host, const char *file, const char *function, const unsigned long line);
+extern void __rrdset_check_rdlock(RRDSET *st, const char *file, const char *function, const unsigned long line);
+extern void __rrdset_check_wrlock(RRDSET *st, const char *file, const char *function, const unsigned long line);
+extern void __rrd_check_rdlock(const char *file, const char *function, const unsigned long line);
+extern void __rrd_check_wrlock(const char *file, const char *function, const unsigned long line);
+
+#define rrdhost_check_rdlock(host) __rrdhost_check_rdlock(host, __FILE__, __FUNCTION__, __LINE__)
+#define rrdhost_check_wrlock(host) __rrdhost_check_wrlock(host, __FILE__, __FUNCTION__, __LINE__)
+#define rrdset_check_rdlock(st) __rrdset_check_rdlock(st, __FILE__, __FUNCTION__, __LINE__)
+#define rrdset_check_wrlock(st) __rrdset_check_wrlock(st, __FILE__, __FUNCTION__, __LINE__)
+#define rrd_check_rdlock() __rrd_check_rdlock(__FILE__, __FUNCTION__, __LINE__)
+#define rrd_check_wrlock() __rrd_check_wrlock(__FILE__, __FUNCTION__, __LINE__)
 
 #else
 #define rrdhost_check_rdlock(host) (void)0
index 8f2ea62386086713975368f8eb92657bd5ded797..74ae1bb744df6f582600e361ed96a3cb18da6ddd 100644 (file)
@@ -323,6 +323,74 @@ void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) {
 
 // ----------------------------------------------------------------------------
 
+void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) {
+    rrdhost_rdlock(host);
+
+    buffer_strcat(wb, "{");
+
+    size_t chart_counter = 0;
+    size_t dimension_counter = 0;
+
+    // for each chart
+    RRDSET *st;
+    rrdset_foreach_read(st, host) {
+        if(rrdset_is_available_for_viewers(st)) {
+            rrdset_rdlock(st);
+
+            buffer_sprintf(wb, "%s\n"
+                    "\t\"%s\": {\n"
+                    "\t\t\"name\":\"%s\",\n"
+                    "\t\t\"context\":\"%s\",\n"
+                    "\t\t\"units\":\"%s\",\n"
+                    "\t\t\"last_updated\": %ld,\n"
+                    "\t\t\"dimensions\": {"
+                    , chart_counter?",":""
+                    , st->id
+                    , st->name
+                    , st->context
+                    , st->units
+                    , rrdset_last_entry_t(st)
+            );
+
+            chart_counter++;
+            dimension_counter = 0;
+
+            // for each dimension
+            RRDDIM *rd;
+            rrddim_foreach_read(rd, st) {
+                if(rd->collections_counter) {
+
+                    buffer_sprintf(wb, "%s\n"
+                            "\t\t\t\"%s\": {\n"
+                            "\t\t\t\t\"name\": \"%s\",\n"
+                            "\t\t\t\t\"value\": "
+                            , dimension_counter?",":""
+                            , rd->id
+                            , rd->name
+                    );
+
+                    if(isnan(rd->last_stored_value))
+                        buffer_strcat(wb, "null");
+                    else
+                        buffer_sprintf(wb, CALCULATED_NUMBER_FORMAT, rd->last_stored_value);
+
+                    buffer_strcat(wb, "\n\t\t\t}");
+
+                    dimension_counter++;
+                }
+            }
+
+            buffer_strcat(wb, "\n\t\t}\n\t}");
+            rrdset_unlock(st);
+        }
+    }
+
+    buffer_strcat(wb, "\n}");
+    rrdhost_unlock(host);
+}
+
+// ----------------------------------------------------------------------------
+
 // RRDR dimension options
 #define RRDR_EMPTY      0x01 // the dimension contains / the value is empty (null)
 #define RRDR_RESET      0x02 // the dimension contains / the value is reset
index 2e977eb50118f147db0150c3a7cb6935529b831b..f2f03c64052ba5d3942f8530f3309d871c32bae8 100644 (file)
 
 #define ALLMETRICS_FORMAT_SHELL "shell"
 #define ALLMETRICS_FORMAT_PROMETHEUS "prometheus"
+#define ALLMETRICS_FORMAT_JSON "json"
 
 #define ALLMETRICS_SHELL 1
 #define ALLMETRICS_PROMETHEUS 2
+#define ALLMETRICS_JSON 3
 
 #define GROUP_UNDEFINED         0
 #define GROUP_AVERAGE           1
@@ -61,6 +63,7 @@
 extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
 extern void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb);
 
+extern void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb);
 extern void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb);
 extern void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb);
 
index 576de2b16f8b9d13d26f15ad7db45024e4d64d8d..575b9ec0816860e47c52aad71785c0d6f88e1f0d 100644 (file)
@@ -3,7 +3,7 @@
 
 RRDHOST *localhost = NULL;
 size_t rrd_hosts_available = 0;
-pthread_rwlock_t rrd_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+netdata_rwlock_t rrd_rwlock = NETDATA_RWLOCK_INITIALIZER;
 
 time_t rrdset_free_obsolete_time = 3600;
 time_t rrdhost_free_orphan_time = 3600;
@@ -91,9 +91,10 @@ RRDHOST *rrdhost_create(const char *hostname,
         char *rrdpush_api_key,
         int is_localhost
 ) {
-
     debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid);
 
+    rrd_check_wrlock();
+
     RRDHOST *host = callocz(1, sizeof(RRDHOST));
 
     host->rrd_update_every    = update_every;
@@ -108,8 +109,8 @@ RRDHOST *rrdhost_create(const char *hostname,
     host->rrdpush_pipe[1] = -1;
     host->rrdpush_socket  = -1;
 
-    pthread_mutex_init(&host->rrdpush_mutex, NULL);
-    pthread_rwlock_init(&host->rrdhost_rwlock, NULL);
+    netdata_mutex_init(&host->rrdpush_mutex);
+    netdata_rwlock_init(&host->rrdhost_rwlock);
 
     rrdhost_init_hostname(host, hostname);
     rrdhost_init_machine_guid(host, guid);
@@ -144,7 +145,7 @@ RRDHOST *rrdhost_create(const char *hostname,
     else
         host->health_log.max = (unsigned int)n;
 
-    pthread_rwlock_init(&(host->health_log.alarm_log_rwlock), NULL);
+    netdata_rwlock_init(&host->health_log.alarm_log_rwlock);
 
     char filename[FILENAME_MAX + 1];
 
@@ -208,8 +209,6 @@ RRDHOST *rrdhost_create(const char *hostname,
     // ------------------------------------------------------------------------
     // link it and add it to the index
 
-    rrd_wrlock();
-
     if(is_localhost) {
         host->next = localhost;
         localhost = host;
@@ -262,7 +261,6 @@ RRDHOST *rrdhost_create(const char *hostname,
     }
 
     rrd_hosts_available++;
-    rrd_unlock();
 
     return host;
 }
@@ -281,6 +279,7 @@ RRDHOST *rrdhost_find_or_create(
 ) {
     debug(D_RRDHOST, "Searching for host '%s' with guid '%s'", hostname, guid);
 
+    rrd_wrlock();
     RRDHOST *host = rrdhost_find_by_guid(guid, 0);
     if(!host) {
         host = rrdhost_create(
@@ -302,8 +301,8 @@ RRDHOST *rrdhost_find_or_create(
 
         if(strcmp(host->hostname, hostname)) {
             char *t = host->hostname;
-            char *n = strdupz(hostname);
-            host->hostname = n;
+            host->hostname = strdupz(hostname);
+            host->hash_hostname = simple_hash(host->hostname);
             freez(t);
         }
 
@@ -316,12 +315,24 @@ RRDHOST *rrdhost_find_or_create(
         if(host->rrd_memory_mode != mode)
             error("Host '%s' has memory mode '%s', but the wanted one is '%s'.", host->hostname, rrd_memory_mode_name(host->rrd_memory_mode), rrd_memory_mode_name(mode));
     }
+    rrd_unlock();
 
     rrdhost_cleanup_orphan(host);
 
     return host;
 }
 
+static inline int rrdhost_should_be_deleted(RRDHOST *host, RRDHOST *protected, time_t now) {
+    if(host != protected
+       && host != localhost
+       && !host->connected_senders
+       && host->senders_disconnected_time
+       && host->senders_disconnected_time + rrdhost_free_orphan_time < now)
+        return 1;
+
+    return 0;
+}
+
 void rrdhost_cleanup_orphan(RRDHOST *protected) {
     time_t now = now_realtime_sec();
 
@@ -331,10 +342,7 @@ void rrdhost_cleanup_orphan(RRDHOST *protected) {
 
 restart_after_removal:
     rrdhost_foreach_write(host) {
-        if(host != protected
-           && host != localhost
-           && !host->connected_senders
-           && host->senders_disconnected_time + rrdhost_free_orphan_time < now) {
+        if(rrdhost_should_be_deleted(host, protected, now)) {
             info("Host '%s' with machine guid '%s' is obsolete - cleaning up.", host->hostname, host->machine_guid);
 
             if(rrdset_flag_check(host, RRDHOST_ORPHAN))
@@ -361,6 +369,7 @@ void rrd_init(char *hostname) {
     rrdpush_init();
 
     debug(D_RRDHOST, "Initializing localhost with hostname '%s'", hostname);
+    rrd_wrlock();
     localhost = rrdhost_create(
             hostname
             , registry_get_this_machine_guid()
@@ -374,40 +383,41 @@ void rrd_init(char *hostname) {
             , default_rrdpush_api_key
             , 1
     );
+    rrd_unlock();
 }
 
 // ----------------------------------------------------------------------------
 // RRDHOST - lock validations
 // there are only used when NETDATA_INTERNAL_CHECKS is set
 
-void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
+void __rrdhost_check_rdlock(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
     debug(D_RRDHOST, "Checking read lock on host '%s'", host->hostname);
 
-    int ret = pthread_rwlock_trywrlock(&host->rrdhost_rwlock);
+    int ret = netdata_rwlock_trywrlock(&host->rrdhost_rwlock);
     if(ret == 0)
         fatal("RRDHOST '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
 }
 
-void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
+void __rrdhost_check_wrlock(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
     debug(D_RRDHOST, "Checking write lock on host '%s'", host->hostname);
 
-    int ret = pthread_rwlock_tryrdlock(&host->rrdhost_rwlock);
+    int ret = netdata_rwlock_tryrdlock(&host->rrdhost_rwlock);
     if(ret == 0)
         fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
 }
 
-void rrd_check_rdlock_int(const char *file, const char *function, const unsigned long line) {
+void __rrd_check_rdlock(const char *file, const char *function, const unsigned long line) {
     debug(D_RRDHOST, "Checking read lock on all RRDs");
 
-    int ret = pthread_rwlock_trywrlock(&rrd_rwlock);
+    int ret = netdata_rwlock_trywrlock(&rrd_rwlock);
     if(ret == 0)
         fatal("RRDs should be read-locked, but it are not, at function %s() at line %lu of file '%s'", function, line, file);
 }
 
-void rrd_check_wrlock_int(const char *file, const char *function, const unsigned long line) {
+void __rrd_check_wrlock(const char *file, const char *function, const unsigned long line) {
     debug(D_RRDHOST, "Checking write lock on all RRDs");
 
-    int ret = pthread_rwlock_tryrdlock(&rrd_rwlock);
+    int ret = netdata_rwlock_tryrdlock(&rrd_rwlock);
     if(ret == 0)
         fatal("RRDs should be write-locked, but it are not, at function %s() at line %lu of file '%s'", function, line, file);
 }
@@ -473,6 +483,8 @@ void rrdhost_free(RRDHOST *host) {
     freez(host->health_log_filename);
     freez(host->hostname);
     rrdhost_unlock(host);
+    netdata_rwlock_destroy(&host->health_log.alarm_log_rwlock);
+    netdata_rwlock_destroy(&host->rrdhost_rwlock);
     freez(host);
 
     rrd_hosts_available--;
index f5f54d39a320e8158b2b7df2d4921510a0a6c1bc..87c4309a2f546d7bff85c195c7d8f707395c0f63 100644 (file)
@@ -33,7 +33,7 @@ int rrdpush_init() {
     default_rrdpush_enabled     = appconfig_get_boolean(&stream_config, CONFIG_SECTION_STREAM, "enabled", default_rrdpush_enabled);
     default_rrdpush_destination = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "destination", "");
     default_rrdpush_api_key     = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "api key", "");
-    rrdhost_free_orphan_time    = appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "free orphan hosts after seconds", rrdhost_free_orphan_time);
+    rrdhost_free_orphan_time    = config_get_number(CONFIG_SECTION_GLOBAL, "cleanup orphan hosts after seconds", rrdhost_free_orphan_time);
 
     if(default_rrdpush_enabled && (!default_rrdpush_destination || !*default_rrdpush_destination || !default_rrdpush_api_key || !*default_rrdpush_api_key)) {
         error("STREAM [send]: cannot enable sending thread - information is missing.");
@@ -59,8 +59,8 @@ int rrdpush_init() {
 // this is for the first iterations of each chart
 static unsigned int remote_clock_resync_iterations = 60;
 
-#define rrdpush_lock(host) pthread_mutex_lock(&((host)->rrdpush_mutex))
-#define rrdpush_unlock(host) pthread_mutex_unlock(&((host)->rrdpush_mutex))
+#define rrdpush_lock(host) netdata_mutex_lock(&((host)->rrdpush_mutex))
+#define rrdpush_unlock(host) netdata_mutex_unlock(&((host)->rrdpush_mutex))
 
 // checks if the current chart definition has been sent
 static inline int need_to_send_chart_definition(RRDSET *st) {
index 1918b5cb2ee8e3e45df900f2c8eb51aa98682a58..c847b96907de21c655707b725712a54289166886 100644 (file)
@@ -3,18 +3,18 @@
 
 #define RRD_DEFAULT_GAP_INTERPOLATIONS 1
 
-void rrdset_check_rdlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line) {
+void __rrdset_check_rdlock(RRDSET *st, const char *file, const char *function, const unsigned long line) {
     debug(D_RRD_CALLS, "Checking read lock on chart '%s'", st->id);
 
-    int ret = pthread_rwlock_trywrlock(&st->rrdset_rwlock);
+    int ret = netdata_rwlock_trywrlock(&st->rrdset_rwlock);
     if(ret == 0)
         fatal("RRDSET '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", st->id, function, line, file);
 }
 
-void rrdset_check_wrlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line) {
+void __rrdset_check_wrlock(RRDSET *st, const char *file, const char *function, const unsigned long line) {
     debug(D_RRD_CALLS, "Checking write lock on chart '%s'", st->id);
 
-    int ret = pthread_rwlock_tryrdlock(&st->rrdset_rwlock);
+    int ret = netdata_rwlock_tryrdlock(&st->rrdset_rwlock);
     if(ret == 0)
         fatal("RRDSET '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", st->id, function, line, file);
 }
@@ -274,6 +274,8 @@ void rrdset_free(RRDSET *st) {
     // ------------------------------------------------------------------------
     // free it
 
+    netdata_rwlock_destroy(&st->rrdset_rwlock);
+
     // free directly allocated members
     freez(st->config_section);
 
@@ -328,6 +330,17 @@ void rrdset_delete(RRDSET *st) {
 // ----------------------------------------------------------------------------
 // RRDSET - create a chart
 
+static inline RRDSET *rrdset_find_on_create(RRDHOST *host, const char *fullid) {
+    RRDSET *st = rrdset_find(host, fullid);
+    if(unlikely(st)) {
+        rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE);
+        debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid);
+        return st;
+    }
+
+    return NULL;
+}
+
 RRDSET *rrdset_create(
           RRDHOST *host
         , const char *type
@@ -357,10 +370,14 @@ RRDSET *rrdset_create(
     char fullid[RRD_ID_LENGTH_MAX + 1];
     snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);
 
-    RRDSET *st = rrdset_find(host, fullid);
+    RRDSET *st = rrdset_find_on_create(host, fullid);
+    if(st) return st;
+
+    rrdhost_wrlock(host);
+
+    st = rrdset_find_on_create(host, fullid);
     if(st) {
-        rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE);
-        debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid);
+        rrdhost_unlock(host);
         return st;
     }
 
@@ -406,7 +423,7 @@ RRDSET *rrdset_create(
             memset(&st->avlname, 0, sizeof(avl));
             memset(&st->variables_root_index, 0, sizeof(avl_tree_lock));
             memset(&st->dimensions_index, 0, sizeof(avl_tree_lock));
-            memset(&st->rrdset_rwlock, 0, sizeof(pthread_rwlock_t));
+            memset(&st->rrdset_rwlock, 0, sizeof(netdata_rwlock_t));
 
             st->name = NULL;
             st->type = NULL;
@@ -522,8 +539,7 @@ RRDSET *rrdset_create(
     avl_init_lock(&st->dimensions_index, rrddim_compare);
     avl_init_lock(&st->variables_root_index, rrdvar_compare);
 
-    pthread_rwlock_init(&st->rrdset_rwlock, NULL);
-    rrdhost_wrlock(host);
+    netdata_rwlock_init(&st->rrdset_rwlock);
 
     if(name && *name) rrdset_set_name(st, name);
     else rrdset_set_name(st, id);
@@ -1250,8 +1266,8 @@ void rrdset_done(RRDSET *st) {
             RRDDIM *last;
             // there is dimension to free
             // upgrade our read lock to a write lock
-            pthread_rwlock_unlock(&st->rrdset_rwlock);
-            pthread_rwlock_wrlock(&st->rrdset_rwlock);
+            rrdset_unlock(st);
+            rrdset_wrlock(st);
 
             for( rd = st->dimensions, last = NULL ; likely(rd) ; ) {
                 // remove it only it is not updated in rrd_delete_unupdated_dimensions seconds
index da93c8948061d55744fcfe5fff79516e9914b636..0acc43acb873df4b8603423d5802bb8f16ad839e 100644 (file)
@@ -222,6 +222,8 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
                 format = ALLMETRICS_SHELL;
             else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS))
                 format = ALLMETRICS_PROMETHEUS;
+            else if(!strcmp(value, ALLMETRICS_FORMAT_JSON))
+                format = ALLMETRICS_JSON;
             else
                 format = 0;
         }
@@ -231,6 +233,11 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
     buffer_no_cacheable(w->response.data);
 
     switch(format) {
+        case ALLMETRICS_JSON:
+            w->response.data->contenttype = CT_APPLICATION_JSON;
+            rrd_stats_api_v1_charts_allmetrics_json(host, w->response.data);
+            return 200;
+
         case ALLMETRICS_SHELL:
             w->response.data->contenttype = CT_TEXT_PLAIN;
             rrd_stats_api_v1_charts_allmetrics_shell(host, w->response.data);
@@ -243,7 +250,7 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
 
         default:
             w->response.data->contenttype = CT_TEXT_PLAIN;
-            buffer_strcat(w->response.data, "Which format? Only '" ALLMETRICS_FORMAT_SHELL "' and '" ALLMETRICS_FORMAT_PROMETHEUS "' is currently supported.");
+            buffer_strcat(w->response.data, "Which format? '" ALLMETRICS_FORMAT_SHELL "', '" ALLMETRICS_FORMAT_PROMETHEUS "' and '" ALLMETRICS_FORMAT_JSON "' are currently supported.");
             return 400;
     }
 }
index 8f6dca018e39fdf49398aa26c6b9cca964a30f22..a254aa83907e547500c39e3b51ac8c78b4022cf7 100644 (file)
             var len, i, url, hostname, icon;
 
             if(options.hosts.length > 1) {
+                // there are mirrored hosts here
+
                 el += '<li><a href="#" onClick="return false;" style="color: #666;" target="_blank">databases available on this host</a></li>';
                 a1 += '<li><a href="#" onClick="return false;"><i class="fa fa-info-circle" aria-hidden="true" style="color: #666;"></i></a></li>';
 
                 if(base.endsWith("/"))
                     base = base.substring(0, base.length - 1);
 
+                var master = options.hosts[0].hostname;
+                var sorted = options.hosts.sort(function(a, b) {
+                    if(a.hostname === master) return -1;
+                    if(a.hostname === b.hostname) return 0;
+                    else if(a.hostname > b.hostname) return 1;
+                    return -1;
+                });
+
                 i = 0;
-                len = options.hosts.length;
+                len = sorted.length;
                 while(len--) {
-                    hostname = options.hosts[i].hostname;
-                    if(i == 0) {
+                    hostname = sorted[i].hostname;
+                    if(hostname == master) {
                         url = base + "/";
                         icon = "home";
                     }