summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2018-11-07 12:19:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2018-11-07 12:20:17 +0000
commita64a253794ac64cb40befee54db53bde17dd0d49 (patch)
treec1024acc5f6e508814b944d99f112259bb28b1be /src
parentNew upstream version 1.10.0+dfsg (diff)
downloadnetdata-a64a253794ac64cb40befee54db53bde17dd0d49.tar.xz
netdata-a64a253794ac64cb40befee54db53bde17dd0d49.zip
New upstream version 1.11.0+dfsgupstream/1.11.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src')
-rw-r--r--src/.keep0
-rw-r--r--src/Makefile.am307
-rw-r--r--src/Makefile.in1238
-rw-r--r--src/adaptive_resortable_list.c269
-rw-r--r--src/adaptive_resortable_list.h171
-rw-r--r--src/appconfig.c606
-rw-r--r--src/appconfig.h74
-rw-r--r--src/apps_plugin.c3639
-rw-r--r--src/avl.c403
-rw-r--r--src/avl.h86
-rw-r--r--src/backend_prometheus.c479
-rw-r--r--src/backend_prometheus.h11
-rw-r--r--src/backends.c969
-rw-r--r--src/backends.h30
-rw-r--r--src/cgroup-network.c651
-rw-r--r--src/clocks.c137
-rw-r--r--src/clocks.h124
-rw-r--r--src/common.c1361
-rw-r--r--src/common.h360
-rw-r--r--src/daemon.c396
-rw-r--r--src/daemon.h12
-rw-r--r--src/dictionary.c292
-rw-r--r--src/dictionary.h44
-rw-r--r--src/eval.c1188
-rw-r--r--src/eval.h72
-rw-r--r--src/freebsd_devstat.c778
-rw-r--r--src/freebsd_getifaddrs.c506
-rw-r--r--src/freebsd_getmntinfo.c299
-rw-r--r--src/freebsd_ipfw.c370
-rw-r--r--src/freebsd_kstat_zfs.c298
-rw-r--r--src/freebsd_sysctl.c3171
-rw-r--r--src/freeipmi_plugin.c1680
-rw-r--r--src/global_statistics.c414
-rw-r--r--src/global_statistics.h38
-rw-r--r--src/health.c737
-rw-r--r--src/health.h438
-rw-r--r--src/health_config.c900
-rw-r--r--src/health_json.c260
-rw-r--r--src/health_log.c463
-rw-r--r--src/inlined.h291
-rw-r--r--src/ipc.c261
-rw-r--r--src/ipc.h7
-rw-r--r--src/locks.c319
-rw-r--r--src/locks.h71
-rw-r--r--src/log.c427
-rw-r--r--src/log.h87
-rw-r--r--src/macos_fw.c684
-rw-r--r--src/macos_mach_smi.c238
-rw-r--r--src/macos_sysctl.c1504
-rw-r--r--src/main.c1071
-rw-r--r--src/main.h41
-rw-r--r--src/plugin_checks.c127
-rw-r--r--src/plugin_checks.h8
-rw-r--r--src/plugin_freebsd.c173
-rw-r--r--src/plugin_freebsd.h130
-rw-r--r--src/plugin_idlejitter.c90
-rw-r--r--src/plugin_idlejitter.h6
-rw-r--r--src/plugin_macos.c67
-rw-r--r--src/plugin_macos.h14
-rw-r--r--src/plugin_nfacct.c819
-rw-r--r--src/plugin_nfacct.h7
-rw-r--r--src/plugin_proc.c201
-rw-r--r--src/plugin_proc.h42
-rw-r--r--src/plugin_proc_diskspace.c460
-rw-r--r--src/plugin_proc_diskspace.h6
-rw-r--r--src/plugin_tc.c1164
-rw-r--r--src/plugin_tc.h7
-rw-r--r--src/plugins_d.c694
-rw-r--r--src/plugins_d.h57
-rw-r--r--src/popen.c204
-rw-r--r--src/popen.h11
-rw-r--r--src/proc_diskstats.c1438
-rw-r--r--src/proc_interrupts.c253
-rw-r--r--src/proc_loadavg.c119
-rw-r--r--src/proc_meminfo.c514
-rw-r--r--src/proc_net_dev.c894
-rw-r--r--src/proc_net_ip_vs_stats.c129
-rw-r--r--src/proc_net_netstat.c761
-rw-r--r--src/proc_net_rpc_nfs.c449
-rw-r--r--src/proc_net_rpc_nfsd.c1002
-rw-r--r--src/proc_net_snmp.c1020
-rw-r--r--src/proc_net_snmp6.c1265
-rw-r--r--src/proc_net_sockstat.c514
-rw-r--r--src/proc_net_sockstat6.c269
-rw-r--r--src/proc_net_softnet_stat.c147
-rw-r--r--src/proc_net_stat_conntrack.c348
-rw-r--r--src/proc_net_stat_synproxy.c181
-rw-r--r--src/proc_self_mountinfo.c401
-rw-r--r--src/proc_self_mountinfo.h55
-rw-r--r--src/proc_softirqs.c249
-rw-r--r--src/proc_spl_kstat_zfs.c153
-rw-r--r--src/proc_stat.c557
-rw-r--r--src/proc_sys_kernel_random_entropy_avail.c47
-rw-r--r--src/proc_uptime.c103
-rw-r--r--src/proc_vmstat.c255
-rw-r--r--src/procfile.c468
-rw-r--r--src/procfile.h124
-rw-r--r--src/registry.c414
-rw-r--r--src/registry.h77
-rw-r--r--src/registry_db.c343
-rw-r--r--src/registry_init.c143
-rw-r--r--src/registry_internals.c322
-rw-r--r--src/registry_internals.h86
-rw-r--r--src/registry_log.c133
-rw-r--r--src/registry_machine.c101
-rw-r--r--src/registry_machine.h41
-rw-r--r--src/registry_person.c264
-rw-r--r--src/registry_person.h60
-rw-r--r--src/registry_url.c85
-rw-r--r--src/registry_url.h33
-rw-r--r--src/rrd.c148
-rw-r--r--src/rrd.h747
-rw-r--r--src/rrd2json.c2059
-rw-r--r--src/rrd2json.h82
-rw-r--r--src/rrd2json_api_old.c487
-rw-r--r--src/rrd2json_api_old.h14
-rw-r--r--src/rrdcalc.c424
-rw-r--r--src/rrdcalctemplate.c69
-rw-r--r--src/rrddim.c387
-rw-r--r--src/rrddimvar.c212
-rw-r--r--src/rrdfamily.c59
-rw-r--r--src/rrdhost.c735
-rw-r--r--src/rrdpush.c1160
-rw-r--r--src/rrdpush.h19
-rw-r--r--src/rrdset.c1544
-rw-r--r--src/rrdsetvar.c183
-rw-r--r--src/rrdvar.c275
-rw-r--r--src/signals.c168
-rw-r--r--src/signals.h10
-rw-r--r--src/simple_pattern.c260
-rw-r--r--src/simple_pattern.h28
-rw-r--r--src/socket.c1518
-rw-r--r--src/socket.h162
-rw-r--r--src/statistical.c459
-rw-r--r--src/statistical.h19
-rw-r--r--src/statsd.c2499
-rw-r--r--src/statsd.h9
-rw-r--r--src/storage_number.c231
-rw-r--r--src/storage_number.h88
-rw-r--r--src/sys_devices_system_edac_mc.c204
-rw-r--r--src/sys_devices_system_node.c161
-rw-r--r--src/sys_fs_btrfs.c714
-rw-r--r--src/sys_fs_cgroup.c2765
-rw-r--r--src/sys_kernel_mm_ksm.c197
-rw-r--r--src/threads.c181
-rw-r--r--src/threads.h33
-rw-r--r--src/unit_test.c1368
-rw-r--r--src/unit_test.h10
-rw-r--r--src/url.c77
-rw-r--r--src/url.h24
-rw-r--r--src/web_api_old.c237
-rw-r--r--src/web_api_old.h13
-rw-r--r--src/web_api_v1.c1017
-rw-r--r--src/web_api_v1.h23
-rw-r--r--src/web_buffer.c400
-rw-r--r--src/web_buffer.h81
-rw-r--r--src/web_buffer_svg.c832
-rw-r--r--src/web_buffer_svg.h7
-rw-r--r--src/web_client.c1706
-rw-r--r--src/web_client.h189
-rw-r--r--src/web_server.c1292
-rw-r--r--src/web_server.h46
-rw-r--r--src/zfs_common.c713
-rw-r--r--src/zfs_common.h111
164 files changed, 0 insertions, 72832 deletions
diff --git a/src/.keep b/src/.keep
deleted file mode 100644
index e69de29bb..000000000
--- a/src/.keep
+++ /dev/null
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index df174cbd1..000000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,307 +0,0 @@
-#
-# Copyright (C) 2015 Alon Bar-Lev <alon.barlev@gmail.com>
-#
-MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
-
-AM_CPPFLAGS = \
- -DVARLIB_DIR="\"$(varlibdir)\"" \
- -DCACHE_DIR="\"$(cachedir)\"" \
- -DCONFIG_DIR="\"$(configdir)\"" \
- -DLOG_DIR="\"$(logdir)\"" \
- -DPLUGINS_DIR="\"$(pluginsdir)\"" \
- -DRUN_DIR="\"$(localstatedir)/run/netdata\"" \
- -DWEB_DIR="\"$(webdir)\"" \
- $(NULL)
-
-AM_CFLAGS = \
- $(OPTIONAL_MATH_CFLAGS) \
- $(OPTIONAL_NFACCT_CLFAGS) \
- $(OPTIONAL_ZLIB_CFLAGS) \
- $(OPTIONAL_UUID_CFLAGS) \
- $(OPTIONAL_LIBCAP_CFLAGS) \
- $(OPTIONAL_IPMIMONITORING_CFLAGS)\
- $(NULL)
-
-sbin_PROGRAMS = netdata
-dist_cache_DATA = .keep
-dist_varlib_DATA = .keep
-dist_registry_DATA = .keep
-dist_log_DATA = .keep
-plugins_PROGRAMS =
-
-if ENABLE_PLUGIN_APPS
-plugins_PROGRAMS += apps.plugin
-endif
-
-if ENABLE_PLUGIN_FREEIPMI
-plugins_PROGRAMS += freeipmi.plugin
-endif
-
-if ENABLE_PLUGIN_CGROUP_NETWORK
-plugins_PROGRAMS += cgroup-network
-endif
-
-netdata_SOURCES = \
- adaptive_resortable_list.c \
- adaptive_resortable_list.h \
- appconfig.c \
- appconfig.h \
- avl.c \
- avl.h \
- backend_prometheus.c \
- backend_prometheus.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 \
- locks.c \
- locks.h \
- log.c \
- log.h \
- main.c \
- main.h \
- plugin_checks.c \
- plugin_checks.h \
- plugin_idlejitter.c \
- plugin_idlejitter.h \
- plugins_d.c \
- plugins_d.h \
- popen.c \
- popen.h \
- procfile.c \
- procfile.h \
- registry.c \
- registry.h \
- registry_db.c \
- registry_init.c \
- registry_internals.c \
- registry_internals.h \
- registry_log.c \
- 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 \
- rrdsetvar.c \
- rrdvar.c \
- signals.c \
- signals.h \
- simple_pattern.c \
- simple_pattern.h \
- socket.c \
- socket.h \
- statistical.c \
- statistical.h \
- statsd.c \
- statsd.h \
- storage_number.c \
- storage_number.h \
- threads.c \
- threads.h \
- 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 \
- $(NULL)
-
-if FREEBSD
-netdata_SOURCES += \
- plugin_freebsd.c \
- plugin_freebsd.h \
- freebsd_sysctl.c \
- freebsd_getmntinfo.c \
- freebsd_getifaddrs.c \
- freebsd_devstat.c \
- zfs_common.c \
- zfs_common.h \
- freebsd_kstat_zfs.c \
- freebsd_ipfw.c \
- $(NULL)
-else
-if MACOS
-netdata_SOURCES += \
- plugin_macos.c \
- plugin_macos.h \
- macos_sysctl.c \
- macos_mach_smi.c \
- macos_fw.c \
- $(NULL)
-else
-netdata_SOURCES += \
- ipc.c \
- ipc.h \
- plugin_nfacct.c \
- plugin_nfacct.h \
- plugin_proc.c \
- plugin_proc.h \
- plugin_proc_diskspace.c \
- plugin_proc_diskspace.h \
- plugin_tc.c \
- plugin_tc.h \
- proc_diskstats.c \
- proc_interrupts.c \
- proc_softirqs.c \
- proc_loadavg.c \
- proc_meminfo.c \
- proc_net_dev.c \
- proc_net_ip_vs_stats.c \
- proc_net_netstat.c \
- proc_net_rpc_nfs.c \
- proc_net_rpc_nfsd.c \
- proc_net_snmp.c \
- proc_net_snmp6.c \
- proc_net_sockstat.c \
- proc_net_sockstat6.c \
- proc_net_softnet_stat.c \
- proc_net_stat_conntrack.c \
- proc_net_stat_synproxy.c \
- proc_self_mountinfo.c \
- proc_self_mountinfo.h \
- zfs_common.c \
- zfs_common.h \
- proc_spl_kstat_zfs.c \
- proc_stat.c \
- proc_sys_kernel_random_entropy_avail.c \
- proc_vmstat.c \
- proc_uptime.c \
- sys_kernel_mm_ksm.c \
- sys_devices_system_edac_mc.c \
- sys_devices_system_node.c \
- sys_fs_cgroup.c \
- sys_fs_btrfs.c \
- $(NULL)
-endif
-endif
-
-netdata_LDADD = \
- $(OPTIONAL_MATH_LIBS) \
- $(OPTIONAL_NFACCT_LIBS) \
- $(OPTIONAL_ZLIB_LIBS) \
- $(OPTIONAL_UUID_LIBS) \
- $(NULL)
-
-apps_plugin_SOURCES = \
- apps_plugin.c \
- avl.c \
- avl.h \
- clocks.c \
- clocks.h \
- common.c \
- common.h \
- inlined.h \
- locks.c \
- locks.h \
- log.c log.h \
- procfile.c \
- procfile.h \
- threads.c \
- threads.h \
- web_buffer.c \
- web_buffer.h \
- $(NULL)
-
-if FREEBSD
-apps_plugin_SOURCES += \
- plugin_freebsd.h \
- $(NULL)
-else
-apps_plugin_SOURCES += \
- adaptive_resortable_list.c \
- adaptive_resortable_list.h \
- $(NULL)
-endif
-
-apps_plugin_LDADD = \
- $(OPTIONAL_MATH_LIBS) \
- $(OPTIONAL_LIBCAP_LIBS) \
- $(NULL)
-
-freeipmi_plugin_SOURCES = \
- freeipmi_plugin.c \
- clocks.c \
- clocks.h \
- common.c \
- common.h \
- inlined.h \
- locks.c \
- locks.h \
- log.c log.h \
- procfile.c \
- procfile.h \
- threads.c \
- threads.h \
- $(NULL)
-
-freeipmi_plugin_LDADD = \
- $(OPTIONAL_IPMIMONITORING_LIBS) \
- $(NULL)
-
-cgroup_network_SOURCES = \
- cgroup-network.c \
- clocks.c \
- clocks.h \
- common.c \
- common.h \
- inlined.h \
- locks.c \
- locks.h \
- log.c \
- log.h \
- procfile.c \
- procfile.h \
- popen.c \
- popen.h \
- signals.c \
- signals.h \
- threads.c \
- threads.h \
- $(NULL)
-
-cgroup_network_LDADD = \
- $(OPTIONAL_MATH_LIBS) \
- $(OPTIONAL_LIBCAP_LIBS) \
- $(NULL)
diff --git a/src/Makefile.in b/src/Makefile.in
deleted file mode 100644
index 75f85632e..000000000
--- a/src/Makefile.in
+++ /dev/null
@@ -1,1238 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-sbin_PROGRAMS = netdata$(EXEEXT)
-plugins_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
-@ENABLE_PLUGIN_APPS_TRUE@am__append_1 = apps.plugin
-@ENABLE_PLUGIN_FREEIPMI_TRUE@am__append_2 = freeipmi.plugin
-@ENABLE_PLUGIN_CGROUP_NETWORK_TRUE@am__append_3 = cgroup-network
-@FREEBSD_TRUE@am__append_4 = \
-@FREEBSD_TRUE@ plugin_freebsd.c \
-@FREEBSD_TRUE@ plugin_freebsd.h \
-@FREEBSD_TRUE@ freebsd_sysctl.c \
-@FREEBSD_TRUE@ freebsd_getmntinfo.c \
-@FREEBSD_TRUE@ freebsd_getifaddrs.c \
-@FREEBSD_TRUE@ freebsd_devstat.c \
-@FREEBSD_TRUE@ zfs_common.c \
-@FREEBSD_TRUE@ zfs_common.h \
-@FREEBSD_TRUE@ freebsd_kstat_zfs.c \
-@FREEBSD_TRUE@ freebsd_ipfw.c \
-@FREEBSD_TRUE@ $(NULL)
-
-@FREEBSD_FALSE@@MACOS_TRUE@am__append_5 = \
-@FREEBSD_FALSE@@MACOS_TRUE@ plugin_macos.c \
-@FREEBSD_FALSE@@MACOS_TRUE@ plugin_macos.h \
-@FREEBSD_FALSE@@MACOS_TRUE@ macos_sysctl.c \
-@FREEBSD_FALSE@@MACOS_TRUE@ macos_mach_smi.c \
-@FREEBSD_FALSE@@MACOS_TRUE@ macos_fw.c \
-@FREEBSD_FALSE@@MACOS_TRUE@ $(NULL)
-
-@FREEBSD_FALSE@@MACOS_FALSE@am__append_6 = \
-@FREEBSD_FALSE@@MACOS_FALSE@ ipc.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ ipc.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_nfacct.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_nfacct.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_tc.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_tc.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_diskstats.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_interrupts.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_softirqs.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_loadavg.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_meminfo.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_dev.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_ip_vs_stats.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_netstat.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfs.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfsd.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp6.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat6.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_softnet_stat.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_conntrack.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_synproxy.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_self_mountinfo.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_self_mountinfo.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ zfs_common.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ zfs_common.h \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_spl_kstat_zfs.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_stat.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_sys_kernel_random_entropy_avail.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_vmstat.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_uptime.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_kernel_mm_ksm.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_edac_mc.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_node.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_cgroup.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_btrfs.c \
-@FREEBSD_FALSE@@MACOS_FALSE@ $(NULL)
-
-@FREEBSD_TRUE@am__append_7 = \
-@FREEBSD_TRUE@ plugin_freebsd.h \
-@FREEBSD_TRUE@ $(NULL)
-
-@FREEBSD_FALSE@am__append_8 = \
-@FREEBSD_FALSE@ adaptive_resortable_list.c \
-@FREEBSD_FALSE@ adaptive_resortable_list.h \
-@FREEBSD_FALSE@ $(NULL)
-
-subdir = src
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/depcomp $(dist_cache_DATA) $(dist_log_DATA) \
- $(dist_registry_DATA) $(dist_varlib_DATA)
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___atomic.m4 \
- $(top_srcdir)/m4/ax_c__generic.m4 $(top_srcdir)/m4/ax_c_lto.m4 \
- $(top_srcdir)/m4/ax_c_mallinfo.m4 \
- $(top_srcdir)/m4/ax_c_mallopt.m4 \
- $(top_srcdir)/m4/ax_check_compile_flag.m4 \
- $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \
- $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/jemalloc.m4 \
- $(top_srcdir)/m4/tcmalloc.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-@ENABLE_PLUGIN_APPS_TRUE@am__EXEEXT_1 = apps.plugin$(EXEEXT)
-@ENABLE_PLUGIN_FREEIPMI_TRUE@am__EXEEXT_2 = freeipmi.plugin$(EXEEXT)
-@ENABLE_PLUGIN_CGROUP_NETWORK_TRUE@am__EXEEXT_3 = \
-@ENABLE_PLUGIN_CGROUP_NETWORK_TRUE@ cgroup-network$(EXEEXT)
-am__installdirs = "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(sbindir)" \
- "$(DESTDIR)$(cachedir)" "$(DESTDIR)$(logdir)" \
- "$(DESTDIR)$(registrydir)" "$(DESTDIR)$(varlibdir)"
-PROGRAMS = $(plugins_PROGRAMS) $(sbin_PROGRAMS)
-am__apps_plugin_SOURCES_DIST = apps_plugin.c avl.c avl.h clocks.c \
- clocks.h common.c common.h inlined.h locks.c locks.h log.c \
- log.h procfile.c procfile.h threads.c threads.h web_buffer.c \
- web_buffer.h plugin_freebsd.h adaptive_resortable_list.c \
- adaptive_resortable_list.h
-am__objects_1 =
-@FREEBSD_FALSE@am__objects_2 = adaptive_resortable_list.$(OBJEXT)
-am_apps_plugin_OBJECTS = apps_plugin.$(OBJEXT) avl.$(OBJEXT) \
- clocks.$(OBJEXT) common.$(OBJEXT) locks.$(OBJEXT) \
- log.$(OBJEXT) procfile.$(OBJEXT) threads.$(OBJEXT) \
- web_buffer.$(OBJEXT) $(am__objects_1) $(am__objects_2)
-apps_plugin_OBJECTS = $(am_apps_plugin_OBJECTS)
-am__DEPENDENCIES_1 =
-apps_plugin_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-am_cgroup_network_OBJECTS = cgroup-network.$(OBJEXT) clocks.$(OBJEXT) \
- common.$(OBJEXT) locks.$(OBJEXT) log.$(OBJEXT) \
- procfile.$(OBJEXT) popen.$(OBJEXT) signals.$(OBJEXT) \
- threads.$(OBJEXT)
-cgroup_network_OBJECTS = $(am_cgroup_network_OBJECTS)
-cgroup_network_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
-am_freeipmi_plugin_OBJECTS = freeipmi_plugin.$(OBJEXT) \
- clocks.$(OBJEXT) common.$(OBJEXT) locks.$(OBJEXT) \
- log.$(OBJEXT) procfile.$(OBJEXT) threads.$(OBJEXT)
-freeipmi_plugin_OBJECTS = $(am_freeipmi_plugin_OBJECTS)
-freeipmi_plugin_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am__netdata_SOURCES_DIST = adaptive_resortable_list.c \
- adaptive_resortable_list.h appconfig.c appconfig.h avl.c avl.h \
- backend_prometheus.c backend_prometheus.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 locks.c \
- locks.h log.c log.h main.c main.h plugin_checks.c \
- plugin_checks.h plugin_idlejitter.c plugin_idlejitter.h \
- plugins_d.c plugins_d.h popen.c popen.h procfile.c procfile.h \
- registry.c registry.h registry_db.c registry_init.c \
- registry_internals.c registry_internals.h registry_log.c \
- 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 rrdsetvar.c rrdvar.c \
- signals.c signals.h simple_pattern.c simple_pattern.h socket.c \
- socket.h statistical.c statistical.h statsd.c statsd.h \
- storage_number.c storage_number.h threads.c threads.h \
- 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 plugin_freebsd.c \
- plugin_freebsd.h freebsd_sysctl.c freebsd_getmntinfo.c \
- freebsd_getifaddrs.c freebsd_devstat.c zfs_common.c \
- zfs_common.h freebsd_kstat_zfs.c freebsd_ipfw.c plugin_macos.c \
- plugin_macos.h macos_sysctl.c macos_mach_smi.c macos_fw.c \
- ipc.c ipc.h plugin_nfacct.c plugin_nfacct.h plugin_proc.c \
- plugin_proc.h plugin_proc_diskspace.c plugin_proc_diskspace.h \
- plugin_tc.c plugin_tc.h proc_diskstats.c proc_interrupts.c \
- proc_softirqs.c proc_loadavg.c proc_meminfo.c proc_net_dev.c \
- proc_net_ip_vs_stats.c proc_net_netstat.c proc_net_rpc_nfs.c \
- proc_net_rpc_nfsd.c proc_net_snmp.c proc_net_snmp6.c \
- proc_net_sockstat.c proc_net_sockstat6.c \
- proc_net_softnet_stat.c proc_net_stat_conntrack.c \
- proc_net_stat_synproxy.c proc_self_mountinfo.c \
- proc_self_mountinfo.h proc_spl_kstat_zfs.c proc_stat.c \
- proc_sys_kernel_random_entropy_avail.c proc_vmstat.c \
- proc_uptime.c sys_kernel_mm_ksm.c sys_devices_system_edac_mc.c \
- sys_devices_system_node.c sys_fs_cgroup.c sys_fs_btrfs.c
-@FREEBSD_TRUE@am__objects_3 = plugin_freebsd.$(OBJEXT) \
-@FREEBSD_TRUE@ freebsd_sysctl.$(OBJEXT) \
-@FREEBSD_TRUE@ freebsd_getmntinfo.$(OBJEXT) \
-@FREEBSD_TRUE@ freebsd_getifaddrs.$(OBJEXT) \
-@FREEBSD_TRUE@ freebsd_devstat.$(OBJEXT) zfs_common.$(OBJEXT) \
-@FREEBSD_TRUE@ freebsd_kstat_zfs.$(OBJEXT) \
-@FREEBSD_TRUE@ freebsd_ipfw.$(OBJEXT)
-@FREEBSD_FALSE@@MACOS_TRUE@am__objects_4 = plugin_macos.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_TRUE@ macos_sysctl.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_TRUE@ macos_mach_smi.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_TRUE@ macos_fw.$(OBJEXT)
-@FREEBSD_FALSE@@MACOS_FALSE@am__objects_5 = ipc.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_nfacct.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_proc_diskspace.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ plugin_tc.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_diskstats.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_interrupts.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_softirqs.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_loadavg.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_meminfo.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_dev.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_ip_vs_stats.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_netstat.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfs.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_rpc_nfsd.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_snmp6.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_sockstat6.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_softnet_stat.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_conntrack.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_net_stat_synproxy.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_self_mountinfo.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ zfs_common.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_spl_kstat_zfs.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_stat.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_sys_kernel_random_entropy_avail.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_vmstat.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ proc_uptime.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_kernel_mm_ksm.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_edac_mc.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_devices_system_node.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_cgroup.$(OBJEXT) \
-@FREEBSD_FALSE@@MACOS_FALSE@ sys_fs_btrfs.$(OBJEXT)
-am_netdata_OBJECTS = adaptive_resortable_list.$(OBJEXT) \
- appconfig.$(OBJEXT) avl.$(OBJEXT) backend_prometheus.$(OBJEXT) \
- backends.$(OBJEXT) clocks.$(OBJEXT) common.$(OBJEXT) \
- daemon.$(OBJEXT) dictionary.$(OBJEXT) eval.$(OBJEXT) \
- global_statistics.$(OBJEXT) health.$(OBJEXT) \
- health_config.$(OBJEXT) health_json.$(OBJEXT) \
- health_log.$(OBJEXT) locks.$(OBJEXT) log.$(OBJEXT) \
- main.$(OBJEXT) plugin_checks.$(OBJEXT) \
- plugin_idlejitter.$(OBJEXT) plugins_d.$(OBJEXT) \
- popen.$(OBJEXT) procfile.$(OBJEXT) registry.$(OBJEXT) \
- registry_db.$(OBJEXT) registry_init.$(OBJEXT) \
- registry_internals.$(OBJEXT) registry_log.$(OBJEXT) \
- registry_machine.$(OBJEXT) registry_person.$(OBJEXT) \
- registry_url.$(OBJEXT) rrd.$(OBJEXT) rrd2json.$(OBJEXT) \
- rrd2json_api_old.$(OBJEXT) rrdcalc.$(OBJEXT) \
- rrdcalctemplate.$(OBJEXT) rrddim.$(OBJEXT) rrddimvar.$(OBJEXT) \
- rrdfamily.$(OBJEXT) rrdhost.$(OBJEXT) rrdpush.$(OBJEXT) \
- rrdset.$(OBJEXT) rrdsetvar.$(OBJEXT) rrdvar.$(OBJEXT) \
- signals.$(OBJEXT) simple_pattern.$(OBJEXT) socket.$(OBJEXT) \
- statistical.$(OBJEXT) statsd.$(OBJEXT) \
- storage_number.$(OBJEXT) threads.$(OBJEXT) unit_test.$(OBJEXT) \
- url.$(OBJEXT) web_api_old.$(OBJEXT) web_api_v1.$(OBJEXT) \
- web_buffer.$(OBJEXT) web_buffer_svg.$(OBJEXT) \
- web_client.$(OBJEXT) web_server.$(OBJEXT) $(am__objects_3) \
- $(am__objects_4) $(am__objects_5)
-netdata_OBJECTS = $(am_netdata_OBJECTS)
-netdata_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(apps_plugin_SOURCES) $(cgroup_network_SOURCES) \
- $(freeipmi_plugin_SOURCES) $(netdata_SOURCES)
-DIST_SOURCES = $(am__apps_plugin_SOURCES_DIST) \
- $(cgroup_network_SOURCES) $(freeipmi_plugin_SOURCES) \
- $(am__netdata_SOURCES_DIST)
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-DATA = $(dist_cache_DATA) $(dist_log_DATA) $(dist_registry_DATA) \
- $(dist_varlib_DATA)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-IPMIMONITORING_CFLAGS = @IPMIMONITORING_CFLAGS@
-IPMIMONITORING_LIBS = @IPMIMONITORING_LIBS@
-LDFLAGS = @LDFLAGS@
-LIBCAP_CFLAGS = @LIBCAP_CFLAGS@
-LIBCAP_LIBS = @LIBCAP_LIBS@
-LIBMNL_CFLAGS = @LIBMNL_CFLAGS@
-LIBMNL_LIBS = @LIBMNL_LIBS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MATH_CFLAGS = @MATH_CFLAGS@
-MATH_LIBS = @MATH_LIBS@
-MKDIR_P = @MKDIR_P@
-NFACCT_CFLAGS = @NFACCT_CFLAGS@
-NFACCT_LIBS = @NFACCT_LIBS@
-OBJEXT = @OBJEXT@
-OPTIONAL_IPMIMONITORING_CFLAGS = @OPTIONAL_IPMIMONITORING_CFLAGS@
-OPTIONAL_IPMIMONITORING_LIBS = @OPTIONAL_IPMIMONITORING_LIBS@
-OPTIONAL_LIBCAP_CFLAGS = @OPTIONAL_LIBCAP_CFLAGS@
-OPTIONAL_LIBCAP_LIBS = @OPTIONAL_LIBCAP_LIBS@
-OPTIONAL_MATH_CLFAGS = @OPTIONAL_MATH_CLFAGS@
-OPTIONAL_MATH_LIBS = @OPTIONAL_MATH_LIBS@
-OPTIONAL_NFACCT_CLFAGS = @OPTIONAL_NFACCT_CLFAGS@
-OPTIONAL_NFACCT_LIBS = @OPTIONAL_NFACCT_LIBS@
-OPTIONAL_UUID_CLFAGS = @OPTIONAL_UUID_CLFAGS@
-OPTIONAL_UUID_LIBS = @OPTIONAL_UUID_LIBS@
-OPTIONAL_ZLIB_CLFAGS = @OPTIONAL_ZLIB_CLFAGS@
-OPTIONAL_ZLIB_LIBS = @OPTIONAL_ZLIB_LIBS@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_RPM_RELEASE = @PACKAGE_RPM_RELEASE@
-PACKAGE_RPM_VERSION = @PACKAGE_RPM_VERSION@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PTHREAD_CC = @PTHREAD_CC@
-PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
-PTHREAD_LIBS = @PTHREAD_LIBS@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SSE_CANDIDATE = @SSE_CANDIDATE@
-STRIP = @STRIP@
-UUID_CFLAGS = @UUID_CFLAGS@
-UUID_LIBS = @UUID_LIBS@
-VERSION = @VERSION@
-ZLIB_CFLAGS = @ZLIB_CFLAGS@
-ZLIB_LIBS = @ZLIB_LIBS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-ax_pthread_config = @ax_pthread_config@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-cachedir = @cachedir@
-chartsdir = @chartsdir@
-configdir = @configdir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-has_jemalloc = @has_jemalloc@
-has_tcmalloc = @has_tcmalloc@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-logdir = @logdir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-nodedir = @nodedir@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pluginsdir = @pluginsdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pythondir = @pythondir@
-registrydir = @registrydir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-varlibdir = @varlibdir@
-webdir = @webdir@
-
-#
-# Copyright (C) 2015 Alon Bar-Lev <alon.barlev@gmail.com>
-#
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
-AM_CPPFLAGS = \
- -DVARLIB_DIR="\"$(varlibdir)\"" \
- -DCACHE_DIR="\"$(cachedir)\"" \
- -DCONFIG_DIR="\"$(configdir)\"" \
- -DLOG_DIR="\"$(logdir)\"" \
- -DPLUGINS_DIR="\"$(pluginsdir)\"" \
- -DRUN_DIR="\"$(localstatedir)/run/netdata\"" \
- -DWEB_DIR="\"$(webdir)\"" \
- $(NULL)
-
-AM_CFLAGS = \
- $(OPTIONAL_MATH_CFLAGS) \
- $(OPTIONAL_NFACCT_CLFAGS) \
- $(OPTIONAL_ZLIB_CFLAGS) \
- $(OPTIONAL_UUID_CFLAGS) \
- $(OPTIONAL_LIBCAP_CFLAGS) \
- $(OPTIONAL_IPMIMONITORING_CFLAGS)\
- $(NULL)
-
-dist_cache_DATA = .keep
-dist_varlib_DATA = .keep
-dist_registry_DATA = .keep
-dist_log_DATA = .keep
-netdata_SOURCES = adaptive_resortable_list.c \
- adaptive_resortable_list.h appconfig.c appconfig.h avl.c avl.h \
- backend_prometheus.c backend_prometheus.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 locks.c \
- locks.h log.c log.h main.c main.h plugin_checks.c \
- plugin_checks.h plugin_idlejitter.c plugin_idlejitter.h \
- plugins_d.c plugins_d.h popen.c popen.h procfile.c procfile.h \
- registry.c registry.h registry_db.c registry_init.c \
- registry_internals.c registry_internals.h registry_log.c \
- 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 rrdsetvar.c rrdvar.c \
- signals.c signals.h simple_pattern.c simple_pattern.h socket.c \
- socket.h statistical.c statistical.h statsd.c statsd.h \
- storage_number.c storage_number.h threads.c threads.h \
- 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 $(NULL) $(am__append_4) \
- $(am__append_5) $(am__append_6)
-netdata_LDADD = \
- $(OPTIONAL_MATH_LIBS) \
- $(OPTIONAL_NFACCT_LIBS) \
- $(OPTIONAL_ZLIB_LIBS) \
- $(OPTIONAL_UUID_LIBS) \
- $(NULL)
-
-apps_plugin_SOURCES = apps_plugin.c avl.c avl.h clocks.c clocks.h \
- common.c common.h inlined.h locks.c locks.h log.c log.h \
- procfile.c procfile.h threads.c threads.h web_buffer.c \
- web_buffer.h $(NULL) $(am__append_7) $(am__append_8)
-apps_plugin_LDADD = \
- $(OPTIONAL_MATH_LIBS) \
- $(OPTIONAL_LIBCAP_LIBS) \
- $(NULL)
-
-freeipmi_plugin_SOURCES = \
- freeipmi_plugin.c \
- clocks.c \
- clocks.h \
- common.c \
- common.h \
- inlined.h \
- locks.c \
- locks.h \
- log.c log.h \
- procfile.c \
- procfile.h \
- threads.c \
- threads.h \
- $(NULL)
-
-freeipmi_plugin_LDADD = \
- $(OPTIONAL_IPMIMONITORING_LIBS) \
- $(NULL)
-
-cgroup_network_SOURCES = \
- cgroup-network.c \
- clocks.c \
- clocks.h \
- common.c \
- common.h \
- inlined.h \
- locks.c \
- locks.h \
- log.c \
- log.h \
- procfile.c \
- procfile.h \
- popen.c \
- popen.h \
- signals.c \
- signals.h \
- threads.c \
- threads.h \
- $(NULL)
-
-cgroup_network_LDADD = \
- $(OPTIONAL_MATH_LIBS) \
- $(OPTIONAL_LIBCAP_LIBS) \
- $(NULL)
-
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-install-pluginsPROGRAMS: $(plugins_PROGRAMS)
- @$(NORMAL_INSTALL)
- @list='$(plugins_PROGRAMS)'; test -n "$(pluginsdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(pluginsdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(pluginsdir)" || exit 1; \
- fi; \
- for p in $$list; do echo "$$p $$p"; done | \
- sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p \
- ; then echo "$$p"; echo "$$p"; else :; fi; \
- done | \
- sed -e 'p;s,.*/,,;n;h' \
- -e 's|.*|.|' \
- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
- sed 'N;N;N;s,\n, ,g' | \
- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
- if ($$2 == $$4) files[d] = files[d] " " $$1; \
- else { print "f", $$3 "/" $$4, $$1; } } \
- END { for (d in files) print "f", d, files[d] }' | \
- while read type dir files; do \
- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
- test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(pluginsdir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(pluginsdir)$$dir" || exit $$?; \
- } \
- ; done
-
-uninstall-pluginsPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(plugins_PROGRAMS)'; test -n "$(pluginsdir)" || list=; \
- files=`for p in $$list; do echo "$$p"; done | \
- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' \
- `; \
- test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(pluginsdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(pluginsdir)" && rm -f $$files
-
-clean-pluginsPROGRAMS:
- -test -z "$(plugins_PROGRAMS)" || rm -f $(plugins_PROGRAMS)
-install-sbinPROGRAMS: $(sbin_PROGRAMS)
- @$(NORMAL_INSTALL)
- @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
- fi; \
- for p in $$list; do echo "$$p $$p"; done | \
- sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p \
- ; then echo "$$p"; echo "$$p"; else :; fi; \
- done | \
- sed -e 'p;s,.*/,,;n;h' \
- -e 's|.*|.|' \
- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
- sed 'N;N;N;s,\n, ,g' | \
- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
- if ($$2 == $$4) files[d] = files[d] " " $$1; \
- else { print "f", $$3 "/" $$4, $$1; } } \
- END { for (d in files) print "f", d, files[d] }' | \
- while read type dir files; do \
- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
- test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
- } \
- ; done
-
-uninstall-sbinPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
- files=`for p in $$list; do echo "$$p"; done | \
- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' \
- `; \
- test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(sbindir)" && rm -f $$files
-
-clean-sbinPROGRAMS:
- -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
-
-apps.plugin$(EXEEXT): $(apps_plugin_OBJECTS) $(apps_plugin_DEPENDENCIES) $(EXTRA_apps_plugin_DEPENDENCIES)
- @rm -f apps.plugin$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(apps_plugin_OBJECTS) $(apps_plugin_LDADD) $(LIBS)
-
-cgroup-network$(EXEEXT): $(cgroup_network_OBJECTS) $(cgroup_network_DEPENDENCIES) $(EXTRA_cgroup_network_DEPENDENCIES)
- @rm -f cgroup-network$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(cgroup_network_OBJECTS) $(cgroup_network_LDADD) $(LIBS)
-
-freeipmi.plugin$(EXEEXT): $(freeipmi_plugin_OBJECTS) $(freeipmi_plugin_DEPENDENCIES) $(EXTRA_freeipmi_plugin_DEPENDENCIES)
- @rm -f freeipmi.plugin$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(freeipmi_plugin_OBJECTS) $(freeipmi_plugin_LDADD) $(LIBS)
-
-netdata$(EXEEXT): $(netdata_OBJECTS) $(netdata_DEPENDENCIES) $(EXTRA_netdata_DEPENDENCIES)
- @rm -f netdata$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(netdata_OBJECTS) $(netdata_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adaptive_resortable_list.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/appconfig.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apps_plugin.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avl.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_prometheus.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backends.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgroup-network.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clocks.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dictionary.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_devstat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_getifaddrs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_getmntinfo.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_ipfw.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_kstat_zfs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_sysctl.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freeipmi_plugin.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/global_statistics.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health_config.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health_json.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/health_log.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/locks.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macos_fw.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macos_mach_smi.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macos_sysctl.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_checks.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_freebsd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_idlejitter.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_macos.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_nfacct.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_proc.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_proc_diskspace.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_tc.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugins_d.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/popen.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_diskstats.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_interrupts.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_loadavg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_meminfo.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_dev.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_ip_vs_stats.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_netstat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_rpc_nfs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_rpc_nfsd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_snmp.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_snmp6.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_sockstat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_sockstat6.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_softnet_stat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_stat_conntrack.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_net_stat_synproxy.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_self_mountinfo.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_softirqs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_spl_kstat_zfs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_stat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_sys_kernel_random_entropy_avail.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_uptime.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_vmstat.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procfile.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_db.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_init.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_internals.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_log.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_machine.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_person.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry_url.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrd2json.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrd2json_api_old.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdcalc.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdcalctemplate.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrddim.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrddimvar.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdfamily.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdhost.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdpush.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdset.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdsetvar.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdvar.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signals.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple_pattern.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistical.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statsd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage_number.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_devices_system_edac_mc.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_devices_system_node.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_fs_btrfs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_fs_cgroup.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_kernel_mm_ksm.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threads.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_test.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/url.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_api_old.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_api_v1.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_buffer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_buffer_svg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_client.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_server.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_common.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-install-dist_cacheDATA: $(dist_cache_DATA)
- @$(NORMAL_INSTALL)
- @list='$(dist_cache_DATA)'; test -n "$(cachedir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(cachedir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(cachedir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(cachedir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(cachedir)" || exit $$?; \
- done
-
-uninstall-dist_cacheDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_cache_DATA)'; test -n "$(cachedir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(cachedir)'; $(am__uninstall_files_from_dir)
-install-dist_logDATA: $(dist_log_DATA)
- @$(NORMAL_INSTALL)
- @list='$(dist_log_DATA)'; test -n "$(logdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(logdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(logdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(logdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(logdir)" || exit $$?; \
- done
-
-uninstall-dist_logDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_log_DATA)'; test -n "$(logdir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(logdir)'; $(am__uninstall_files_from_dir)
-install-dist_registryDATA: $(dist_registry_DATA)
- @$(NORMAL_INSTALL)
- @list='$(dist_registry_DATA)'; test -n "$(registrydir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(registrydir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(registrydir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(registrydir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(registrydir)" || exit $$?; \
- done
-
-uninstall-dist_registryDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_registry_DATA)'; test -n "$(registrydir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(registrydir)'; $(am__uninstall_files_from_dir)
-install-dist_varlibDATA: $(dist_varlib_DATA)
- @$(NORMAL_INSTALL)
- @list='$(dist_varlib_DATA)'; test -n "$(varlibdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(varlibdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(varlibdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(varlibdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(varlibdir)" || exit $$?; \
- done
-
-uninstall-dist_varlibDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_varlib_DATA)'; test -n "$(varlibdir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(varlibdir)'; $(am__uninstall_files_from_dir)
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(PROGRAMS) $(DATA)
-installdirs:
- for dir in "$(DESTDIR)$(pluginsdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(cachedir)" "$(DESTDIR)$(logdir)" "$(DESTDIR)$(registrydir)" "$(DESTDIR)$(varlibdir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
- -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-clean: clean-am
-
-clean-am: clean-generic clean-pluginsPROGRAMS clean-sbinPROGRAMS \
- mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-dist_cacheDATA install-dist_logDATA \
- install-dist_registryDATA install-dist_varlibDATA \
- install-pluginsPROGRAMS
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am: install-sbinPROGRAMS
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-dist_cacheDATA uninstall-dist_logDATA \
- uninstall-dist_registryDATA uninstall-dist_varlibDATA \
- uninstall-pluginsPROGRAMS uninstall-sbinPROGRAMS
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
- clean-pluginsPROGRAMS clean-sbinPROGRAMS cscopelist-am ctags \
- ctags-am distclean distclean-compile distclean-generic \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am \
- install-dist_cacheDATA install-dist_logDATA \
- install-dist_registryDATA install-dist_varlibDATA install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-pluginsPROGRAMS install-ps \
- install-ps-am install-sbinPROGRAMS install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
- uninstall-am uninstall-dist_cacheDATA uninstall-dist_logDATA \
- uninstall-dist_registryDATA uninstall-dist_varlibDATA \
- uninstall-pluginsPROGRAMS uninstall-sbinPROGRAMS
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/src/adaptive_resortable_list.c b/src/adaptive_resortable_list.c
deleted file mode 100644
index c564efff3..000000000
--- a/src/adaptive_resortable_list.c
+++ /dev/null
@@ -1,269 +0,0 @@
-#include "adaptive_resortable_list.h"
-
-// the default processor() of the ARL
-// can be overwritten at arl_create()
-inline void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name;
- (void)hash;
-
- register unsigned long long *d = dst;
- *d = str2ull(value);
- // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d);
-}
-
-inline void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name;
- (void)hash;
-
- register kernel_uint_t *d = dst;
- *d = str2kernel_uint_t(value);
- // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, (unsigned long long)*d);
-}
-
-// create a new ARL
-ARL_BASE *arl_create(const char *name, void (*processor)(const char *, uint32_t, const char *, void *), size_t rechecks) {
- ARL_BASE *base = callocz(1, sizeof(ARL_BASE));
-
- base->name = strdupz(name);
-
- if(!processor)
- base->processor = arl_callback_str2ull;
- else
- base->processor = processor;
-
- base->rechecks = rechecks;
-
- return base;
-}
-
-void arl_free(ARL_BASE *arl_base) {
- if(unlikely(!arl_base))
- return;
-
- while(arl_base->head) {
- ARL_ENTRY *e = arl_base->head;
- arl_base->head = e->next;
-
- freez(e->name);
-#ifdef NETDATA_INTERNAL_CHECKS
- memset(e, 0, sizeof(ARL_ENTRY));
-#endif
- freez(e);
- }
-
- freez(arl_base->name);
-
-#ifdef NETDATA_INTERNAL_CHECKS
- memset(arl_base, 0, sizeof(ARL_BASE));
-#endif
-
- freez(arl_base);
-}
-
-void arl_begin(ARL_BASE *base) {
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(likely(base->iteration > 10)) {
- // do these checks after the ARL has been sorted
-
- if(unlikely(base->relinkings > (base->expected + base->allocated)))
- info("ARL '%s' has %zu relinkings with %zu expected and %zu allocated entries. Is the source changing so fast?"
- , base->name, base->relinkings, base->expected, base->allocated);
-
- if(unlikely(base->slow > base->fast))
- info("ARL '%s' has %zu fast searches and %zu slow searches. Is the source really changing so fast?"
- , base->name, base->fast, base->slow);
-
- /*
- if(unlikely(base->iteration % 60 == 0)) {
- info("ARL '%s' statistics: iteration %zu, expected %zu, wanted %zu, allocated %zu, fred %zu, relinkings %zu, found %zu, added %zu, fast %zu, slow %zu"
- , base->name
- , base->iteration
- , base->expected
- , base->wanted
- , base->allocated
- , base->fred
- , base->relinkings
- , base->found
- , base->added
- , base->fast
- , base->slow
- );
- // for(e = base->head; e; e = e->next) fprintf(stderr, "%s ", e->name);
- // fprintf(stderr, "\n");
- }
- */
- }
-#endif
-
- if(unlikely(base->iteration > 0 && (base->added || (base->iteration % base->rechecks) == 0))) {
- int wanted_equals_expected = ((base->iteration % base->rechecks) == 0);
-
- // fprintf(stderr, "\n\narl_begin() rechecking, added %zu, iteration %zu, rechecks %zu, wanted_equals_expected %d\n\n\n", base->added, base->iteration, base->rechecks, wanted_equals_expected);
-
- base->added = 0;
- base->wanted = (wanted_equals_expected)?base->expected:0;
-
- ARL_ENTRY *e = base->head;
- while(e) {
- if(e->flags & ARL_ENTRY_FLAG_FOUND) {
-
- // remove the found flag
- e->flags &= ~ARL_ENTRY_FLAG_FOUND;
-
- // count it in wanted
- if(!wanted_equals_expected && e->flags & ARL_ENTRY_FLAG_EXPECTED)
- base->wanted++;
-
- }
- else if(e->flags & ARL_ENTRY_FLAG_DYNAMIC && !(base->head == e && !e->next)) { // not last entry
- // we can remove this entry
- // it is not found, and it was created because
- // it was found in the source file
-
- // remember the next one
- ARL_ENTRY *t = e->next;
-
- // remove it from the list
- if(e->next) e->next->prev = e->prev;
- if(e->prev) e->prev->next = e->next;
- if(base->head == e) base->head = e->next;
-
- // free it
- freez(e->name);
- freez(e);
-
- // count it
- base->fred++;
-
- // continue
- e = t;
- continue;
- }
-
- e = e->next;
- }
- }
-
- if(unlikely(!base->head)) {
- // hm... no nodes at all in the list #1700
- // add a fake one to prevent a crash
- // this is better than checking for the existence of nodes all the time
- arl_expect(base, "a-really-not-existing-source-keyword", NULL);
- }
-
- base->iteration++;
- base->next_keyword = base->head;
- base->found = 0;
-
-}
-
-// register an expected keyword to the ARL
-// together with its destination ( i.e. the output of the processor() )
-ARL_ENTRY *arl_expect_custom(ARL_BASE *base, const char *keyword, void (*processor)(const char *name, uint32_t hash, const char *value, void *dst), void *dst) {
- ARL_ENTRY *e = callocz(1, sizeof(ARL_ENTRY));
- e->name = strdupz(keyword);
- e->hash = simple_hash(e->name);
- e->processor = (processor)?processor:base->processor;
- e->dst = dst;
- e->flags = ARL_ENTRY_FLAG_EXPECTED;
- e->prev = NULL;
- e->next = base->head;
-
- if(base->head) base->head->prev = e;
- else base->next_keyword = e;
-
- base->head = e;
- base->expected++;
- base->allocated++;
-
- base->wanted = base->expected;
-
- return e;
-}
-
-int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *value) {
- ARL_ENTRY *e;
-
- uint32_t hash = simple_hash(s);
-
- // find if it already exists in the data
- for(e = base->head; e ; e = e->next)
- if(e->hash == hash && !strcmp(e->name, s))
- break;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(base->next_keyword && e == base->next_keyword))
- fatal("Internal Error: e == base->last");
-#endif
-
- if(e) {
- // found it in the keywords
-
- base->relinkings++;
-
- // run the processor for it
- if(unlikely(e->dst)) {
- e->processor(e->name, hash, value, e->dst);
- base->found++;
- }
-
- // unlink it - we will relink it below
- if(e->next) e->next->prev = e->prev;
- if(e->prev) e->prev->next = e->next;
-
- // make sure the head is properly linked
- if(base->head == e)
- base->head = e->next;
- }
- else {
- // not found
-
- // create it
- e = callocz(1, sizeof(ARL_ENTRY));
- e->name = strdupz(s);
- e->hash = hash;
- e->flags = ARL_ENTRY_FLAG_DYNAMIC;
-
- base->allocated++;
- base->added++;
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(base->iteration % 60 == 0 && e->flags & ARL_ENTRY_FLAG_FOUND))
- info("ARL '%s': entry '%s' is already found. Did you forget to call arl_begin()?", base->name, s);
-#endif
-
- e->flags |= ARL_ENTRY_FLAG_FOUND;
-
- // link it here
- e->next = base->next_keyword;
- if(base->next_keyword) {
- e->prev = base->next_keyword->prev;
- base->next_keyword->prev = e;
-
- if(e->prev)
- e->prev->next = e;
-
- if(base->head == base->next_keyword)
- base->head = e;
- }
- else {
- e->prev = NULL;
-
- if(!base->head)
- base->head = e;
- }
-
- // prepare the next iteration
- base->next_keyword = e->next;
- if(unlikely(!base->next_keyword))
- base->next_keyword = base->head;
-
- if(unlikely(base->found == base->wanted)) {
- // fprintf(stderr, "FOUND ALL WANTED 1: found = %zu, wanted = %zu, expected %zu\n", base->found, base->wanted, base->expected);
- return 1;
- }
-
- return 0;
-}
diff --git a/src/adaptive_resortable_list.h b/src/adaptive_resortable_list.h
deleted file mode 100644
index d05a8ede7..000000000
--- a/src/adaptive_resortable_list.h
+++ /dev/null
@@ -1,171 +0,0 @@
-#ifndef NETDATA_ADAPTIVE_RESORTABLE_LIST_H
-#define NETDATA_ADAPTIVE_RESORTABLE_LIST_H
-
-/*
- * ADAPTIVE RE-SORTABLE LIST
- * This structure allows netdata to read a file of NAME VALUE lines
- * in the fastest possible way.
- *
- * It maintains a linked list of all NAME (keywords), sorted in the
- * same order as found in the source data file.
- * The linked list is kept sorted at all times - the source file
- * may change at any time, the list will adapt.
- *
- * The caller:
- *
- * 1. calls arl_create() to create a list
- *
- * 2. calls arl_expect() to register the expected keyword
- *
- * Then:
- *
- * 3. calls arl_begin() to initiate a data collection iteration.
- * This is to be called just ONCE every time the source is re-scanned.
- *
- * 4. calls arl_check() for each line read from the file.
- *
- * Finally:
- *
- * 5. calls arl_free() to destroy this and free all memory.
- *
- * The program will call the processor() function, given to
- * arl_create(), for each expected keyword found.
- * The default processor() expects dst to be an unsigned long long *.
- *
- * LIMITATIONS
- * DO NOT USE THIS IF THE A NAME/KEYWORD MAY APPEAR MORE THAN
- * ONCE IN THE SOURCE DATA SET.
- */
-
-#include "common.h"
-
-#define ARL_ENTRY_FLAG_FOUND 0x01 // the entry has been found in the source data
-#define ARL_ENTRY_FLAG_EXPECTED 0x02 // the entry is expected by the program
-#define ARL_ENTRY_FLAG_DYNAMIC 0x04 // the entry was dynamically allocated, from source data
-
-typedef struct arl_entry {
- char *name; // the keywords
- uint32_t hash; // the hash of the keyword
-
- void *dst; // the dst to pass to the processor
-
- uint8_t flags; // ARL_ENTRY_FLAG_*
-
- // the processor to do the job
- void (*processor)(const char *name, uint32_t hash, const char *value, void *dst);
-
- // double linked list for fast re-linkings
- struct arl_entry *prev, *next;
-} ARL_ENTRY;
-
-typedef struct arl_base {
- char *name;
-
- size_t iteration; // incremented on each iteration (arl_begin())
- size_t found; // the number of expected keywords found in this iteration
- size_t expected; // the number of expected keywords
- size_t wanted; // the number of wanted keywords
- // i.e. the number of keywords found and expected
-
- size_t relinkings; // the number of relinkings we have made so far
-
- size_t allocated; // the number of keywords allocated
- size_t fred; // the number of keywords cleaned up
-
- size_t rechecks; // the number of iterations between re-checks of the
- // wanted number of keywords
- // this is only needed in cases where the source
- // is having less lines over time.
-
- size_t added; // it is non-zero if new keywords have been added
- // this is only needed to detect new lines have
- // been added to the file, over time.
-
-#ifdef NETDATA_INTERNAL_CHECKS
- size_t fast; // the number of times we have taken the fast path
- size_t slow; // the number of times we have taken the slow path
-#endif
-
- // the processor to do the job
- void (*processor)(const char *name, uint32_t hash, const char *value, void *dst);
-
- // the linked list of the keywords
- ARL_ENTRY *head;
-
- // since we keep the list of keywords sorted (as found in the source data)
- // this is next keyword that we expect to find in the source data.
- ARL_ENTRY *next_keyword;
-} ARL_BASE;
-
-// create a new ARL
-extern ARL_BASE *arl_create(const char *name, void (*processor)(const char *, uint32_t, const char *, void *), size_t rechecks);
-
-// free an ARL
-extern void arl_free(ARL_BASE *arl_base);
-
-// register an expected keyword to the ARL
-// together with its destination ( i.e. the output of the processor() )
-extern ARL_ENTRY *arl_expect_custom(ARL_BASE *base, const char *keyword, void (*processor)(const char *name, uint32_t hash, const char *value, void *dst), void *dst);
-#define arl_expect(base, keyword, dst) arl_expect_custom(base, keyword, NULL, dst)
-
-// an internal call to complete the check() call
-extern int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *value);
-
-// begin an ARL iteration
-extern void arl_begin(ARL_BASE *base);
-
-extern void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst);
-extern void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst);
-
-// check a keyword against the ARL
-// this is to be called for each keyword read from source data
-// s = the keyword, as collected
-// src = the src data to be passed to the processor
-// it is defined in the header file in order to be inlined
-static inline int arl_check(ARL_BASE *base, const char *keyword, const char *value) {
- ARL_ENTRY *e = base->next_keyword;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely((base->fast + base->slow) % (base->expected + base->allocated) == 0 && (base->fast + base->slow) > (base->expected + base->allocated) * base->iteration))
- info("ARL '%s': Did you forget to call arl_begin()?", base->name);
-#endif
-
- // it should be the first entry (pointed by base->next_keyword)
- if(likely(!strcmp(keyword, e->name))) {
- // it is
-
-#ifdef NETDATA_INTERNAL_CHECKS
- base->fast++;
-#endif
-
- e->flags |= ARL_ENTRY_FLAG_FOUND;
-
- // execute the processor
- if(unlikely(e->dst)) {
- e->processor(e->name, e->hash, value, e->dst);
- base->found++;
- }
-
- // be prepared for the next iteration
- base->next_keyword = e->next;
- if(unlikely(!base->next_keyword))
- base->next_keyword = base->head;
-
- // stop if we collected all the values for this iteration
- if(unlikely(base->found == base->wanted)) {
- // fprintf(stderr, "FOUND ALL WANTED 2: found = %zu, wanted = %zu, expected %zu\n", base->found, base->wanted, base->expected);
- return 1;
- }
-
- return 0;
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- base->slow++;
-#endif
-
- // we read from source, a not-expected keyword
- return arl_find_or_create_and_relink(base, keyword, value);
-}
-
-#endif //NETDATA_ADAPTIVE_RESORTABLE_LIST_H
diff --git a/src/appconfig.c b/src/appconfig.c
deleted file mode 100644
index 2424864b5..000000000
--- a/src/appconfig.c
+++ /dev/null
@@ -1,606 +0,0 @@
-#include "common.h"
-
-#define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2)
-
-// ----------------------------------------------------------------------------
-// definitions
-
-#define CONFIG_VALUE_LOADED 0x01 // has been loaded from the config
-#define CONFIG_VALUE_USED 0x02 // has been accessed from the program
-#define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value
-#define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default
-
-struct config_option {
- avl avl; // the index - this has to be first!
-
- uint8_t flags;
- uint32_t hash; // a simple hash to speed up searching
- // we first compare hashes, and only if the hashes are equal we do string comparisons
-
- char *name;
- char *value;
-
- struct config_option *next; // config->mutex protects just this
-};
-
-struct section {
- avl avl;
-
- uint32_t hash; // a simple hash to speed up searching
- // we first compare hashes, and only if the hashes are equal we do string comparisons
-
- char *name;
-
- struct section *next; // gloabl config_mutex protects just this
-
- struct config_option *values;
- avl_tree_lock values_index;
-
- netdata_mutex_t mutex; // this locks only the writers, to ensure atomic updates
- // readers are protected using the rwlock in avl_tree_lock
-};
-
-static int appconfig_section_compare(void *a, void *b);
-
-struct config netdata_config = {
- .sections = NULL,
- .mutex = NETDATA_MUTEX_INITIALIZER,
- .index = {
- { NULL, appconfig_section_compare },
- AVL_LOCK_INITIALIZER
- }
-};
-
-struct config stream_config = {
- .sections = NULL,
- .mutex = NETDATA_MUTEX_INITIALIZER,
- .index = {
- { NULL, appconfig_section_compare },
- AVL_LOCK_INITIALIZER
- }
-};
-
-// ----------------------------------------------------------------------------
-// locking
-
-static inline void appconfig_wrlock(struct config *root) {
- netdata_mutex_lock(&root->mutex);
-}
-
-static inline void appconfig_unlock(struct config *root) {
- netdata_mutex_unlock(&root->mutex);
-}
-
-static inline void config_section_wrlock(struct section *co) {
- netdata_mutex_lock(&co->mutex);
-}
-
-static inline void config_section_unlock(struct section *co) {
- netdata_mutex_unlock(&co->mutex);
-}
-
-
-// ----------------------------------------------------------------------------
-// config name-value index
-
-static int appconfig_option_compare(void *a, void *b) {
- if(((struct config_option *)a)->hash < ((struct config_option *)b)->hash) return -1;
- else if(((struct config_option *)a)->hash > ((struct config_option *)b)->hash) return 1;
- else return strcmp(((struct config_option *)a)->name, ((struct config_option *)b)->name);
-}
-
-#define appconfig_option_index_add(co, cv) (struct config_option *)avl_insert_lock(&((co)->values_index), (avl *)(cv))
-#define appconfig_option_index_del(co, cv) (struct config_option *)avl_remove_lock(&((co)->values_index), (avl *)(cv))
-
-static struct config_option *appconfig_option_index_find(struct section *co, const char *name, uint32_t hash) {
- struct config_option tmp;
- tmp.hash = (hash)?hash:simple_hash(name);
- tmp.name = (char *)name;
-
- return (struct config_option *)avl_search_lock(&(co->values_index), (avl *) &tmp);
-}
-
-
-// ----------------------------------------------------------------------------
-// config sections index
-
-static int appconfig_section_compare(void *a, void *b) {
- if(((struct section *)a)->hash < ((struct section *)b)->hash) return -1;
- else if(((struct section *)a)->hash > ((struct section *)b)->hash) return 1;
- else return strcmp(((struct section *)a)->name, ((struct section *)b)->name);
-}
-
-#define appconfig_index_add(root, cfg) (struct section *)avl_insert_lock(&(root)->index, (avl *)(cfg))
-#define appconfig_index_del(root, cfg) (struct section *)avl_remove_lock(&(root)->index, (avl *)(cfg))
-
-static struct section *appconfig_index_find(struct config *root, const char *name, uint32_t hash) {
- struct section tmp;
- tmp.hash = (hash)?hash:simple_hash(name);
- tmp.name = (char *)name;
-
- return (struct section *)avl_search_lock(&root->index, (avl *) &tmp);
-}
-
-
-// ----------------------------------------------------------------------------
-// config section methods
-
-static inline struct section *appconfig_section_find(struct config *root, const char *section) {
- return appconfig_index_find(root, section, 0);
-}
-
-static inline struct section *appconfig_section_create(struct config *root, const char *section) {
- debug(D_CONFIG, "Creating section '%s'.", section);
-
- struct section *co = callocz(1, sizeof(struct section));
- co->name = strdupz(section);
- co->hash = simple_hash(co->name);
- netdata_mutex_init(&co->mutex);
-
- avl_init_lock(&co->values_index, appconfig_option_compare);
-
- if(unlikely(appconfig_index_add(root, co) != co))
- error("INTERNAL ERROR: indexing of section '%s', already exists.", co->name);
-
- appconfig_wrlock(root);
- struct section *co2 = root->sections;
- if(co2) {
- while (co2->next) co2 = co2->next;
- co2->next = co;
- }
- else root->sections = co;
- appconfig_unlock(root);
-
- return co;
-}
-
-
-// ----------------------------------------------------------------------------
-// config name-value methods
-
-static inline struct config_option *appconfig_value_create(struct section *co, const char *name, const char *value) {
- debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name);
-
- struct config_option *cv = callocz(1, sizeof(struct config_option));
- cv->name = strdupz(name);
- cv->hash = simple_hash(cv->name);
- cv->value = strdupz(value);
-
- struct config_option *found = appconfig_option_index_add(co, cv);
- if(found != cv) {
- error("indexing of config '%s' in section '%s': already exists - using the existing one.", cv->name, co->name);
- freez(cv->value);
- freez(cv->name);
- freez(cv);
- return found;
- }
-
- config_section_wrlock(co);
- struct config_option *cv2 = co->values;
- if(cv2) {
- while (cv2->next) cv2 = cv2->next;
- cv2->next = cv;
- }
- else co->values = cv;
- config_section_unlock(co);
-
- return cv;
-}
-
-int appconfig_exists(struct config *root, const char *section, const char *name) {
- struct config_option *cv;
-
- debug(D_CONFIG, "request to get config in section '%s', name '%s'", section, name);
-
- struct section *co = appconfig_section_find(root, section);
- if(!co) return 0;
-
- cv = appconfig_option_index_find(co, name, 0);
- if(!cv) return 0;
-
- return 1;
-}
-
-int appconfig_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new) {
- struct config_option *cv_old, *cv_new;
- int ret = -1;
-
- debug(D_CONFIG, "request to rename config in section '%s', old name '%s', to section '%s', new name '%s'", section_old, name_old, section_new, name_new);
-
- struct section *co_old = appconfig_section_find(root, section_old);
- if(!co_old) return ret;
-
- struct section *co_new = appconfig_section_find(root, section_new);
- if(!co_new) co_new = appconfig_section_create(root, section_new);
-
- config_section_wrlock(co_old);
- if(co_old != co_new)
- config_section_wrlock(co_new);
-
- cv_old = appconfig_option_index_find(co_old, name_old, 0);
- if(!cv_old) goto cleanup;
-
- cv_new = appconfig_option_index_find(co_new, name_new, 0);
- if(cv_new) goto cleanup;
-
- if(unlikely(appconfig_option_index_del(co_old, cv_old) != cv_old))
- error("INTERNAL ERROR: deletion of config '%s' from section '%s', deleted tge wrong config entry.", cv_old->name, co_old->name);
-
- if(co_old->values == cv_old) {
- co_old->values = cv_old->next;
- }
- else {
- struct config_option *t;
- for(t = co_old->values; t && t->next != cv_old ;t = t->next) ;
- if(!t || t->next != cv_old)
- error("INTERNAL ERROR: cannot find variable '%s' in section '%s' of the config - but it should be there.", cv_old->name, co_old->name);
- else
- t->next = cv_old->next;
- }
-
- freez(cv_old->name);
- cv_old->name = strdupz(name_new);
- cv_old->hash = simple_hash(cv_old->name);
-
- cv_new = cv_old;
- cv_new->next = co_new->values;
- co_new->values = cv_new;
-
- if(unlikely(appconfig_option_index_add(co_new, cv_old) != cv_old))
- error("INTERNAL ERROR: re-indexing of config '%s' in section '%s', already exists.", cv_old->name, co_new->name);
-
- ret = 0;
-
-cleanup:
- if(co_old != co_new)
- config_section_unlock(co_new);
- config_section_unlock(co_old);
- return ret;
-}
-
-char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value)
-{
- struct config_option *cv;
-
- debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);
-
- struct section *co = appconfig_section_find(root, section);
- if(!co) co = appconfig_section_create(root, section);
-
- cv = appconfig_option_index_find(co, name, 0);
- if(!cv) {
- cv = appconfig_value_create(co, name, default_value);
- if(!cv) return NULL;
- }
- cv->flags |= CONFIG_VALUE_USED;
-
- if((cv->flags & CONFIG_VALUE_LOADED) || (cv->flags & CONFIG_VALUE_CHANGED)) {
- // this is a loaded value from the config file
- // if it is different that the default, mark it
- if(!(cv->flags & CONFIG_VALUE_CHECKED)) {
- if(strcmp(cv->value, default_value) != 0) cv->flags |= CONFIG_VALUE_CHANGED;
- cv->flags |= CONFIG_VALUE_CHECKED;
- }
- }
-
- return(cv->value);
-}
-
-long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value)
-{
- char buffer[100], *s;
- sprintf(buffer, "%lld", value);
-
- s = appconfig_get(root, section, name, buffer);
- if(!s) return value;
-
- return strtoll(s, NULL, 0);
-}
-
-LONG_DOUBLE appconfig_get_float(struct config *root, const char *section, const char *name, LONG_DOUBLE value)
-{
- char buffer[100], *s;
- sprintf(buffer, "%0.5" LONG_DOUBLE_MODIFIER, value);
-
- s = appconfig_get(root, section, name, buffer);
- if(!s) return value;
-
- return str2ld(s, NULL);
-}
-
-int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value)
-{
- char *s;
- if(value) s = "yes";
- else s = "no";
-
- s = appconfig_get(root, section, name, s);
- if(!s) return value;
-
- if(!strcasecmp(s, "yes") || !strcasecmp(s, "true") || !strcasecmp(s, "on") || !strcasecmp(s, "auto") || !strcasecmp(s, "on demand")) return 1;
- return 0;
-}
-
-int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value)
-{
- char *s;
-
- if(value == CONFIG_BOOLEAN_AUTO)
- s = "auto";
-
- else if(value == CONFIG_BOOLEAN_NO)
- s = "no";
-
- else
- s = "yes";
-
- s = appconfig_get(root, section, name, s);
- if(!s) return value;
-
- if(!strcmp(s, "yes"))
- return CONFIG_BOOLEAN_YES;
- else if(!strcmp(s, "no"))
- return CONFIG_BOOLEAN_NO;
- else if(!strcmp(s, "auto") || !strcmp(s, "on demand"))
- return CONFIG_BOOLEAN_AUTO;
-
- return value;
-}
-
-const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value)
-{
- struct config_option *cv;
-
- debug(D_CONFIG, "request to set default config in section '%s', name '%s', value '%s'", section, name, value);
-
- struct section *co = appconfig_section_find(root, section);
- if(!co) return appconfig_set(root, section, name, value);
-
- cv = appconfig_option_index_find(co, name, 0);
- if(!cv) return appconfig_set(root, section, name, value);
-
- cv->flags |= CONFIG_VALUE_USED;
-
- if(cv->flags & CONFIG_VALUE_LOADED)
- return cv->value;
-
- if(strcmp(cv->value, value) != 0) {
- cv->flags |= CONFIG_VALUE_CHANGED;
-
- freez(cv->value);
- cv->value = strdupz(value);
- }
-
- return cv->value;
-}
-
-const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value)
-{
- struct config_option *cv;
-
- debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
-
- struct section *co = appconfig_section_find(root, section);
- if(!co) co = appconfig_section_create(root, section);
-
- cv = appconfig_option_index_find(co, name, 0);
- if(!cv) cv = appconfig_value_create(co, name, value);
- cv->flags |= CONFIG_VALUE_USED;
-
- if(strcmp(cv->value, value) != 0) {
- cv->flags |= CONFIG_VALUE_CHANGED;
-
- freez(cv->value);
- cv->value = strdupz(value);
- }
-
- return value;
-}
-
-long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value)
-{
- char buffer[100];
- sprintf(buffer, "%lld", value);
-
- appconfig_set(root, section, name, buffer);
-
- return value;
-}
-
-LONG_DOUBLE appconfig_set_float(struct config *root, const char *section, const char *name, LONG_DOUBLE value)
-{
- char buffer[100];
- sprintf(buffer, "%0.5" LONG_DOUBLE_MODIFIER, value);
-
- appconfig_set(root, section, name, buffer);
-
- return value;
-}
-
-int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value)
-{
- char *s;
- if(value) s = "yes";
- else s = "no";
-
- appconfig_set(root, section, name, s);
-
- return value;
-}
-
-
-// ----------------------------------------------------------------------------
-// config load/save
-
-int appconfig_load(struct config *root, char *filename, int overwrite_used)
-{
- int line = 0;
- struct section *co = NULL;
-
- char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
-
- if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
-
- debug(D_CONFIG, "CONFIG: opening config file '%s'", filename);
-
- FILE *fp = fopen(filename, "r");
- if(!fp) {
- error("CONFIG: cannot open file '%s'", filename);
- return 0;
- }
-
- while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) {
- buffer[CONFIG_FILE_LINE_MAX] = '\0';
- line++;
-
- s = trim(buffer);
- if(!s || *s == '#') {
- debug(D_CONFIG, "CONFIG: ignoring line %d of file '%s', it is empty.", line, filename);
- continue;
- }
-
- int len = (int) strlen(s);
- if(*s == '[' && s[len - 1] == ']') {
- // new section
- s[len - 1] = '\0';
- s++;
-
- co = appconfig_section_find(root, s);
- if(!co) co = appconfig_section_create(root, s);
-
- continue;
- }
-
- if(!co) {
- // line outside a section
- error("CONFIG: ignoring line %d ('%s') of file '%s', it is outside all sections.", line, s, filename);
- continue;
- }
-
- char *name = s;
- char *value = strchr(s, '=');
- if(!value) {
- error("CONFIG: ignoring line %d ('%s') of file '%s', there is no = in it.", line, s, filename);
- continue;
- }
- *value = '\0';
- value++;
-
- name = trim(name);
- value = trim(value);
-
- if(!name || *name == '#') {
- error("CONFIG: ignoring line %d of file '%s', name is empty.", line, filename);
- continue;
- }
- if(!value) {
- debug(D_CONFIG, "CONFIG: ignoring line %d of file '%s', value is empty.", line, filename);
- continue;
- }
-
- struct config_option *cv = appconfig_option_index_find(co, name, 0);
-
- if(!cv) cv = appconfig_value_create(co, name, value);
- else {
- if(((cv->flags & CONFIG_VALUE_USED) && overwrite_used) || !(cv->flags & CONFIG_VALUE_USED)) {
- debug(D_CONFIG, "CONFIG: line %d of file '%s', overwriting '%s/%s'.", line, filename, co->name, cv->name);
- freez(cv->value);
- cv->value = strdupz(value);
- }
- else
- debug(D_CONFIG, "CONFIG: ignoring line %d of file '%s', '%s/%s' is already present and used.", line, filename, co->name, cv->name);
- }
- cv->flags |= CONFIG_VALUE_LOADED;
- }
-
- fclose(fp);
-
- return 1;
-}
-
-void appconfig_generate(struct config *root, BUFFER *wb, int only_changed)
-{
- int i, pri;
- struct section *co;
- struct config_option *cv;
-
- for(i = 0; i < 3 ;i++) {
- switch(i) {
- case 0:
- buffer_strcat(wb,
- "# netdata configuration\n"
- "#\n"
- "# You can download the latest version of this file, using:\n"
- "#\n"
- "# wget -O /etc/netdata/netdata.conf http://localhost:19999/netdata.conf\n"
- "# or\n"
- "# curl -o /etc/netdata/netdata.conf http://localhost:19999/netdata.conf\n"
- "#\n"
- "# You can uncomment and change any of the options below.\n"
- "# The value shown in the commented settings, is the default value.\n"
- "#\n"
- "\n# global netdata configuration\n");
- break;
-
- case 1:
- buffer_strcat(wb, "\n\n# per plugin configuration\n");
- break;
-
- case 2:
- buffer_strcat(wb, "\n\n# per chart configuration\n");
- break;
- }
-
- appconfig_wrlock(root);
- for(co = root->sections; co ; co = co->next) {
- if(!strcmp(co->name, CONFIG_SECTION_GLOBAL)
- || !strcmp(co->name, CONFIG_SECTION_WEB)
- || !strcmp(co->name, CONFIG_SECTION_STATSD)
- || !strcmp(co->name, CONFIG_SECTION_PLUGINS)
- || !strcmp(co->name, CONFIG_SECTION_REGISTRY)
- || !strcmp(co->name, CONFIG_SECTION_HEALTH)
- || !strcmp(co->name, CONFIG_SECTION_BACKEND)
- || !strcmp(co->name, CONFIG_SECTION_STREAM)
- )
- pri = 0;
- else if(!strncmp(co->name, "plugin:", 7)) pri = 1;
- else pri = 2;
-
- if(i == pri) {
- int loaded = 0;
- int used = 0;
- int changed = 0;
- int count = 0;
-
- config_section_wrlock(co);
- for(cv = co->values; cv ; cv = cv->next) {
- used += (cv->flags & CONFIG_VALUE_USED)?1:0;
- loaded += (cv->flags & CONFIG_VALUE_LOADED)?1:0;
- changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0;
- count++;
- }
- config_section_unlock(co);
-
- if(!count) continue;
- if(only_changed && !changed && !loaded) continue;
-
- if(!used) {
- buffer_sprintf(wb, "\n# section '%s' is not used.", co->name);
- }
-
- buffer_sprintf(wb, "\n[%s]\n", co->name);
-
- config_section_wrlock(co);
- for(cv = co->values; cv ; cv = cv->next) {
-
- if(used && !(cv->flags & CONFIG_VALUE_USED)) {
- buffer_sprintf(wb, "\n\t# option '%s' is not used.\n", cv->name);
- }
- buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_LOADED)) && (!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
- }
- config_section_unlock(co);
- }
- }
- appconfig_unlock(root);
- }
-}
diff --git a/src/appconfig.h b/src/appconfig.h
deleted file mode 100644
index 7d056e6be..000000000
--- a/src/appconfig.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef NETDATA_CONFIG_H
-#define NETDATA_CONFIG_H 1
-
-#define CONFIG_FILENAME "netdata.conf"
-
-#define CONFIG_SECTION_GLOBAL "global"
-#define CONFIG_SECTION_WEB "web"
-#define CONFIG_SECTION_STATSD "statsd"
-#define CONFIG_SECTION_PLUGINS "plugins"
-#define CONFIG_SECTION_REGISTRY "registry"
-#define CONFIG_SECTION_HEALTH "health"
-#define CONFIG_SECTION_BACKEND "backend"
-#define CONFIG_SECTION_STREAM "stream"
-
-// these are used to limit the configuration names and values lengths
-// they are not enforced by config.c functions (they will strdup() all strings, no matter of their length)
-#define CONFIG_MAX_NAME 1024
-#define CONFIG_MAX_VALUE 2048
-
-struct config {
- struct section *sections;
- netdata_mutex_t mutex;
- avl_tree_lock index;
-};
-
-extern struct config
- netdata_config,
- stream_config;
-
-#define CONFIG_BOOLEAN_NO 0
-#define CONFIG_BOOLEAN_YES 1
-#define CONFIG_BOOLEAN_AUTO 2
-
-extern int appconfig_load(struct config *root, char *filename, int overwrite_used);
-
-extern char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value);
-extern long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value);
-extern LONG_DOUBLE appconfig_get_float(struct config *root, const char *section, const char *name, LONG_DOUBLE value);
-extern int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value);
-extern int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value);
-
-extern const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value);
-extern const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value);
-extern long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value);
-extern LONG_DOUBLE appconfig_set_float(struct config *root, const char *section, const char *name, LONG_DOUBLE value);
-extern int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value);
-
-extern int appconfig_exists(struct config *root, const char *section, const char *name);
-extern int appconfig_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new);
-
-extern void appconfig_generate(struct config *root, BUFFER *wb, int only_changed);
-
-// ----------------------------------------------------------------------------
-// shortcuts for the default netdata configuration
-
-#define config_load(filename, overwrite_used) appconfig_load(&netdata_config, filename, overwrite_used)
-#define config_get(section, name, default_value) appconfig_get(&netdata_config, section, name, default_value)
-#define config_get_number(section, name, value) appconfig_get_number(&netdata_config, section, name, value)
-#define config_get_float(section, name, value) appconfig_get_float(&netdata_config, section, name, value)
-#define config_get_boolean(section, name, value) appconfig_get_boolean(&netdata_config, section, name, value)
-#define config_get_boolean_ondemand(section, name, value) appconfig_get_boolean_ondemand(&netdata_config, section, name, value)
-
-#define config_set(section, name, default_value) appconfig_set(&netdata_config, section, name, default_value)
-#define config_set_default(section, name, value) appconfig_set_default(&netdata_config, section, name, value)
-#define config_set_number(section, name, value) appconfig_set_number(&netdata_config, section, name, value)
-#define config_set_float(section, name, value) appconfig_set_float(&netdata_config, section, name, value)
-#define config_set_boolean(section, name, value) appconfig_set_boolean(&netdata_config, section, name, value)
-
-#define config_exists(section, name) appconfig_exists(&netdata_config, section, name)
-#define config_move(section_old, name_old, section_new, name_new) appconfig_move(&netdata_config, section_old, name_old, section_new, name_new)
-
-#define config_generate(buffer, only_changed) appconfig_generate(&netdata_config, buffer, only_changed)
-
-#endif /* NETDATA_CONFIG_H */
diff --git a/src/apps_plugin.c b/src/apps_plugin.c
deleted file mode 100644
index 8595da6c2..000000000
--- a/src/apps_plugin.c
+++ /dev/null
@@ -1,3639 +0,0 @@
-
-/*
- * netdata apps.plugin
- * (C) Copyright 2016-2017 Costa Tsaousis <costa@tsaousis.gr>
- * Released under GPL v3+
- */
-
-#include "common.h"
-
-#ifdef __FreeBSD__
-#include <sys/user.h>
-#endif
-
-// ----------------------------------------------------------------------------
-// per O/S configuration
-
-// the minimum PID of the system
-// this is also the pid of the init process
-#define INIT_PID 1
-
-// if the way apps.plugin will work, will read the entire process list,
-// including the resource utilization of each process, instantly
-// set this to 1
-// when set to 0, apps.plugin builds a sort list of processes, in order
-// to process children processes, before parent processes
-#ifdef __FreeBSD__
-#define ALL_PIDS_ARE_READ_INSTANTLY 1
-#else
-#define ALL_PIDS_ARE_READ_INSTANTLY 0
-#endif
-
-// ----------------------------------------------------------------------------
-// string lengths
-
-#define MAX_COMPARE_NAME 100
-#define MAX_NAME 100
-#define MAX_CMDLINE 16384
-
-// ----------------------------------------------------------------------------
-// the rates we are going to send to netdata will have this detail a value of:
-// - 1 will send just integer parts to netdata
-// - 100 will send 2 decimal points
-// - 1000 will send 3 decimal points
-// etc.
-#define RATES_DETAIL 10000ULL
-
-
-// ----------------------------------------------------------------------------
-// to avoid reallocating too frequently, we can increase the number of spare
-// file descriptors used by processes.
-// IMPORTANT:
-// having a lot of spares, increases the CPU utilization of the plugin.
-#define MAX_SPARE_FDS 1
-
-
-// ----------------------------------------------------------------------------
-// command line options
-
-static int
- debug = 0,
- update_every = 1,
- enable_guest_charts = 0,
-#ifdef __FreeBSD__
- enable_file_charts = 0,
-#else
- enable_file_charts = 1,
-#endif
- enable_users_charts = 1,
- enable_groups_charts = 1,
- include_exited_childs = 1;
-
-
-// will be changed to getenv(NETDATA_CONFIG_DIR) if it exists
-static char *config_dir = CONFIG_DIR;
-
-// ----------------------------------------------------------------------------
-// internal flags
-// handled in code (automatically set)
-
-static int
- show_guest_time = 0, // 1 when guest values are collected
- show_guest_time_old = 0,
- proc_pid_cmdline_is_needed = 0; // 1 when we need to read /proc/cmdline
-
-
-// ----------------------------------------------------------------------------
-// internal counters
-
-static size_t
- global_iterations_counter = 1,
- calls_counter = 0,
- file_counter = 0,
- targets_assignment_counter = 0;
-
-
-// ----------------------------------------------------------------------------
-// Normalization
-//
-// With normalization we lower the collected metrics by a factor to make them
-// match the total utilization of the system.
-// The discrepancy exists because apps.plugin needs some time to collect all
-// the metrics. This results in utilization that exceeds the total utilization
-// of the system.
-//
-// With normalization we align the per-process utilization, to the total of
-// the system. We first consume the exited children utilization and it the
-// collected values is above the total, we proportionally scale each reported
-// metric.
-
-// the total system time, as reported by /proc/stat
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
-static kernel_uint_t
- global_utime = 0,
- global_stime = 0,
- global_gtime = 0;
-#endif
-
-// the normalization ratios, as calculated by normalize_utilization()
-double utime_fix_ratio = 1.0,
- stime_fix_ratio = 1.0,
- gtime_fix_ratio = 1.0,
- minflt_fix_ratio = 1.0,
- majflt_fix_ratio = 1.0,
- cutime_fix_ratio = 1.0,
- cstime_fix_ratio = 1.0,
- cgtime_fix_ratio = 1.0,
- cminflt_fix_ratio = 1.0,
- cmajflt_fix_ratio = 1.0;
-
-// ----------------------------------------------------------------------------
-// target
-//
-// target is the structure that processes are aggregated to be reported
-// to netdata.
-//
-// - Each entry in /etc/apps_groups.conf creates a target.
-// - Each user and group used by a process in the system, creates a target.
-
-struct target {
- char compare[MAX_COMPARE_NAME + 1];
- uint32_t comparehash;
- size_t comparelen;
-
- char id[MAX_NAME + 1];
- uint32_t idhash;
-
- char name[MAX_NAME + 1];
-
- uid_t uid;
- gid_t gid;
-
- kernel_uint_t minflt;
- kernel_uint_t cminflt;
- kernel_uint_t majflt;
- kernel_uint_t cmajflt;
- kernel_uint_t utime;
- kernel_uint_t stime;
- kernel_uint_t gtime;
- kernel_uint_t cutime;
- kernel_uint_t cstime;
- kernel_uint_t cgtime;
- kernel_uint_t num_threads;
- // kernel_uint_t rss;
-
- kernel_uint_t status_vmsize;
- kernel_uint_t status_vmrss;
- kernel_uint_t status_vmshared;
- kernel_uint_t status_rssfile;
- kernel_uint_t status_rssshmem;
- kernel_uint_t status_vmswap;
-
- kernel_uint_t io_logical_bytes_read;
- kernel_uint_t io_logical_bytes_written;
- // kernel_uint_t io_read_calls;
- // kernel_uint_t io_write_calls;
- kernel_uint_t io_storage_bytes_read;
- kernel_uint_t io_storage_bytes_written;
- // kernel_uint_t io_cancelled_write_bytes;
-
- int *target_fds;
- int target_fds_size;
-
- kernel_uint_t openfiles;
- kernel_uint_t openpipes;
- kernel_uint_t opensockets;
- kernel_uint_t openinotifies;
- kernel_uint_t openeventfds;
- kernel_uint_t opentimerfds;
- kernel_uint_t opensignalfds;
- kernel_uint_t openeventpolls;
- kernel_uint_t openother;
-
- unsigned int processes; // how many processes have been merged to this
- int exposed; // if set, we have sent this to netdata
- int hidden; // if set, we set the hidden flag on the dimension
- int debug;
- int ends_with;
- int starts_with; // if set, the compare string matches only the
- // beginning of the command
-
- struct target *target; // the one that will be reported to netdata
- struct target *next;
-};
-
-struct target
- *apps_groups_default_target = NULL, // the default target
- *apps_groups_root_target = NULL, // apps_groups.conf defined
- *users_root_target = NULL, // users
- *groups_root_target = NULL; // user groups
-
-size_t
- apps_groups_targets_count = 0; // # of apps_groups.conf targets
-
-
-// ----------------------------------------------------------------------------
-// pid_stat
-//
-// structure to store data for each process running
-// see: man proc for the description of the fields
-
-struct pid_stat {
- int32_t pid;
- char comm[MAX_COMPARE_NAME + 1];
- char *cmdline;
-
- uint32_t log_thrown;
-
- // char state;
- int32_t ppid;
- // int32_t pgrp;
- // int32_t session;
- // int32_t tty_nr;
- // int32_t tpgid;
- // uint64_t flags;
-
- // these are raw values collected
- kernel_uint_t minflt_raw;
- kernel_uint_t cminflt_raw;
- kernel_uint_t majflt_raw;
- kernel_uint_t cmajflt_raw;
- kernel_uint_t utime_raw;
- kernel_uint_t stime_raw;
- kernel_uint_t gtime_raw; // guest_time
- kernel_uint_t cutime_raw;
- kernel_uint_t cstime_raw;
- kernel_uint_t cgtime_raw; // cguest_time
-
- // these are rates
- kernel_uint_t minflt;
- kernel_uint_t cminflt;
- kernel_uint_t majflt;
- kernel_uint_t cmajflt;
- kernel_uint_t utime;
- kernel_uint_t stime;
- kernel_uint_t gtime;
- kernel_uint_t cutime;
- kernel_uint_t cstime;
- kernel_uint_t cgtime;
-
- // int64_t priority;
- // int64_t nice;
- int32_t num_threads;
- // int64_t itrealvalue;
- // kernel_uint_t starttime;
- // kernel_uint_t vsize;
- // kernel_uint_t rss;
- // kernel_uint_t rsslim;
- // kernel_uint_t starcode;
- // kernel_uint_t endcode;
- // kernel_uint_t startstack;
- // kernel_uint_t kstkesp;
- // kernel_uint_t kstkeip;
- // uint64_t signal;
- // uint64_t blocked;
- // uint64_t sigignore;
- // uint64_t sigcatch;
- // uint64_t wchan;
- // uint64_t nswap;
- // uint64_t cnswap;
- // int32_t exit_signal;
- // int32_t processor;
- // uint32_t rt_priority;
- // uint32_t policy;
- // kernel_uint_t delayacct_blkio_ticks;
-
- uid_t uid;
- gid_t gid;
-
- kernel_uint_t status_vmsize;
- kernel_uint_t status_vmrss;
- kernel_uint_t status_vmshared;
- kernel_uint_t status_rssfile;
- kernel_uint_t status_rssshmem;
- kernel_uint_t status_vmswap;
-#ifndef __FreeBSD__
- ARL_BASE *status_arl;
-#endif
-
- kernel_uint_t io_logical_bytes_read_raw;
- kernel_uint_t io_logical_bytes_written_raw;
- // kernel_uint_t io_read_calls_raw;
- // kernel_uint_t io_write_calls_raw;
- kernel_uint_t io_storage_bytes_read_raw;
- kernel_uint_t io_storage_bytes_written_raw;
- // kernel_uint_t io_cancelled_write_bytes_raw;
-
- kernel_uint_t io_logical_bytes_read;
- kernel_uint_t io_logical_bytes_written;
- // kernel_uint_t io_read_calls;
- // kernel_uint_t io_write_calls;
- kernel_uint_t io_storage_bytes_read;
- kernel_uint_t io_storage_bytes_written;
- // kernel_uint_t io_cancelled_write_bytes;
-
- int *fds; // array of fds it uses
- int fds_size; // the size of the fds array
-
- int children_count; // number of processes directly referencing this
- char keep:1; // 1 when we need to keep this process in memory even after it exited
- int keeploops; // increases by 1 every time keep is 1 and updated 0
- char updated:1; // 1 when the process is currently running
- char merged:1; // 1 when it has been merged to its parent
- char read:1; // 1 when we have already read this process for this iteration
-
- int sortlist; // higher numbers = top on the process tree
- // each process gets a unique number
-
- struct target *target; // app_groups.conf targets
- struct target *user_target; // uid based targets
- struct target *group_target; // gid based targets
-
- usec_t stat_collected_usec;
- usec_t last_stat_collected_usec;
-
- usec_t io_collected_usec;
- usec_t last_io_collected_usec;
-
- char *fds_dirname; // the full directory name in /proc/PID/fd
-
- char *stat_filename;
- char *status_filename;
- char *io_filename;
- char *cmdline_filename;
-
- struct pid_stat *parent;
- struct pid_stat *prev;
- struct pid_stat *next;
-};
-
-size_t pagesize;
-
-// log each problem once per process
-// log flood protection flags (log_thrown)
-#define PID_LOG_IO 0x00000001
-#define PID_LOG_STATUS 0x00000002
-#define PID_LOG_CMDLINE 0x00000004
-#define PID_LOG_FDS 0x00000008
-#define PID_LOG_STAT 0x00000010
-
-static struct pid_stat
- *root_of_pids = NULL, // global list of all processes running
- **all_pids = NULL; // to avoid allocations, we pre-allocate the
- // the entire pid space.
-
-static size_t
- all_pids_count = 0; // the number of processes running
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
-// Another pre-allocated list of all possible pids.
-// We need it to pids and assign them a unique sortlist id, so that we
-// read parents before children. This is needed to prevent a situation where
-// a child is found running, but until we read its parent, it has exited and
-// its parent has accumulated its resources.
-static pid_t
- *all_pids_sortlist = NULL;
-#endif
-
-// ----------------------------------------------------------------------------
-// file descriptor
-//
-// this is used to keep a global list of all open files of the system.
-// it is needed in order to calculate the unique files processes have open.
-
-#define FILE_DESCRIPTORS_INCREASE_STEP 100
-
-// types for struct file_descriptor->type
-typedef enum fd_filetype {
- FILETYPE_OTHER,
- FILETYPE_FILE,
- FILETYPE_PIPE,
- FILETYPE_SOCKET,
- FILETYPE_INOTIFY,
- FILETYPE_EVENTFD,
- FILETYPE_EVENTPOLL,
- FILETYPE_TIMERFD,
- FILETYPE_SIGNALFD
-} FD_FILETYPE;
-
-struct file_descriptor {
- avl avl;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- uint32_t magic;
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- const char *name;
- uint32_t hash;
-
- FD_FILETYPE type;
- int count;
- int pos;
-} *all_files = NULL;
-
-static int
- all_files_len = 0,
- all_files_size = 0;
-
-// ----------------------------------------------------------------------------
-// callback required by fatal()
-
-void netdata_cleanup_and_exit(int ret) {
- exit(ret);
-}
-
-// ----------------------------------------------------------------------------
-// apps_groups.conf
-// aggregate all processes in groups, to have a limited number of dimensions
-
-static struct target *get_users_target(uid_t uid) {
- struct target *w;
- for(w = users_root_target ; w ; w = w->next)
- if(w->uid == uid) return w;
-
- w = callocz(sizeof(struct target), 1);
- snprintfz(w->compare, MAX_COMPARE_NAME, "%u", uid);
- w->comparehash = simple_hash(w->compare);
- w->comparelen = strlen(w->compare);
-
- snprintfz(w->id, MAX_NAME, "%u", uid);
- w->idhash = simple_hash(w->id);
-
- struct passwd *pw = getpwuid(uid);
- if(!pw || !pw->pw_name || !*pw->pw_name)
- snprintfz(w->name, MAX_NAME, "%u", uid);
- else
- snprintfz(w->name, MAX_NAME, "%s", pw->pw_name);
-
- netdata_fix_chart_name(w->name);
-
- w->uid = uid;
-
- w->next = users_root_target;
- users_root_target = w;
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: added uid %u ('%s') target\n", w->uid, w->name);
-
- return w;
-}
-
-struct target *get_groups_target(gid_t gid)
-{
- struct target *w;
- for(w = groups_root_target ; w ; w = w->next)
- if(w->gid == gid) return w;
-
- w = callocz(sizeof(struct target), 1);
- snprintfz(w->compare, MAX_COMPARE_NAME, "%u", gid);
- w->comparehash = simple_hash(w->compare);
- w->comparelen = strlen(w->compare);
-
- snprintfz(w->id, MAX_NAME, "%u", gid);
- w->idhash = simple_hash(w->id);
-
- struct group *gr = getgrgid(gid);
- if(!gr || !gr->gr_name || !*gr->gr_name)
- snprintfz(w->name, MAX_NAME, "%u", gid);
- else
- snprintfz(w->name, MAX_NAME, "%s", gr->gr_name);
-
- netdata_fix_chart_name(w->name);
-
- w->gid = gid;
-
- w->next = groups_root_target;
- groups_root_target = w;
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: added gid %u ('%s') target\n", w->gid, w->name);
-
- return w;
-}
-
-// find or create a new target
-// there are targets that are just aggregated to other target (the second argument)
-static struct target *get_apps_groups_target(const char *id, struct target *target, const char *name) {
- int tdebug = 0, thidden = target?target->hidden:0, ends_with = 0;
- const char *nid = id;
-
- // extract the options
- while(nid[0] == '-' || nid[0] == '+' || nid[0] == '*') {
- if(nid[0] == '-') thidden = 1;
- if(nid[0] == '+') tdebug = 1;
- if(nid[0] == '*') ends_with = 1;
- nid++;
- }
- uint32_t hash = simple_hash(id);
-
- // find if it already exists
- struct target *w, *last = apps_groups_root_target;
- for(w = apps_groups_root_target ; w ; w = w->next) {
- if(w->idhash == hash && strncmp(nid, w->id, MAX_NAME) == 0)
- return w;
-
- last = w;
- }
-
- // find an existing target
- if(unlikely(!target)) {
- while(*name == '-') {
- if(*name == '-') thidden = 1;
- name++;
- }
-
- for(target = apps_groups_root_target ; target != NULL ; target = target->next) {
- if(!target->target && strcmp(name, target->name) == 0)
- break;
- }
-
- if(unlikely(debug)) {
- if(unlikely(target))
- fprintf(stderr, "apps.plugin: REUSING TARGET NAME '%s' on ID '%s'\n", target->name, target->id);
- else
- fprintf(stderr, "apps.plugin: NEW TARGET NAME '%s' on ID '%s'\n", name, id);
- }
- }
-
- if(target && target->target)
- fatal("Internal Error: request to link process '%s' to target '%s' which is linked to target '%s'", id, target->id, target->target->id);
-
- w = callocz(sizeof(struct target), 1);
- strncpyz(w->id, nid, MAX_NAME);
- w->idhash = simple_hash(w->id);
-
- if(unlikely(!target))
- // copy the name
- strncpyz(w->name, name, MAX_NAME);
- else
- // copy the id
- strncpyz(w->name, nid, MAX_NAME);
-
- strncpyz(w->compare, nid, MAX_COMPARE_NAME);
- size_t len = strlen(w->compare);
- if(w->compare[len - 1] == '*') {
- w->compare[len - 1] = '\0';
- w->starts_with = 1;
- }
- w->ends_with = ends_with;
-
- if(w->starts_with && w->ends_with)
- proc_pid_cmdline_is_needed = 1;
-
- w->comparehash = simple_hash(w->compare);
- w->comparelen = strlen(w->compare);
-
- w->hidden = thidden;
- w->debug = tdebug;
- w->target = target;
-
- // append it, to maintain the order in apps_groups.conf
- if(last) last->next = w;
- else apps_groups_root_target = w;
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: ADDING TARGET ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n"
- , w->id
- , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact"))
- , w->target?w->target->name:w->name
- , (w->hidden)?"hidden":"-"
- , (w->debug)?"debug":"-"
- );
-
- return w;
-}
-
-// read the apps_groups.conf file
-static int read_apps_groups_conf(const char *file)
-{
- char filename[FILENAME_MAX + 1];
-
- snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", config_dir, file);
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: process groups file: '%s'\n", filename);
-
- // ----------------------------------------
-
- procfile *ff = procfile_open(filename, " :\t", PROCFILE_FLAG_DEFAULT);
- if(!ff) return 1;
-
- procfile_set_quotes(ff, "'\"");
-
- ff = procfile_readall(ff);
- if(!ff)
- return 1;
-
- size_t line, lines = procfile_lines(ff);
-
- for(line = 0; line < lines ;line++) {
- size_t word, words = procfile_linewords(ff, line);
- if(!words) continue;
-
- char *name = procfile_lineword(ff, line, 0);
- if(!name || !*name) continue;
-
- // find a possibly existing target
- struct target *w = NULL;
-
- // loop through all words, skipping the first one (the name)
- for(word = 0; word < words ;word++) {
- char *s = procfile_lineword(ff, line, word);
- if(!s || !*s) continue;
- if(*s == '#') break;
-
- // is this the first word? skip it
- if(s == name) continue;
-
- // add this target
- struct target *n = get_apps_groups_target(s, w, name);
- if(!n) {
- error("Cannot create target '%s' (line %zu, word %zu)", s, line, word);
- continue;
- }
-
- // just some optimization
- // to avoid searching for a target for each process
- if(!w) w = n->target?n->target:n;
- }
- }
-
- procfile_close(ff);
-
- apps_groups_default_target = get_apps_groups_target("p+!o@w#e$i^r&7*5(-i)l-o_", NULL, "other"); // match nothing
- if(!apps_groups_default_target)
- fatal("Cannot create default target");
-
- // allow the user to override group 'other'
- if(apps_groups_default_target->target)
- apps_groups_default_target = apps_groups_default_target->target;
-
- return 0;
-}
-
-
-// ----------------------------------------------------------------------------
-// struct pid_stat management
-
-static inline struct pid_stat *get_pid_entry(pid_t pid) {
- if(unlikely(all_pids[pid]))
- return all_pids[pid];
-
- struct pid_stat *p = callocz(sizeof(struct pid_stat), 1);
- p->fds = callocz(sizeof(int), MAX_SPARE_FDS);
- p->fds_size = MAX_SPARE_FDS;
-
- if(likely(root_of_pids))
- root_of_pids->prev = p;
-
- p->next = root_of_pids;
- root_of_pids = p;
-
- p->pid = pid;
-
- all_pids[pid] = p;
- all_pids_count++;
-
- return p;
-}
-
-static inline void del_pid_entry(pid_t pid) {
- struct pid_stat *p = all_pids[pid];
-
- if(unlikely(!p)) {
- error("attempted to free pid %d that is not allocated.", pid);
- return;
- }
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, p->comm);
-
- if(root_of_pids == p)
- root_of_pids = p->next;
-
- if(p->next) p->next->prev = p->prev;
- if(p->prev) p->prev->next = p->next;
-
- freez(p->fds);
- freez(p->fds_dirname);
- freez(p->stat_filename);
- freez(p->status_filename);
-#ifndef __FreeBSD__
- arl_free(p->status_arl);
-#endif
- freez(p->io_filename);
- freez(p->cmdline_filename);
- freez(p->cmdline);
- freez(p);
-
- all_pids[pid] = NULL;
- all_pids_count--;
-}
-
-// ----------------------------------------------------------------------------
-
-static inline int managed_log(struct pid_stat *p, uint32_t log, int status) {
- if(unlikely(!status)) {
- // error("command failed log %u, errno %d", log, errno);
-
- if(unlikely(debug || errno != ENOENT)) {
- if(unlikely(debug || !(p->log_thrown & log))) {
- p->log_thrown |= log;
- switch(log) {
- case PID_LOG_IO:
- #ifdef __FreeBSD__
- error("Cannot fetch process %d I/O info (command '%s')", p->pid, p->comm);
- #else
- error("Cannot process %s/proc/%d/io (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
- #endif
- break;
-
- case PID_LOG_STATUS:
- #ifdef __FreeBSD__
- error("Cannot fetch process %d status info (command '%s')", p->pid, p->comm);
- #else
- error("Cannot process %s/proc/%d/status (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
- #endif
- break;
-
- case PID_LOG_CMDLINE:
- #ifdef __FreeBSD__
- error("Cannot fetch process %d command line (command '%s')", p->pid, p->comm);
- #else
- error("Cannot process %s/proc/%d/cmdline (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
- #endif
- break;
-
- case PID_LOG_FDS:
- #ifdef __FreeBSD__
- error("Cannot fetch process %d files (command '%s')", p->pid, p->comm);
- #else
- error("Cannot process entries in %s/proc/%d/fd (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
- #endif
- break;
-
- case PID_LOG_STAT:
- break;
-
- default:
- error("unhandled error for pid %d, command '%s'", p->pid, p->comm);
- break;
- }
- }
- }
- errno = 0;
- }
- else if(unlikely(p->log_thrown & log)) {
- // error("unsetting log %u on pid %d", log, p->pid);
- p->log_thrown &= ~log;
- }
-
- return status;
-}
-
-static inline void assign_target_to_pid(struct pid_stat *p) {
- targets_assignment_counter++;
-
- uint32_t hash = simple_hash(p->comm);
- size_t pclen = strlen(p->comm);
-
- struct target *w;
- for(w = apps_groups_root_target; w ; w = w->next) {
- // if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
-
- // find it - 4 cases:
- // 1. the target is not a pattern
- // 2. the target has the prefix
- // 3. the target has the suffix
- // 4. the target is something inside cmdline
-
- if(unlikely(( (!w->starts_with && !w->ends_with && w->comparehash == hash && !strcmp(w->compare, p->comm))
- || (w->starts_with && !w->ends_with && !strncmp(w->compare, p->comm, w->comparelen))
- || (!w->starts_with && w->ends_with && pclen >= w->comparelen && !strcmp(w->compare, &p->comm[pclen - w->comparelen]))
- || (proc_pid_cmdline_is_needed && w->starts_with && w->ends_with && p->cmdline && strstr(p->cmdline, w->compare))
- ))) {
-
- if(w->target) p->target = w->target;
- else p->target = w;
-
- if(debug || (p->target && p->target->debug))
- fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name);
-
- break;
- }
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// update pids from proc
-
-static inline int read_proc_pid_cmdline(struct pid_stat *p) {
- static char cmdline[MAX_CMDLINE + 1];
-
-#ifdef __FreeBSD__
- size_t i, bytes = MAX_CMDLINE;
- int mib[4];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_ARGS;
- mib[3] = p->pid;
- if (unlikely(sysctl(mib, 4, cmdline, &bytes, NULL, 0)))
- goto cleanup;
-#else
- if(unlikely(!p->cmdline_filename)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", netdata_configured_host_prefix, p->pid);
- p->cmdline_filename = strdupz(filename);
- }
-
- int fd = open(p->cmdline_filename, O_RDONLY, 0666);
- if(unlikely(fd == -1)) goto cleanup;
-
- ssize_t i, bytes = read(fd, cmdline, MAX_CMDLINE);
- close(fd);
-
- if(unlikely(bytes < 0)) goto cleanup;
-#endif
-
- cmdline[bytes] = '\0';
- for(i = 0; i < bytes ; i++)
- if(unlikely(!cmdline[i])) cmdline[i] = ' ';
-
- p->cmdline = strdupz(cmdline);
-
- if(unlikely(debug))
- fprintf(stderr, "Read file '%s' contents: %s\n", p->cmdline_filename, p->cmdline);
-
- return 1;
-
-cleanup:
- // copy the command to the command line
- p->cmdline = strdupz(p->comm);
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// macro to calculate the incremental rate of a value
-// each parameter is accessed only ONCE - so it is safe to pass function calls
-// or other macros as parameters
-
-#define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec) { \
- kernel_uint_t _new_tmp = new_kernel_value; \
- (rate_variable) = (_new_tmp - (last_kernel_variable)) * (USEC_PER_SEC * RATES_DETAIL) / ((collected_usec) - (last_collected_usec)); \
- (last_kernel_variable) = _new_tmp; \
- }
-
-// the same macro for struct pid members
-#define pid_incremental_rate(type, var, value) \
- incremental_rate(var, var##_raw, value, p->type##_collected_usec, p->last_##type##_collected_usec)
-
-
-// ----------------------------------------------------------------------------
-
-#ifndef __FreeBSD__
-struct arl_callback_ptr {
- struct pid_stat *p;
- procfile *ff;
- size_t line;
-};
-
-void arl_callback_status_uid(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 5)) return;
-
- //const char *real_uid = procfile_lineword(aptr->ff, aptr->line, 1);
- const char *effective_uid = procfile_lineword(aptr->ff, aptr->line, 2);
- //const char *saved_uid = procfile_lineword(aptr->ff, aptr->line, 3);
- //const char *filesystem_uid = procfile_lineword(aptr->ff, aptr->line, 4);
-
- if(likely(effective_uid && *effective_uid))
- aptr->p->uid = (uid_t)str2l(effective_uid);
-}
-
-void arl_callback_status_gid(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 5)) return;
-
- //const char *real_gid = procfile_lineword(aptr->ff, aptr->line, 1);
- const char *effective_gid = procfile_lineword(aptr->ff, aptr->line, 2);
- //const char *saved_gid = procfile_lineword(aptr->ff, aptr->line, 3);
- //const char *filesystem_gid = procfile_lineword(aptr->ff, aptr->line, 4);
-
- if(likely(effective_gid && *effective_gid))
- aptr->p->gid = (uid_t)str2l(effective_gid);
-}
-
-void arl_callback_status_vmsize(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
-
- aptr->p->status_vmsize = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1));
-}
-
-void arl_callback_status_vmswap(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
-
- aptr->p->status_vmswap = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1));
-}
-
-void arl_callback_status_vmrss(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
-
- aptr->p->status_vmrss = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1));
-}
-
-void arl_callback_status_rssfile(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
-
- aptr->p->status_rssfile = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1));
-}
-
-void arl_callback_status_rssshmem(const char *name, uint32_t hash, const char *value, void *dst) {
- (void)name; (void)hash; (void)value;
- struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
- if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 3)) return;
-
- aptr->p->status_rssshmem = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1));
-}
-#endif // !__FreeBSD__
-
-static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
- p->status_vmsize = 0;
- p->status_vmrss = 0;
- p->status_vmshared = 0;
- p->status_rssfile = 0;
- p->status_rssshmem = 0;
- p->status_vmswap = 0;
-
-#ifdef __FreeBSD__
- struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
-
- p->uid = proc_info->ki_uid;
- p->gid = proc_info->ki_groups[0];
- p->status_vmsize = proc_info->ki_size / 1024; // in kB
- p->status_vmrss = proc_info->ki_rssize * pagesize / 1024; // in kB
- // FIXME: what about shared and swap memory on FreeBSD?
- return 1;
-#else
- (void)ptr;
-
- static struct arl_callback_ptr arl_ptr;
- static procfile *ff = NULL;
-
- if(unlikely(!p->status_arl)) {
- p->status_arl = arl_create("/proc/pid/status", NULL, 60);
- arl_expect_custom(p->status_arl, "Uid", arl_callback_status_uid, &arl_ptr);
- arl_expect_custom(p->status_arl, "Gid", arl_callback_status_gid, &arl_ptr);
- arl_expect_custom(p->status_arl, "VmSize", arl_callback_status_vmsize, &arl_ptr);
- arl_expect_custom(p->status_arl, "VmRSS", arl_callback_status_vmrss, &arl_ptr);
- arl_expect_custom(p->status_arl, "RssFile", arl_callback_status_rssfile, &arl_ptr);
- arl_expect_custom(p->status_arl, "RssShmem", arl_callback_status_rssshmem, &arl_ptr);
- arl_expect_custom(p->status_arl, "VmSwap", arl_callback_status_vmswap, &arl_ptr);
- }
-
- if(unlikely(!p->status_filename)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/status", netdata_configured_host_prefix, p->pid);
- p->status_filename = strdupz(filename);
- }
-
- ff = procfile_reopen(ff, p->status_filename, (!ff)?" \t:,-()/":NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
- if(unlikely(!ff)) return 0;
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0;
-
- calls_counter++;
-
- // let ARL use this pid
- arl_ptr.p = p;
- arl_ptr.ff = ff;
-
- size_t lines = procfile_lines(ff), l;
- arl_begin(p->status_arl);
-
- for(l = 0; l < lines ;l++) {
- // fprintf(stderr, "CHECK: line %zu of %zu, key '%s' = '%s'\n", l, lines, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1));
- arl_ptr.line = l;
- if(unlikely(arl_check(p->status_arl,
- procfile_lineword(ff, l, 0),
- procfile_lineword(ff, l, 1)))) break;
- }
-
- p->status_vmshared = p->status_rssfile + p->status_rssshmem;
-
- // fprintf(stderr, "%s uid %d, gid %d, VmSize %zu, VmRSS %zu, RssFile %zu, RssShmem %zu, shared %zu\n", p->comm, (int)p->uid, (int)p->gid, p->status_vmsize, p->status_vmrss, p->status_rssfile, p->status_rssshmem, p->status_vmshared);
-
- return 1;
-#endif
-}
-
-
-// ----------------------------------------------------------------------------
-
-static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
- (void)ptr;
-
-#ifdef __FreeBSD__
- struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
-
- if (unlikely(proc_info->ki_tdflags & TDF_IDLETD))
- goto cleanup;
-#else
- static procfile *ff = NULL;
-
- if(unlikely(!p->stat_filename)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", netdata_configured_host_prefix, p->pid);
- p->stat_filename = strdupz(filename);
- }
-
- int set_quotes = (!ff)?1:0;
-
- ff = procfile_reopen(ff, p->stat_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
- if(unlikely(!ff)) goto cleanup;
-
- // if(set_quotes) procfile_set_quotes(ff, "()");
- if(unlikely(set_quotes))
- procfile_set_open_close(ff, "(", ")");
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) goto cleanup;
-#endif
-
- p->last_stat_collected_usec = p->stat_collected_usec;
- p->stat_collected_usec = now_monotonic_usec();
- calls_counter++;
-
-#ifdef __FreeBSD__
- char *comm = proc_info->ki_comm;
- p->ppid = proc_info->ki_ppid;
-#else
- // p->pid = str2pid_t(procfile_lineword(ff, 0, 0));
- char *comm = procfile_lineword(ff, 0, 1);
- // p->state = *(procfile_lineword(ff, 0, 2));
- p->ppid = (int32_t)str2pid_t(procfile_lineword(ff, 0, 3));
- // p->pgrp = (int32_t)str2pid_t(procfile_lineword(ff, 0, 4));
- // p->session = (int32_t)str2pid_t(procfile_lineword(ff, 0, 5));
- // p->tty_nr = (int32_t)str2pid_t(procfile_lineword(ff, 0, 6));
- // p->tpgid = (int32_t)str2pid_t(procfile_lineword(ff, 0, 7));
- // p->flags = str2uint64_t(procfile_lineword(ff, 0, 8));
-#endif
-
- if(strcmp(p->comm, comm) != 0) {
- if(unlikely(debug)) {
- if(p->comm[0])
- fprintf(stderr, "apps.plugin: \tpid %d (%s) changed name to '%s'\n", p->pid, p->comm, comm);
- else
- fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", p->pid, comm);
- }
-
- strncpyz(p->comm, comm, MAX_COMPARE_NAME);
-
- // /proc/<pid>/cmdline
- if(likely(proc_pid_cmdline_is_needed))
- managed_log(p, PID_LOG_CMDLINE, read_proc_pid_cmdline(p));
-
- assign_target_to_pid(p);
- }
-
-#ifdef __FreeBSD__
- pid_incremental_rate(stat, p->minflt, (kernel_uint_t)proc_info->ki_rusage.ru_minflt);
- pid_incremental_rate(stat, p->cminflt, (kernel_uint_t)proc_info->ki_rusage_ch.ru_minflt);
- pid_incremental_rate(stat, p->majflt, (kernel_uint_t)proc_info->ki_rusage.ru_majflt);
- pid_incremental_rate(stat, p->cmajflt, (kernel_uint_t)proc_info->ki_rusage_ch.ru_majflt);
- pid_incremental_rate(stat, p->utime, (kernel_uint_t)proc_info->ki_rusage.ru_utime.tv_sec * 100 + proc_info->ki_rusage.ru_utime.tv_usec / 10000);
- pid_incremental_rate(stat, p->stime, (kernel_uint_t)proc_info->ki_rusage.ru_stime.tv_sec * 100 + proc_info->ki_rusage.ru_stime.tv_usec / 10000);
- pid_incremental_rate(stat, p->cutime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_utime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000);
- pid_incremental_rate(stat, p->cstime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_stime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_stime.tv_usec / 10000);
-
- p->num_threads = proc_info->ki_numthreads;
-
- if(enable_guest_charts) {
- enable_guest_charts = 0;
- info("Guest charts aren't supported by FreeBSD");
- }
-#else
- pid_incremental_rate(stat, p->minflt, str2kernel_uint_t(procfile_lineword(ff, 0, 9)));
- pid_incremental_rate(stat, p->cminflt, str2kernel_uint_t(procfile_lineword(ff, 0, 10)));
- pid_incremental_rate(stat, p->majflt, str2kernel_uint_t(procfile_lineword(ff, 0, 11)));
- pid_incremental_rate(stat, p->cmajflt, str2kernel_uint_t(procfile_lineword(ff, 0, 12)));
- pid_incremental_rate(stat, p->utime, str2kernel_uint_t(procfile_lineword(ff, 0, 13)));
- pid_incremental_rate(stat, p->stime, str2kernel_uint_t(procfile_lineword(ff, 0, 14)));
- pid_incremental_rate(stat, p->cutime, str2kernel_uint_t(procfile_lineword(ff, 0, 15)));
- pid_incremental_rate(stat, p->cstime, str2kernel_uint_t(procfile_lineword(ff, 0, 16)));
- // p->priority = str2kernel_uint_t(procfile_lineword(ff, 0, 17));
- // p->nice = str2kernel_uint_t(procfile_lineword(ff, 0, 18));
- p->num_threads = (int32_t)str2uint32_t(procfile_lineword(ff, 0, 19));
- // p->itrealvalue = str2kernel_uint_t(procfile_lineword(ff, 0, 20));
- // p->starttime = str2kernel_uint_t(procfile_lineword(ff, 0, 21));
- // p->vsize = str2kernel_uint_t(procfile_lineword(ff, 0, 22));
- // p->rss = str2kernel_uint_t(procfile_lineword(ff, 0, 23));
- // p->rsslim = str2kernel_uint_t(procfile_lineword(ff, 0, 24));
- // p->starcode = str2kernel_uint_t(procfile_lineword(ff, 0, 25));
- // p->endcode = str2kernel_uint_t(procfile_lineword(ff, 0, 26));
- // p->startstack = str2kernel_uint_t(procfile_lineword(ff, 0, 27));
- // p->kstkesp = str2kernel_uint_t(procfile_lineword(ff, 0, 28));
- // p->kstkeip = str2kernel_uint_t(procfile_lineword(ff, 0, 29));
- // p->signal = str2kernel_uint_t(procfile_lineword(ff, 0, 30));
- // p->blocked = str2kernel_uint_t(procfile_lineword(ff, 0, 31));
- // p->sigignore = str2kernel_uint_t(procfile_lineword(ff, 0, 32));
- // p->sigcatch = str2kernel_uint_t(procfile_lineword(ff, 0, 33));
- // p->wchan = str2kernel_uint_t(procfile_lineword(ff, 0, 34));
- // p->nswap = str2kernel_uint_t(procfile_lineword(ff, 0, 35));
- // p->cnswap = str2kernel_uint_t(procfile_lineword(ff, 0, 36));
- // p->exit_signal = str2kernel_uint_t(procfile_lineword(ff, 0, 37));
- // p->processor = str2kernel_uint_t(procfile_lineword(ff, 0, 38));
- // p->rt_priority = str2kernel_uint_t(procfile_lineword(ff, 0, 39));
- // p->policy = str2kernel_uint_t(procfile_lineword(ff, 0, 40));
- // p->delayacct_blkio_ticks = str2kernel_uint_t(procfile_lineword(ff, 0, 41));
-
- if(enable_guest_charts) {
-
- pid_incremental_rate(stat, p->gtime, str2kernel_uint_t(procfile_lineword(ff, 0, 42)));
- pid_incremental_rate(stat, p->cgtime, str2kernel_uint_t(procfile_lineword(ff, 0, 43)));
-
- if (show_guest_time || p->gtime || p->cgtime) {
- p->utime -= (p->utime >= p->gtime) ? p->gtime : p->utime;
- p->cutime -= (p->cutime >= p->cgtime) ? p->cgtime : p->cutime;
- show_guest_time = 1;
- }
- }
-#endif
-
- if(unlikely(debug || (p->target && p->target->debug)))
- fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT ", threads=%d\n", netdata_configured_host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
-
- if(unlikely(global_iterations_counter == 1)) {
- p->minflt = 0;
- p->cminflt = 0;
- p->majflt = 0;
- p->cmajflt = 0;
- p->utime = 0;
- p->stime = 0;
- p->gtime = 0;
- p->cutime = 0;
- p->cstime = 0;
- p->cgtime = 0;
- }
-
- return 1;
-
-cleanup:
- p->minflt = 0;
- p->cminflt = 0;
- p->majflt = 0;
- p->cmajflt = 0;
- p->utime = 0;
- p->stime = 0;
- p->gtime = 0;
- p->cutime = 0;
- p->cstime = 0;
- p->cgtime = 0;
- p->num_threads = 0;
- // p->rss = 0;
- return 0;
-}
-
-static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
- (void)ptr;
-#ifdef __FreeBSD__
- struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
-#else
- static procfile *ff = NULL;
-
- if(unlikely(!p->io_filename)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", netdata_configured_host_prefix, p->pid);
- p->io_filename = strdupz(filename);
- }
-
- // open the file
- ff = procfile_reopen(ff, p->io_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
- if(unlikely(!ff)) goto cleanup;
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) goto cleanup;
-#endif
-
- calls_counter++;
-
- p->last_io_collected_usec = p->io_collected_usec;
- p->io_collected_usec = now_monotonic_usec();
-
-#ifdef __FreeBSD__
- pid_incremental_rate(io, p->io_storage_bytes_read, proc_info->ki_rusage.ru_inblock);
- pid_incremental_rate(io, p->io_storage_bytes_written, proc_info->ki_rusage.ru_oublock);
-#else
- pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1)));
- pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1)));
- // pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
- // pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1)));
- pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1)));
- pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1)));
- // pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
-#endif
-
- if(unlikely(global_iterations_counter == 1)) {
- p->io_logical_bytes_read = 0;
- p->io_logical_bytes_written = 0;
- // p->io_read_calls = 0;
- // p->io_write_calls = 0;
- p->io_storage_bytes_read = 0;
- p->io_storage_bytes_written = 0;
- // p->io_cancelled_write_bytes = 0;
- }
-
- return 1;
-
-#ifndef __FreeBSD__
-cleanup:
- p->io_logical_bytes_read = 0;
- p->io_logical_bytes_written = 0;
- // p->io_read_calls = 0;
- // p->io_write_calls = 0;
- p->io_storage_bytes_read = 0;
- p->io_storage_bytes_written = 0;
- // p->io_cancelled_write_bytes = 0;
- return 0;
-#endif
-}
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
-static inline int read_proc_stat() {
- static char filename[FILENAME_MAX + 1] = "";
- static procfile *ff = NULL;
- static kernel_uint_t utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0;
- static usec_t collected_usec = 0, last_collected_usec = 0;
-
- if(unlikely(!ff)) {
- snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix);
- ff = procfile_open(filename, " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) goto cleanup;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) goto cleanup;
-
- last_collected_usec = collected_usec;
- collected_usec = now_monotonic_usec();
-
- calls_counter++;
-
- // temporary - it is added global_ntime;
- kernel_uint_t global_ntime = 0;
-
- incremental_rate(global_utime, utime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 1)), collected_usec, last_collected_usec);
- incremental_rate(global_ntime, ntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 2)), collected_usec, last_collected_usec);
- incremental_rate(global_stime, stime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 3)), collected_usec, last_collected_usec);
- incremental_rate(global_gtime, gtime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 10)), collected_usec, last_collected_usec);
-
- global_utime += global_ntime;
-
- if(enable_guest_charts) {
- // temporary - it is added global_ntime;
- kernel_uint_t global_gntime = 0;
-
- // guest nice time, on guest time
- incremental_rate(global_gntime, gntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 11)), collected_usec, last_collected_usec);
-
- global_gtime += global_gntime;
-
- // remove guest time from user time
- global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
- }
-
- if(unlikely(global_iterations_counter == 1)) {
- global_utime = 0;
- global_stime = 0;
- global_gtime = 0;
- }
-
- return 1;
-
-cleanup:
- global_utime = 0;
- global_stime = 0;
- global_gtime = 0;
- return 0;
-}
-#else
-static inline int read_proc_stat() {
- return 0;
-}
-#endif
-
-// ----------------------------------------------------------------------------
-
-int file_descriptor_compare(void* a, void* b) {
-#ifdef NETDATA_INTERNAL_CHECKS
- if(((struct file_descriptor *)a)->magic != 0x0BADCAFE || ((struct file_descriptor *)b)->magic != 0x0BADCAFE)
- error("Corrupted index data detected. Please report this.");
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- if(((struct file_descriptor *)a)->hash < ((struct file_descriptor *)b)->hash)
- return -1;
-
- else if(((struct file_descriptor *)a)->hash > ((struct file_descriptor *)b)->hash)
- return 1;
-
- else
- return strcmp(((struct file_descriptor *)a)->name, ((struct file_descriptor *)b)->name);
-}
-
-int file_descriptor_iterator(avl *a) { if(a) {}; return 0; }
-
-avl_tree all_files_index = {
- NULL,
- file_descriptor_compare
-};
-
-static struct file_descriptor *file_descriptor_find(const char *name, uint32_t hash) {
- struct file_descriptor tmp;
- tmp.hash = (hash)?hash:simple_hash(name);
- tmp.name = name;
- tmp.count = 0;
- tmp.pos = 0;
-#ifdef NETDATA_INTERNAL_CHECKS
- tmp.magic = 0x0BADCAFE;
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- return (struct file_descriptor *)avl_search(&all_files_index, (avl *) &tmp);
-}
-
-#define file_descriptor_add(fd) avl_insert(&all_files_index, (avl *)(fd))
-#define file_descriptor_remove(fd) avl_remove(&all_files_index, (avl *)(fd))
-
-// ----------------------------------------------------------------------------
-
-static inline void file_descriptor_not_used(int id)
-{
- if(id > 0 && id < all_files_size) {
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(all_files[id].magic != 0x0BADCAFE) {
- error("Ignoring request to remove empty file id %d.", id);
- return;
- }
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: decreasing slot %d (count = %d).\n", id, all_files[id].count);
-
- if(all_files[id].count > 0) {
- all_files[id].count--;
-
- if(!all_files[id].count) {
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> slot %d is empty.\n", id);
-
- if(unlikely(file_descriptor_remove(&all_files[id]) != (void *)&all_files[id]))
- error("INTERNAL ERROR: removal of unused fd from index, removed a different fd");
-
-#ifdef NETDATA_INTERNAL_CHECKS
- all_files[id].magic = 0x00000000;
-#endif /* NETDATA_INTERNAL_CHECKS */
- all_files_len--;
- }
- }
- else
- error("Request to decrease counter of fd %d (%s), while the use counter is 0", id, all_files[id].name);
- }
- else error("Request to decrease counter of fd %d, which is outside the array size (1 to %d)", id, all_files_size);
-}
-
-static inline void all_files_grow() {
- void *old = all_files;
- int i;
-
- // there is no empty slot
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
-
- all_files = reallocz(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor));
-
- // if the address changed, we have to rebuild the index
- // since all pointers are now invalid
-
- if(unlikely(old && old != (void *)all_files)) {
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> re-indexing.\n");
-
- all_files_index.root = NULL;
- for(i = 0; i < all_files_size; i++) {
- if(!all_files[i].count) continue;
- if(unlikely(file_descriptor_add(&all_files[i]) != (void *)&all_files[i]))
- error("INTERNAL ERROR: duplicate indexing of fd during realloc.");
- }
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
- }
-
- // initialize the newly added entries
-
- for(i = all_files_size; i < (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); i++) {
- all_files[i].count = 0;
- all_files[i].name = NULL;
-#ifdef NETDATA_INTERNAL_CHECKS
- all_files[i].magic = 0x00000000;
-#endif /* NETDATA_INTERNAL_CHECKS */
- all_files[i].pos = i;
- }
-
- if(unlikely(!all_files_size)) all_files_len = 1;
- all_files_size += FILE_DESCRIPTORS_INCREASE_STEP;
-}
-
-static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t hash, FD_FILETYPE type) {
- // check we have enough memory to add it
- if(!all_files || all_files_len == all_files_size)
- all_files_grow();
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> searching for empty slot.\n");
-
- // search for an empty slot
-
- static int last_pos = 0;
- int i, c;
- for(i = 0, c = last_pos ; i < all_files_size ; i++, c++) {
- if(c >= all_files_size) c = 0;
- if(c == 0) continue;
-
- if(!all_files[c].count) {
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> Examining slot %d.\n", c);
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(all_files[c].magic == 0x0BADCAFE && all_files[c].name && file_descriptor_find(all_files[c].name, all_files[c].hash))
- error("fd on position %d is not cleared properly. It still has %s in it.\n", c, all_files[c].name);
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
-
- freez((void *)all_files[c].name);
- all_files[c].name = NULL;
- last_pos = c;
- break;
- }
- }
-
- all_files_len++;
-
- if(i == all_files_size) {
- fatal("We should find an empty slot, but there isn't any");
- exit(1);
- }
- // else we have an empty slot in 'c'
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c);
-
- all_files[c].name = strdupz(name);
- all_files[c].hash = hash;
- all_files[c].type = type;
- all_files[c].pos = c;
- all_files[c].count = 1;
-#ifdef NETDATA_INTERNAL_CHECKS
- all_files[c].magic = 0x0BADCAFE;
-#endif /* NETDATA_INTERNAL_CHECKS */
- if(unlikely(file_descriptor_add(&all_files[c]) != (void *)&all_files[c]))
- error("INTERNAL ERROR: duplicate indexing of fd.");
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
-
- return c;
-}
-
-static inline int file_descriptor_find_or_add(const char *name)
-{
- uint32_t hash = simple_hash(name);
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
-
- struct file_descriptor *fd = file_descriptor_find(name, hash);
- if(fd) {
- // found
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
-
- fd->count++;
- return fd->pos;
- }
- // not found
-
- FD_FILETYPE type;
- if(likely(name[0] == '/')) type = FILETYPE_FILE;
- else if(likely(strncmp(name, "pipe:", 5) == 0)) type = FILETYPE_PIPE;
- else if(likely(strncmp(name, "socket:", 7) == 0)) type = FILETYPE_SOCKET;
- else if(likely(strncmp(name, "anon_inode:", 11) == 0)) {
- const char *t = &name[11];
-
- if(strcmp(t, "inotify") == 0) type = FILETYPE_INOTIFY;
- else if(strcmp(t, "[eventfd]") == 0) type = FILETYPE_EVENTFD;
- else if(strcmp(t, "[eventpoll]") == 0) type = FILETYPE_EVENTPOLL;
- else if(strcmp(t, "[timerfd]") == 0) type = FILETYPE_TIMERFD;
- else if(strcmp(t, "[signalfd]") == 0) type = FILETYPE_SIGNALFD;
- else {
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: FIXME: unknown anonymous inode: %s\n", name);
-
- type = FILETYPE_OTHER;
- }
- }
- else if(likely(strcmp(name, "inotify") == 0)) type = FILETYPE_INOTIFY;
- else {
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: FIXME: cannot understand linkname: %s\n", name);
-
- type = FILETYPE_OTHER;
- }
-
- return file_descriptor_set_on_empty_slot(name, hash, type);
-}
-
-static inline void make_all_pid_fds_negative(struct pid_stat *p) {
- int *fd = p->fds, *end = &p->fds[p->fds_size];
- while(fd < end) {
- *fd = -(*fd);
- fd++;
- }
-}
-
-static inline void cleanup_negative_pid_fds(struct pid_stat *p) {
- int *fd = p->fds, *fdend = &p->fds[p->fds_size];
-
- while(fd < fdend) {
- if(unlikely(*fd < 0)) {
- file_descriptor_not_used(-(*fd));
- *fd++ = 0;
- }
- else
- fd++;
- }
-}
-
-static inline void zero_pid_fds(struct pid_stat *p, int first, int size) {
- int *fd = &p->fds[first], *end = &p->fds[first + size];
- while(fd < end) *fd++ = 0;
-}
-
-static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
- (void)ptr;
-#ifdef __FreeBSD__
- int mib[4];
- size_t size;
- struct kinfo_file *fds;
- static char *fdsbuf;
- char *bfdsbuf, *efdsbuf;
- char fdsname[FILENAME_MAX + 1];
-
- // we make all pid fds negative, so that
- // we can detect unused file descriptors
- // at the end, to free them
- make_all_pid_fds_negative(p);
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_FILEDESC;
- mib[3] = p->pid;
-
- if (unlikely(sysctl(mib, 4, NULL, &size, NULL, 0))) {
- error("sysctl error: Can't get file descriptors data size for pid %d", p->pid);
- return 0;
- }
- if (likely(size > 0))
- fdsbuf = reallocz(fdsbuf, size);
- if (unlikely(sysctl(mib, 4, fdsbuf, &size, NULL, 0))) {
- error("sysctl error: Can't get file descriptors data for pid %d", p->pid);
- return 0;
- }
-
- bfdsbuf = fdsbuf;
- efdsbuf = fdsbuf + size;
- while (bfdsbuf < efdsbuf) {
- fds = (struct kinfo_file *)(uintptr_t)bfdsbuf;
- if (unlikely(fds->kf_structsize == 0))
- break;
-
- // do not process file descriptors for current working directory, root directory,
- // jail directory, ktrace vnode, text vnode and controlling terminal
- if (unlikely(fds->kf_fd < 0)) {
- bfdsbuf += fds->kf_structsize;
- continue;
- }
-
- // get file descriptors array index
- int fdid = fds->kf_fd;
-
- // check if the fds array is small
- if (unlikely(fdid >= p->fds_size)) {
- // it is small, extend it
-
- if (unlikely(debug))
- fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS);
-
- p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int));
-
- // and initialize it
- zero_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size);
- p->fds_size = fdid + MAX_SPARE_FDS;
- }
-
- if (unlikely(p->fds[fdid] == 0)) {
- // we don't know this fd, get it
-
- switch (fds->kf_type) {
- case KF_TYPE_FIFO:
- case KF_TYPE_VNODE:
- if (unlikely(!fds->kf_path[0])) {
- sprintf(fdsname, "other: inode: %lu", fds->kf_un.kf_file.kf_file_fileid);
- break;
- }
- sprintf(fdsname, "%s", fds->kf_path);
- break;
- case KF_TYPE_SOCKET:
- switch (fds->kf_sock_domain) {
- case AF_INET:
- case AF_INET6:
- if (fds->kf_sock_protocol == IPPROTO_TCP)
- sprintf(fdsname, "socket: %d %lx", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sock_inpcb);
- else
- sprintf(fdsname, "socket: %d %lx", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sock_pcb);
- break;
- case AF_UNIX:
- /* print address of pcb and connected pcb */
- sprintf(fdsname, "socket: %lx %lx", fds->kf_un.kf_sock.kf_sock_pcb, fds->kf_un.kf_sock.kf_sock_unpconn);
- break;
- default:
- /* print protocol number and socket address */
-#if __FreeBSD_version < 1200031
- sprintf(fdsname, "socket: other: %d %s %s", fds->kf_sock_protocol, fds->kf_sa_local.__ss_pad1, fds->kf_sa_local.__ss_pad2);
-#else
- sprintf(fdsname, "socket: other: %d %s %s", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sa_local.__ss_pad1, fds->kf_un.kf_sock.kf_sa_local.__ss_pad2);
-#endif
- }
- break;
- case KF_TYPE_PIPE:
- sprintf(fdsname, "pipe: %lu %lu", fds->kf_un.kf_pipe.kf_pipe_addr, fds->kf_un.kf_pipe.kf_pipe_peer);
- break;
- case KF_TYPE_PTS:
-#if __FreeBSD_version < 1200031
- sprintf(fdsname, "other: pts: %u", fds->kf_un.kf_pts.kf_pts_dev);
-#else
- sprintf(fdsname, "other: pts: %lu", fds->kf_un.kf_pts.kf_pts_dev);
-#endif
- break;
- case KF_TYPE_SHM:
- sprintf(fdsname, "other: shm: %s size: %lu", fds->kf_path, fds->kf_un.kf_file.kf_file_size);
- break;
- case KF_TYPE_SEM:
- sprintf(fdsname, "other: sem: %u", fds->kf_un.kf_sem.kf_sem_value);
- break;
- default:
- sprintf(fdsname, "other: pid: %d fd: %d", fds->kf_un.kf_proc.kf_pid, fds->kf_fd);
- }
-
- // if another process already has this, we will get
- // the same id
- p->fds[fdid] = file_descriptor_find_or_add(fdsname);
- }
-
- // else make it positive again, we need it
- // of course, the actual file may have changed, but we don't care so much
- // FIXME: we could compare the inode as returned by readdir dirent structure
-
- else
- p->fds[fdid] = -p->fds[fdid];
-
- bfdsbuf += fds->kf_structsize;
- }
-#else
- if(unlikely(!p->fds_dirname)) {
- char dirname[FILENAME_MAX+1];
- snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", netdata_configured_host_prefix, p->pid);
- p->fds_dirname = strdupz(dirname);
- }
-
- DIR *fds = opendir(p->fds_dirname);
- if(unlikely(!fds)) return 0;
-
- struct dirent *de;
- char fdname[FILENAME_MAX + 1];
- char linkname[FILENAME_MAX + 1];
-
- // we make all pid fds negative, so that
- // we can detect unused file descriptors
- // at the end, to free them
- make_all_pid_fds_negative(p);
-
- while((de = readdir(fds))) {
- // we need only files with numeric names
-
- if(unlikely(de->d_name[0] < '0' || de->d_name[0] > '9'))
- continue;
-
- // get its number
- int fdid = (int) str2l(de->d_name);
- if(unlikely(fdid < 0)) continue;
-
- // check if the fds array is small
- if(unlikely(fdid >= p->fds_size)) {
- // it is small, extend it
-
- if(unlikely(debug))
- fprintf(stderr
- , "apps.plugin: extending fd memory slots for %s from %d to %d\n"
- , p->comm
- , p->fds_size
- , fdid + MAX_SPARE_FDS
- );
-
- p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int));
-
- // and initialize it
- zero_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size);
- p->fds_size = fdid + MAX_SPARE_FDS;
- }
-
- if(unlikely(p->fds[fdid] == 0)) {
- // we don't know this fd, get it
-
- sprintf(fdname, "%s/proc/%d/fd/%s", netdata_configured_host_prefix, p->pid, de->d_name);
- ssize_t l = readlink(fdname, linkname, FILENAME_MAX);
- if(unlikely(l == -1)) {
- if(debug || (p->target && p->target->debug)) {
- if(debug || (p->target && p->target->debug))
- error("Cannot read link %s", fdname);
- }
- continue;
- }
- else
- linkname[l] = '\0';
-
- file_counter++;
-
- // if another process already has this, we will get
- // the same id
- p->fds[fdid] = file_descriptor_find_or_add(linkname);
- }
-
- // else make it positive again, we need it
- // of course, the actual file may have changed, but we don't care so much
- // FIXME: we could compare the inode as returned by readdir dirent structure
- // UPDATE: no we cannot use inodes - under /proc inodes don't change when the link is changed
-
- else
- p->fds[fdid] = -p->fds[fdid];
- }
-
- closedir(fds);
-#endif
- cleanup_negative_pid_fds(p);
-
- return 1;
-}
-
-// ----------------------------------------------------------------------------
-
-static inline int print_process_and_parents(struct pid_stat *p, usec_t time) {
- char *prefix = "\\_ ";
- int indent = 0;
-
- if(p->parent)
- indent = print_process_and_parents(p->parent, p->stat_collected_usec);
- else
- prefix = " > ";
-
- char buffer[indent + 1];
- int i;
-
- for(i = 0; i < indent ;i++) buffer[i] = ' ';
- buffer[i] = '\0';
-
- fprintf(stderr, " %s %s%s (%d %s %llu"
- , buffer
- , prefix
- , p->comm
- , p->pid
- , p->updated?"running":"exited"
- , p->stat_collected_usec - time
- );
-
- if(p->utime) fprintf(stderr, " utime=" KERNEL_UINT_FORMAT, p->utime);
- if(p->stime) fprintf(stderr, " stime=" KERNEL_UINT_FORMAT, p->stime);
- if(p->gtime) fprintf(stderr, " gtime=" KERNEL_UINT_FORMAT, p->gtime);
- if(p->cutime) fprintf(stderr, " cutime=" KERNEL_UINT_FORMAT, p->cutime);
- if(p->cstime) fprintf(stderr, " cstime=" KERNEL_UINT_FORMAT, p->cstime);
- if(p->cgtime) fprintf(stderr, " cgtime=" KERNEL_UINT_FORMAT, p->cgtime);
- if(p->minflt) fprintf(stderr, " minflt=" KERNEL_UINT_FORMAT, p->minflt);
- if(p->cminflt) fprintf(stderr, " cminflt=" KERNEL_UINT_FORMAT, p->cminflt);
- if(p->majflt) fprintf(stderr, " majflt=" KERNEL_UINT_FORMAT, p->majflt);
- if(p->cmajflt) fprintf(stderr, " cmajflt=" KERNEL_UINT_FORMAT, p->cmajflt);
- fprintf(stderr, ")\n");
-
- return indent + 1;
-}
-
-static inline void print_process_tree(struct pid_stat *p, char *msg) {
- fprintf(stderr, "%s: process %s (%d, %s) with parents:\n", msg, p->comm, p->pid, p->updated?"running":"exited");
- print_process_and_parents(p, p->stat_collected_usec);
-}
-
-static inline void find_lost_child_debug(struct pid_stat *pe, kernel_uint_t lost, int type) {
- int found = 0;
- struct pid_stat *p = NULL;
-
- for(p = root_of_pids; p ; p = p->next) {
- if(p == pe) continue;
-
- switch(type) {
- case 1:
- if(p->cminflt > lost) {
- fprintf(stderr, " > process %d (%s) could use the lost exited child minflt " KERNEL_UINT_FORMAT " of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
- found++;
- }
- break;
-
- case 2:
- if(p->cmajflt > lost) {
- fprintf(stderr, " > process %d (%s) could use the lost exited child majflt " KERNEL_UINT_FORMAT " of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
- found++;
- }
- break;
-
- case 3:
- if(p->cutime > lost) {
- fprintf(stderr, " > process %d (%s) could use the lost exited child utime " KERNEL_UINT_FORMAT " of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
- found++;
- }
- break;
-
- case 4:
- if(p->cstime > lost) {
- fprintf(stderr, " > process %d (%s) could use the lost exited child stime " KERNEL_UINT_FORMAT " of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
- found++;
- }
- break;
-
- case 5:
- if(p->cgtime > lost) {
- fprintf(stderr, " > process %d (%s) could use the lost exited child gtime " KERNEL_UINT_FORMAT " of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
- found++;
- }
- break;
- }
- }
-
- if(!found) {
- switch(type) {
- case 1:
- fprintf(stderr, " > cannot find any process to use the lost exited child minflt " KERNEL_UINT_FORMAT " of process %d (%s)\n", lost, pe->pid, pe->comm);
- break;
-
- case 2:
- fprintf(stderr, " > cannot find any process to use the lost exited child majflt " KERNEL_UINT_FORMAT " of process %d (%s)\n", lost, pe->pid, pe->comm);
- break;
-
- case 3:
- fprintf(stderr, " > cannot find any process to use the lost exited child utime " KERNEL_UINT_FORMAT " of process %d (%s)\n", lost, pe->pid, pe->comm);
- break;
-
- case 4:
- fprintf(stderr, " > cannot find any process to use the lost exited child stime " KERNEL_UINT_FORMAT " of process %d (%s)\n", lost, pe->pid, pe->comm);
- break;
-
- case 5:
- fprintf(stderr, " > cannot find any process to use the lost exited child gtime " KERNEL_UINT_FORMAT " of process %d (%s)\n", lost, pe->pid, pe->comm);
- break;
- }
- }
-}
-
-static inline kernel_uint_t remove_exited_child_from_parent(kernel_uint_t *field, kernel_uint_t *pfield) {
- kernel_uint_t absorbed = 0;
-
- if(*field > *pfield) {
- absorbed += *pfield;
- *field -= *pfield;
- *pfield = 0;
- }
- else {
- absorbed += *field;
- *pfield -= *field;
- *field = 0;
- }
-
- return absorbed;
-}
-
-static inline void process_exited_processes() {
- struct pid_stat *p;
-
- for(p = root_of_pids; p ; p = p->next) {
- if(p->updated || !p->stat_collected_usec)
- continue;
-
- kernel_uint_t utime = (p->utime_raw + p->cutime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t stime = (p->stime_raw + p->cstime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t gtime = (p->gtime_raw + p->cgtime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t minflt = (p->minflt_raw + p->cminflt_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t majflt = (p->majflt_raw + p->cmajflt_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- if(utime + stime + gtime + minflt + majflt == 0)
- continue;
-
- if(unlikely(debug)) {
- fprintf(stderr, "Absorb %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")\n"
- , p->comm
- , p->pid
- , p->updated?"running":"exited"
- , utime
- , stime
- , gtime
- , minflt
- , majflt
- );
- print_process_tree(p, "Searching parents");
- }
-
- struct pid_stat *pp;
- for(pp = p->parent; pp ; pp = pp->parent) {
- if(!pp->updated) continue;
-
- kernel_uint_t absorbed;
- absorbed = remove_exited_child_from_parent(&utime, &pp->cutime);
- if(unlikely(debug && absorbed))
- fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " utime (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, utime);
-
- absorbed = remove_exited_child_from_parent(&stime, &pp->cstime);
- if(unlikely(debug && absorbed))
- fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " stime (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, stime);
-
- absorbed = remove_exited_child_from_parent(&gtime, &pp->cgtime);
- if(unlikely(debug && absorbed))
- fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " gtime (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, gtime);
-
- absorbed = remove_exited_child_from_parent(&minflt, &pp->cminflt);
- if(unlikely(debug && absorbed))
- fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " minflt (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, minflt);
-
- absorbed = remove_exited_child_from_parent(&majflt, &pp->cmajflt);
- if(unlikely(debug && absorbed))
- fprintf(stderr, " > process %s (%d %s) absorbed " KERNEL_UINT_FORMAT " majflt (remaining: " KERNEL_UINT_FORMAT ")\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, majflt);
- }
-
- if(unlikely(utime + stime + gtime + minflt + majflt > 0)) {
- if(unlikely(debug)) {
- if(utime) find_lost_child_debug(p, utime, 3);
- if(stime) find_lost_child_debug(p, stime, 4);
- if(gtime) find_lost_child_debug(p, gtime, 5);
- if(minflt) find_lost_child_debug(p, minflt, 1);
- if(majflt) find_lost_child_debug(p, majflt, 2);
- }
-
- p->keep = 1;
-
- if(unlikely(debug))
- fprintf(stderr, " > remaining resources - KEEP - for another loop: %s (%d %s total resources: utime=" KERNEL_UINT_FORMAT " stime=" KERNEL_UINT_FORMAT " gtime=" KERNEL_UINT_FORMAT " minflt=" KERNEL_UINT_FORMAT " majflt=" KERNEL_UINT_FORMAT ")\n"
- , p->comm
- , p->pid
- , p->updated?"running":"exited"
- , utime
- , stime
- , gtime
- , minflt
- , majflt
- );
-
- for(pp = p->parent; pp ; pp = pp->parent) {
- if(pp->updated) break;
- pp->keep = 1;
-
- if(unlikely(debug))
- fprintf(stderr, " > - KEEP - parent for another loop: %s (%d %s)\n"
- , pp->comm
- , pp->pid
- , pp->updated?"running":"exited"
- );
- }
-
- p->utime_raw = utime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
- p->stime_raw = stime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
- p->gtime_raw = gtime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
- p->minflt_raw = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
- p->majflt_raw = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
- p->cutime_raw = p->cstime_raw = p->cgtime_raw = p->cminflt_raw = p->cmajflt_raw = 0;
-
- if(unlikely(debug))
- fprintf(stderr, "\n");
- }
- else if(unlikely(debug)) {
- fprintf(stderr, " > totally absorbed - DONE - %s (%d %s)\n"
- , p->comm
- , p->pid
- , p->updated?"running":"exited"
- );
- }
- }
-}
-
-static inline void link_all_processes_to_their_parents(void) {
- struct pid_stat *p, *pp;
-
- // link all children to their parents
- // and update children count on parents
- for(p = root_of_pids; p ; p = p->next) {
- // for each process found
-
- p->sortlist = 0;
- p->parent = NULL;
-
- if(unlikely(!p->ppid)) {
- p->parent = NULL;
- continue;
- }
-
- pp = all_pids[p->ppid];
- if(likely(pp)) {
- p->parent = pp;
- pp->children_count++;
-
- if(unlikely(debug || (p->target && p->target->debug)))
- fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) on target '%s' has parent %d (%s, %s). Parent: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", gtime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", cgtime=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT "\n", p->pid, p->comm, p->updated?"running":"exited", (p->target)?p->target->name:"UNSET", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->gtime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cgtime, pp->cminflt, pp->cmajflt);
- }
- else {
- p->parent = NULL;
- error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-
-// 1. read all files in /proc
-// 2. for each numeric directory:
-// i. read /proc/pid/stat
-// ii. read /proc/pid/status
-// iii. read /proc/pid/io (requires root access)
-// iii. read the entries in directory /proc/pid/fd (requires root access)
-// for each entry:
-// a. find or create a struct file_descriptor
-// b. cleanup any old/unused file_descriptors
-
-// after all these, some pids may be linked to targets, while others may not
-
-// in case of errors, only 1 every 1000 errors is printed
-// to avoid filling up all disk space
-// if debug is enabled, all errors are printed
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
-static int compar_pid(const void *pid1, const void *pid2) {
-
- struct pid_stat *p1 = all_pids[*((pid_t *)pid1)];
- struct pid_stat *p2 = all_pids[*((pid_t *)pid2)];
-
- if(p1->sortlist > p2->sortlist)
- return -1;
- else
- return 1;
-}
-#endif
-
-static inline int collect_data_for_pid(pid_t pid, void *ptr) {
- if(unlikely(pid < 0 || pid > pid_max)) {
- error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, 0, pid_max);
- return 0;
- }
-
- struct pid_stat *p = get_pid_entry(pid);
- if(unlikely(!p || p->read)) return 0;
- p->read = 1;
-
- // fprintf(stderr, "Reading process %d (%s), sortlist %d\n", p->pid, p->comm, p->sortlist);
-
- // --------------------------------------------------------------------
- // /proc/<pid>/stat
-
- if(unlikely(!managed_log(p, PID_LOG_STAT, read_proc_pid_stat(p, ptr))))
- // there is no reason to proceed if we cannot get its status
- return 0;
-
- // check its parent pid
- if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
- error("Pid %d (command '%s') states invalid parent pid %d. Using 0.", pid, p->comm, p->ppid);
- p->ppid = 0;
- }
-
- // --------------------------------------------------------------------
- // /proc/<pid>/io
-
- managed_log(p, PID_LOG_IO, read_proc_pid_io(p, ptr));
-
- // --------------------------------------------------------------------
- // /proc/<pid>/status
-
- if(unlikely(!managed_log(p, PID_LOG_STATUS, read_proc_pid_status(p, ptr))))
- // there is no reason to proceed if we cannot get its status
- return 0;
-
- // --------------------------------------------------------------------
- // /proc/<pid>/fd
-
- if(enable_file_charts)
- managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p, ptr));
-
- // --------------------------------------------------------------------
- // done!
-
- if(unlikely(debug && include_exited_childs && all_pids_count && p->ppid && all_pids[p->ppid] && !all_pids[p->ppid]->read))
- fprintf(stderr, "Read process %d (%s) sortlisted %d, but its parent %d (%s) sortlisted %d, is not read\n", p->pid, p->comm, p->sortlist, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm, all_pids[p->ppid]->sortlist);
-
- // mark it as updated
- p->updated = 1;
- p->keep = 0;
- p->keeploops = 0;
-
- return 1;
-}
-
-static int collect_data_for_all_processes(void) {
- struct pid_stat *p = NULL;
-
-#ifdef __FreeBSD__
- int i, procnum;
-
- static size_t procbase_size = 0;
- static struct kinfo_proc *procbase = NULL;
-
- size_t new_procbase_size;
-
- int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC };
- if (unlikely(sysctl(mib, 3, NULL, &new_procbase_size, NULL, 0))) {
- error("sysctl error: Can't get processes data size");
- return 0;
- }
-
- // give it some air for processes that may be started
- // during this little time.
- new_procbase_size += 100 * sizeof(struct kinfo_proc);
-
- // increase the buffer if needed
- if(new_procbase_size > procbase_size) {
- procbase_size = new_procbase_size;
- procbase = reallocz(procbase, procbase_size);
- }
-
- // sysctl() gets from new_procbase_size the buffer size
- // and also returns to it the amount of data filled in
- new_procbase_size = procbase_size;
-
- // get the processes from the system
- if (unlikely(sysctl(mib, 3, procbase, &new_procbase_size, NULL, 0))) {
- error("sysctl error: Can't get processes data");
- return 0;
- }
-
- // based on the amount of data filled in
- // calculate the number of processes we got
- procnum = new_procbase_size / sizeof(struct kinfo_proc);
-
-#endif
-
- if(all_pids_count) {
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
- size_t slc = 0;
-#endif
- for(p = root_of_pids; p ; p = p->next) {
- p->read = 0; // mark it as not read, so that collect_data_for_pid() will read it
- p->updated = 0;
- p->merged = 0;
- p->children_count = 0;
- p->parent = NULL;
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
- all_pids_sortlist[slc++] = p->pid;
-#endif
- }
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
- if(unlikely(slc != all_pids_count)) {
- error("Internal error: I was thinking I had %zu processes in my arrays, but it seems there are %zu.", all_pids_count, slc);
- all_pids_count = slc;
- }
-
- if(include_exited_childs) {
- // Read parents before childs
- // This is needed to prevent a situation where
- // a child is found running, but until we read
- // its parent, it has exited and its parent
- // has accumulated its resources.
-
- qsort((void *)all_pids_sortlist, (size_t)all_pids_count, sizeof(pid_t), compar_pid);
-
- // we forward read all running processes
- // collect_data_for_pid() is smart enough,
- // not to read the same pid twice per iteration
- for(slc = 0; slc < all_pids_count; slc++)
- collect_data_for_pid(all_pids_sortlist[slc], NULL);
- }
-#endif
- }
-
-#ifdef __FreeBSD__
- for (i = 0 ; i < procnum ; ++i) {
- pid_t pid = procbase[i].ki_pid;
- collect_data_for_pid(pid, &procbase[i]);
- }
-#else
- char dirname[FILENAME_MAX + 1];
-
- snprintfz(dirname, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
- DIR *dir = opendir(dirname);
- if(!dir) return 0;
-
- struct dirent *de = NULL;
-
- while((de = readdir(dir))) {
- char *endptr = de->d_name;
-
- if(unlikely(de->d_type != DT_DIR || de->d_name[0] < '0' || de->d_name[0] > '9'))
- continue;
-
- pid_t pid = (pid_t) strtoul(de->d_name, &endptr, 10);
-
- // make sure we read a valid number
- if(unlikely(endptr == de->d_name || *endptr != '\0'))
- continue;
-
- collect_data_for_pid(pid, NULL);
- }
- closedir(dir);
-#endif
-
- if(!all_pids_count)
- return 0;
-
- // we need /proc/stat to normalize the cpu consumption of the exited childs
- read_proc_stat();
-
- // build the process tree
- link_all_processes_to_their_parents();
-
- // normally this is done
- // however we may have processes exited while we collected values
- // so let's find the exited ones
- // we do this by collecting the ownership of process
- // if we manage to get the ownership, the process still runs
- process_exited_processes();
-
- return 1;
-}
-
-// ----------------------------------------------------------------------------
-// update statistics on the targets
-
-// 1. link all childs to their parents
-// 2. go from bottom to top, marking as merged all childs to their parents
-// this step links all parents without a target to the child target, if any
-// 3. link all top level processes (the ones not merged) to the default target
-// 4. go from top to bottom, linking all childs without a target, to their parent target
-// after this step, all processes have a target
-// [5. for each killed pid (updated = 0), remove its usage from its target]
-// 6. zero all apps_groups_targets
-// 7. concentrate all values on the apps_groups_targets
-// 8. remove all killed processes
-// 9. find the unique file count for each target
-// check: update_apps_groups_statistics()
-
-static void cleanup_exited_pids(void) {
- int c;
- struct pid_stat *p = NULL;
-
- for(p = root_of_pids; p ;) {
- if(!p->updated && (!p->keep || p->keeploops > 0)) {
- if(unlikely(debug && (p->keep || p->keeploops)))
- fprintf(stderr, " > CLEANUP cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm);
-
- for(c = 0; c < p->fds_size; c++)
- if(p->fds[c] > 0) {
- file_descriptor_not_used(p->fds[c]);
- p->fds[c] = 0;
- }
-
- pid_t r = p->pid;
- p = p->next;
- del_pid_entry(r);
- }
- else {
- if(unlikely(p->keep)) p->keeploops++;
- p->keep = 0;
- p = p->next;
- }
- }
-}
-
-static void apply_apps_groups_targets_inheritance(void) {
- struct pid_stat *p = NULL;
-
- // children that do not have a target
- // inherit their target from their parent
- int found = 1, loops = 0;
- while(found) {
- if(unlikely(debug)) loops++;
- found = 0;
- for(p = root_of_pids; p ; p = p->next) {
- // if this process does not have a target
- // and it has a parent
- // and its parent has a target
- // then, set the parent's target to this process
- if(unlikely(!p->target && p->parent && p->parent->target)) {
- p->target = p->parent->target;
- found++;
-
- if(debug || (p->target && p->target->debug))
- fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s).\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
- }
- }
- }
-
- // find all the procs with 0 childs and merge them to their parents
- // repeat, until nothing more can be done.
- int sortlist = 1;
- found = 1;
- while(found) {
- if(unlikely(debug)) loops++;
- found = 0;
-
- for(p = root_of_pids; p ; p = p->next) {
- if(unlikely(!p->sortlist && !p->children_count))
- p->sortlist = sortlist++;
-
- if(unlikely(
- !p->children_count // if this process does not have any children
- && !p->merged // and is not already merged
- && p->parent // and has a parent
- && p->parent->children_count // and its parent has children
- // and the target of this process and its parent is the same,
- // or the parent does not have a target
- && (p->target == p->parent->target || !p->parent->target)
- && p->ppid != INIT_PID // and its parent is not init
- )) {
- // mark it as merged
- p->parent->children_count--;
- p->merged = 1;
-
- // the parent inherits the child's target, if it does not have a target itself
- if(unlikely(p->target && !p->parent->target)) {
- p->parent->target = p->target;
-
- if(debug || (p->target && p->target->debug))
- fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its child %d (%s).\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
- }
-
- found++;
- }
- }
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: TARGET INHERITANCE: merged %d processes\n", found);
- }
-
- // init goes always to default target
- if(all_pids[INIT_PID])
- all_pids[INIT_PID]->target = apps_groups_default_target;
-
- // pid 0 goes always to default target
- if(all_pids[0])
- all_pids[0]->target = apps_groups_default_target;
-
- // give a default target on all top level processes
- if(unlikely(debug)) loops++;
- for(p = root_of_pids; p ; p = p->next) {
- // if the process is not merged itself
- // then is is a top level process
- if(unlikely(!p->merged && !p->target))
- p->target = apps_groups_default_target;
-
- // make sure all processes have a sortlist
- if(unlikely(!p->sortlist))
- p->sortlist = sortlist++;
- }
-
- if(all_pids[1])
- all_pids[1]->sortlist = sortlist++;
-
- // give a target to all merged child processes
- found = 1;
- while(found) {
- if(unlikely(debug)) loops++;
- found = 0;
- for(p = root_of_pids; p ; p = p->next) {
- if(unlikely(!p->target && p->merged && p->parent && p->parent->target)) {
- p->target = p->parent->target;
- found++;
-
- if(debug || (p->target && p->target->debug))
- fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s) at phase 2.\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
- }
- }
- }
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: apply_apps_groups_targets_inheritance() made %d loops on the process tree\n", loops);
-}
-
-static size_t zero_all_targets(struct target *root) {
- struct target *w;
- size_t count = 0;
-
- for (w = root; w ; w = w->next) {
- count++;
-
- w->minflt = 0;
- w->majflt = 0;
- w->utime = 0;
- w->stime = 0;
- w->gtime = 0;
- w->cminflt = 0;
- w->cmajflt = 0;
- w->cutime = 0;
- w->cstime = 0;
- w->cgtime = 0;
- w->num_threads = 0;
- // w->rss = 0;
- w->processes = 0;
-
- w->status_vmsize = 0;
- w->status_vmrss = 0;
- w->status_vmshared = 0;
- w->status_rssfile = 0;
- w->status_rssshmem = 0;
- w->status_vmswap = 0;
-
- w->io_logical_bytes_read = 0;
- w->io_logical_bytes_written = 0;
- // w->io_read_calls = 0;
- // w->io_write_calls = 0;
- w->io_storage_bytes_read = 0;
- w->io_storage_bytes_written = 0;
- // w->io_cancelled_write_bytes = 0;
-
- // zero file counters
- if(w->target_fds) {
- memset(w->target_fds, 0, sizeof(int) * w->target_fds_size);
- w->openfiles = 0;
- w->openpipes = 0;
- w->opensockets = 0;
- w->openinotifies = 0;
- w->openeventfds = 0;
- w->opentimerfds = 0;
- w->opensignalfds = 0;
- w->openeventpolls = 0;
- w->openother = 0;
- }
- }
-
- return count;
-}
-
-static inline void reallocate_target_fds(struct target *w) {
- if(unlikely(!w))
- return;
-
- if(unlikely(!w->target_fds || w->target_fds_size < all_files_size)) {
- w->target_fds = reallocz(w->target_fds, sizeof(int) * all_files_size);
- memset(&w->target_fds[w->target_fds_size], 0, sizeof(int) * (all_files_size - w->target_fds_size));
- w->target_fds_size = all_files_size;
- }
-}
-
-static inline void aggregate_fd_on_target(int fd, struct target *w) {
- if(unlikely(!w))
- return;
-
- if(unlikely(w->target_fds[fd])) {
- // it is already aggregated
- // just increase its usage counter
- w->target_fds[fd]++;
- return;
- }
-
- // increase its usage counter
- // so that we will not add it again
- w->target_fds[fd]++;
-
- switch(all_files[fd].type) {
- case FILETYPE_FILE:
- w->openfiles++;
- break;
-
- case FILETYPE_PIPE:
- w->openpipes++;
- break;
-
- case FILETYPE_SOCKET:
- w->opensockets++;
- break;
-
- case FILETYPE_INOTIFY:
- w->openinotifies++;
- break;
-
- case FILETYPE_EVENTFD:
- w->openeventfds++;
- break;
-
- case FILETYPE_TIMERFD:
- w->opentimerfds++;
- break;
-
- case FILETYPE_SIGNALFD:
- w->opensignalfds++;
- break;
-
- case FILETYPE_EVENTPOLL:
- w->openeventpolls++;
- break;
-
- case FILETYPE_OTHER:
- w->openother++;
- break;
- }
-}
-
-static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) {
-
- if(unlikely(!p->updated)) {
- // the process is not running
- return;
- }
-
- struct target *w = p->target, *u = p->user_target, *g = p->group_target;
-
- reallocate_target_fds(w);
- reallocate_target_fds(u);
- reallocate_target_fds(g);
-
- int c, size = p->fds_size, *fds = p->fds;
- for(c = 0; c < size ;c++) {
- int fd = fds[c];
-
- if(likely(fd <= 0 || fd >= all_files_size))
- continue;
-
- aggregate_fd_on_target(fd, w);
- aggregate_fd_on_target(fd, u);
- aggregate_fd_on_target(fd, g);
- }
-}
-
-static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target *o) {
- (void)o;
-
- if(unlikely(!p->updated)) {
- // the process is not running
- return;
- }
-
- if(unlikely(!w)) {
- error("pid %d %s was left without a target!", p->pid, p->comm);
- return;
- }
-
- w->cutime += p->cutime;
- w->cstime += p->cstime;
- w->cgtime += p->cgtime;
- w->cminflt += p->cminflt;
- w->cmajflt += p->cmajflt;
-
- w->utime += p->utime;
- w->stime += p->stime;
- w->gtime += p->gtime;
- w->minflt += p->minflt;
- w->majflt += p->majflt;
-
- // w->rss += p->rss;
-
- w->status_vmsize += p->status_vmsize;
- w->status_vmrss += p->status_vmrss;
- w->status_vmshared += p->status_vmshared;
- w->status_rssfile += p->status_rssfile;
- w->status_rssshmem += p->status_rssshmem;
- w->status_vmswap += p->status_vmswap;
-
- w->io_logical_bytes_read += p->io_logical_bytes_read;
- w->io_logical_bytes_written += p->io_logical_bytes_written;
- // w->io_read_calls += p->io_read_calls;
- // w->io_write_calls += p->io_write_calls;
- w->io_storage_bytes_read += p->io_storage_bytes_read;
- w->io_storage_bytes_written += p->io_storage_bytes_written;
- // w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
-
- w->processes++;
- w->num_threads += p->num_threads;
-
- if(unlikely(debug || w->debug))
- fprintf(stderr, "apps.plugin: \taggregating '%s' pid %d on target '%s' utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", gtime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", cgtime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT "\n", p->comm, p->pid, w->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
-}
-
-static void calculate_netdata_statistics(void) {
-
- apply_apps_groups_targets_inheritance();
-
- zero_all_targets(users_root_target);
- zero_all_targets(groups_root_target);
- apps_groups_targets_count = zero_all_targets(apps_groups_root_target);
-
- // this has to be done, before the cleanup
- struct pid_stat *p = NULL;
- struct target *w = NULL, *o = NULL;
-
- // concentrate everything on the targets
- for(p = root_of_pids; p ; p = p->next) {
-
- // --------------------------------------------------------------------
- // apps_groups target
-
- aggregate_pid_on_target(p->target, p, NULL);
-
-
- // --------------------------------------------------------------------
- // user target
-
- o = p->user_target;
- if(likely(p->user_target && p->user_target->uid == p->uid))
- w = p->user_target;
- else {
- if(unlikely(debug && p->user_target))
- fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched user from %u (%s) to %u.\n", p->pid, p->comm, p->user_target->uid, p->user_target->name, p->uid);
-
- w = p->user_target = get_users_target(p->uid);
- }
-
- aggregate_pid_on_target(w, p, o);
-
-
- // --------------------------------------------------------------------
- // user group target
-
- o = p->group_target;
- if(likely(p->group_target && p->group_target->gid == p->gid))
- w = p->group_target;
- else {
- if(unlikely(debug && p->group_target))
- fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched group from %u (%s) to %u.\n", p->pid, p->comm, p->group_target->gid, p->group_target->name, p->gid);
-
- w = p->group_target = get_groups_target(p->gid);
- }
-
- aggregate_pid_on_target(w, p, o);
-
-
- // --------------------------------------------------------------------
- // aggregate all file descriptors
-
- if(enable_file_charts)
- aggregate_pid_fds_on_targets(p);
- }
-
- cleanup_exited_pids();
-}
-
-// ----------------------------------------------------------------------------
-// update chart dimensions
-
-int print_calculated_number(char *str, calculated_number value) { (void)str; (void)value; return 0; }
-
-static inline void send_BEGIN(const char *type, const char *id, usec_t usec) {
- fprintf(stdout, "BEGIN %s.%s %llu\n", type, id, usec);
-}
-
-static inline void send_SET(const char *name, kernel_uint_t value) {
- fprintf(stdout, "SET %s = " KERNEL_UINT_FORMAT "\n", name, value);
-}
-
-static inline void send_END(void) {
- fprintf(stdout, "END\n");
-}
-
-void send_resource_usage_to_netdata(usec_t dt) {
- static struct timeval last = { 0, 0 };
- static struct rusage me_last;
-
- struct timeval now;
- struct rusage me;
-
- usec_t cpuuser;
- usec_t cpusyst;
-
- if(!last.tv_sec) {
- now_monotonic_timeval(&last);
- getrusage(RUSAGE_SELF, &me_last);
-
- cpuuser = 0;
- cpusyst = 0;
- }
- else {
- now_monotonic_timeval(&now);
- getrusage(RUSAGE_SELF, &me);
-
- cpuuser = me.ru_utime.tv_sec * USEC_PER_SEC + me.ru_utime.tv_usec;
- cpusyst = me.ru_stime.tv_sec * USEC_PER_SEC + me.ru_stime.tv_usec;
-
- memmove(&last, &now, sizeof(struct timeval));
- memmove(&me_last, &me, sizeof(struct rusage));
- }
-
- static char created_charts = 0;
- if(unlikely(!created_charts)) {
- created_charts = 1;
-
- fprintf(stdout,
- "CHART netdata.apps_cpu '' 'Apps Plugin CPU' 'milliseconds/s' apps.plugin netdata.apps_cpu stacked 140000 %1$d\n"
- "DIMENSION user '' incremental 1 1000\n"
- "DIMENSION system '' incremental 1 1000\n"
- "CHART netdata.apps_sizes '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_sizes line 140001 %1$d\n"
- "DIMENSION calls '' incremental 1 1\n"
- "DIMENSION files '' incremental 1 1\n"
- "DIMENSION pids '' absolute 1 1\n"
- "DIMENSION fds '' absolute 1 1\n"
- "DIMENSION targets '' absolute 1 1\n"
- "DIMENSION new_pids 'new pids' incremental 1 1\n"
- , update_every
- );
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
- fprintf(stdout,
- "CHART netdata.apps_fix '' 'Apps Plugin Normalization Ratios' 'percentage' apps.plugin netdata.apps_fix line 140002 %1$d\n"
- "DIMENSION utime '' absolute 1 %2$llu\n"
- "DIMENSION stime '' absolute 1 %2$llu\n"
- "DIMENSION gtime '' absolute 1 %2$llu\n"
- "DIMENSION minflt '' absolute 1 %2$llu\n"
- "DIMENSION majflt '' absolute 1 %2$llu\n"
- , update_every
- , RATES_DETAIL
- );
-
- if(include_exited_childs)
- fprintf(stdout,
- "CHART netdata.apps_children_fix '' 'Apps Plugin Exited Children Normalization Ratios' 'percentage' apps.plugin netdata.apps_children_fix line 140003 %1$d\n"
- "DIMENSION cutime '' absolute 1 %2$llu\n"
- "DIMENSION cstime '' absolute 1 %2$llu\n"
- "DIMENSION cgtime '' absolute 1 %2$llu\n"
- "DIMENSION cminflt '' absolute 1 %2$llu\n"
- "DIMENSION cmajflt '' absolute 1 %2$llu\n"
- , update_every
- , RATES_DETAIL
- );
-#endif
-
- }
-
- fprintf(stdout,
- "BEGIN netdata.apps_cpu %llu\n"
- "SET user = %llu\n"
- "SET system = %llu\n"
- "END\n"
- "BEGIN netdata.apps_sizes %llu\n"
- "SET calls = %zu\n"
- "SET files = %zu\n"
- "SET pids = %zu\n"
- "SET fds = %d\n"
- "SET targets = %zu\n"
- "SET new_pids = %zu\n"
- "END\n"
- , dt
- , cpuuser
- , cpusyst
- , dt
- , calls_counter
- , file_counter
- , all_pids_count
- , all_files_len
- , apps_groups_targets_count
- , targets_assignment_counter
- );
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
- fprintf(stdout,
- "BEGIN netdata.apps_fix %llu\n"
- "SET utime = %u\n"
- "SET stime = %u\n"
- "SET gtime = %u\n"
- "SET minflt = %u\n"
- "SET majflt = %u\n"
- "END\n"
- , dt
- , (unsigned int)(utime_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(stime_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(gtime_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(minflt_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(majflt_fix_ratio * 100 * RATES_DETAIL)
- );
-
- if(include_exited_childs)
- fprintf(stdout,
- "BEGIN netdata.apps_children_fix %llu\n"
- "SET cutime = %u\n"
- "SET cstime = %u\n"
- "SET cgtime = %u\n"
- "SET cminflt = %u\n"
- "SET cmajflt = %u\n"
- "END\n"
- , dt
- , (unsigned int)(cutime_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(cstime_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(cgtime_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(cminflt_fix_ratio * 100 * RATES_DETAIL)
- , (unsigned int)(cmajflt_fix_ratio * 100 * RATES_DETAIL)
- );
-#endif
-}
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
-static void normalize_utilization(struct target *root) {
- struct target *w;
-
- // childs processing introduces spikes
- // here we try to eliminate them by disabling childs processing either for specific dimensions
- // or entirely. Of course, either way, we disable it just a single iteration.
-
- kernel_uint_t max_time = processors * hz * RATES_DETAIL;
- kernel_uint_t utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
-
- if(global_utime > max_time) global_utime = max_time;
- if(global_stime > max_time) global_stime = max_time;
- if(global_gtime > max_time) global_gtime = max_time;
-
- for(w = root; w ; w = w->next) {
- if(w->target || (!w->processes && !w->exposed)) continue;
-
- utime += w->utime;
- stime += w->stime;
- gtime += w->gtime;
- cutime += w->cutime;
- cstime += w->cstime;
- cgtime += w->cgtime;
-
- minflt += w->minflt;
- majflt += w->majflt;
- cminflt += w->cminflt;
- cmajflt += w->cmajflt;
- }
-
- if((global_utime || global_stime || global_gtime) && (utime || stime || gtime)) {
- if(global_utime + global_stime + global_gtime > utime + cutime + stime + cstime + gtime + cgtime) {
- // everything we collected fits
- utime_fix_ratio =
- stime_fix_ratio =
- gtime_fix_ratio =
- cutime_fix_ratio =
- cstime_fix_ratio =
- cgtime_fix_ratio = 1.0; //(double)(global_utime + global_stime) / (double)(utime + cutime + stime + cstime);
- }
- else if(global_utime + global_stime > utime + stime) {
- // childrens resources are too high
- // lower only the children resources
- utime_fix_ratio =
- stime_fix_ratio =
- gtime_fix_ratio = 1.0;
- cutime_fix_ratio =
- cstime_fix_ratio =
- cgtime_fix_ratio = (double)((global_utime + global_stime) - (utime + stime)) / (double)(cutime + cstime);
- }
- else {
- // even running processes are unrealistic
- // zero the children resources
- // lower the running processes resources
- utime_fix_ratio =
- stime_fix_ratio =
- gtime_fix_ratio = (double)(global_utime + global_stime) / (double)(utime + stime);
- cutime_fix_ratio =
- cstime_fix_ratio =
- cgtime_fix_ratio = 0.0;
- }
- }
- else {
- utime_fix_ratio =
- stime_fix_ratio =
- gtime_fix_ratio =
- cutime_fix_ratio =
- cstime_fix_ratio =
- cgtime_fix_ratio = 0.0;
- }
-
- if(utime_fix_ratio > 1.0) utime_fix_ratio = 1.0;
- if(cutime_fix_ratio > 1.0) cutime_fix_ratio = 1.0;
- if(stime_fix_ratio > 1.0) stime_fix_ratio = 1.0;
- if(cstime_fix_ratio > 1.0) cstime_fix_ratio = 1.0;
- if(gtime_fix_ratio > 1.0) gtime_fix_ratio = 1.0;
- if(cgtime_fix_ratio > 1.0) cgtime_fix_ratio = 1.0;
-
- // if(utime_fix_ratio < 0.0) utime_fix_ratio = 0.0;
- // if(cutime_fix_ratio < 0.0) cutime_fix_ratio = 0.0;
- // if(stime_fix_ratio < 0.0) stime_fix_ratio = 0.0;
- // if(cstime_fix_ratio < 0.0) cstime_fix_ratio = 0.0;
- // if(gtime_fix_ratio < 0.0) gtime_fix_ratio = 0.0;
- // if(cgtime_fix_ratio < 0.0) cgtime_fix_ratio = 0.0;
-
- // FIXME
- // we use cpu time to normalize page faults
- // the problem is that to find the proper max values
- // for page faults we have to parse /proc/vmstat
- // which is quite big to do it again (netdata does it already)
- //
- // a better solution could be to somehow have netdata
- // do this normalization for us
-
- if(utime || stime || gtime)
- majflt_fix_ratio =
- minflt_fix_ratio = (double)(utime * utime_fix_ratio + stime * stime_fix_ratio + gtime * gtime_fix_ratio) / (double)(utime + stime + gtime);
- else
- minflt_fix_ratio =
- majflt_fix_ratio = 1.0;
-
- if(cutime || cstime || cgtime)
- cmajflt_fix_ratio =
- cminflt_fix_ratio = (double)(cutime * cutime_fix_ratio + cstime * cstime_fix_ratio + cgtime * cgtime_fix_ratio) / (double)(cutime + cstime + cgtime);
- else
- cminflt_fix_ratio =
- cmajflt_fix_ratio = 1.0;
-
- // the report
-
- if(unlikely(debug)) {
- fprintf(stderr,
- "SYSTEM: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " "
- "COLLECTED: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " cu=" KERNEL_UINT_FORMAT " cs=" KERNEL_UINT_FORMAT " cg=" KERNEL_UINT_FORMAT " "
- "DELTA: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " "
- "FIX: u=%0.2f s=%0.2f g=%0.2f cu=%0.2f cs=%0.2f cg=%0.2f "
- "FINALLY: u=" KERNEL_UINT_FORMAT " s=" KERNEL_UINT_FORMAT " g=" KERNEL_UINT_FORMAT " cu=" KERNEL_UINT_FORMAT " cs=" KERNEL_UINT_FORMAT " cg=" KERNEL_UINT_FORMAT " "
- "\n"
- , global_utime
- , global_stime
- , global_gtime
- , utime
- , stime
- , gtime
- , cutime
- , cstime
- , cgtime
- , utime + cutime - global_utime
- , stime + cstime - global_stime
- , gtime + cgtime - global_gtime
- , utime_fix_ratio
- , stime_fix_ratio
- , gtime_fix_ratio
- , cutime_fix_ratio
- , cstime_fix_ratio
- , cgtime_fix_ratio
- , (kernel_uint_t)(utime * utime_fix_ratio)
- , (kernel_uint_t)(stime * stime_fix_ratio)
- , (kernel_uint_t)(gtime * gtime_fix_ratio)
- , (kernel_uint_t)(cutime * cutime_fix_ratio)
- , (kernel_uint_t)(cstime * cstime_fix_ratio)
- , (kernel_uint_t)(cgtime * cgtime_fix_ratio)
- );
- }
-}
-#else // ALL_PIDS_ARE_READ_INSTANTLY == 1
-static void normalize_utilization(struct target *root) {
- (void)root;
-}
-#endif // ALL_PIDS_ARE_READ_INSTANTLY
-
-static void send_collected_data_to_netdata(struct target *root, const char *type, usec_t dt) {
- struct target *w;
-
- send_BEGIN(type, "cpu", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (kernel_uint_t)(w->utime * utime_fix_ratio) + (kernel_uint_t)(w->stime * stime_fix_ratio) + (kernel_uint_t)(w->gtime * gtime_fix_ratio) + (include_exited_childs?((kernel_uint_t)(w->cutime * cutime_fix_ratio) + (kernel_uint_t)(w->cstime * cstime_fix_ratio) + (kernel_uint_t)(w->cgtime * cgtime_fix_ratio)):0ULL));
- }
- send_END();
-
- send_BEGIN(type, "cpu_user", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (kernel_uint_t)(w->utime * utime_fix_ratio) + (include_exited_childs?((kernel_uint_t)(w->cutime * cutime_fix_ratio)):0ULL));
- }
- send_END();
-
- send_BEGIN(type, "cpu_system", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (kernel_uint_t)(w->stime * stime_fix_ratio) + (include_exited_childs?((kernel_uint_t)(w->cstime * cstime_fix_ratio)):0ULL));
- }
- send_END();
-
- if(show_guest_time) {
- send_BEGIN(type, "cpu_guest", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (kernel_uint_t)(w->gtime * gtime_fix_ratio) + (include_exited_childs?((kernel_uint_t)(w->cgtime * cgtime_fix_ratio)):0ULL));
- }
- send_END();
- }
-
- send_BEGIN(type, "threads", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->num_threads);
- }
- send_END();
-
- send_BEGIN(type, "processes", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->processes);
- }
- send_END();
-
- send_BEGIN(type, "mem", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (w->status_vmrss > w->status_vmshared)?(w->status_vmrss - w->status_vmshared):0ULL);
- }
- send_END();
-
- send_BEGIN(type, "vmem", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->status_vmsize);
- }
- send_END();
-
-#ifndef __FreeBSD__
- send_BEGIN(type, "swap", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->status_vmswap);
- }
- send_END();
-#endif
-
- send_BEGIN(type, "minor_faults", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (kernel_uint_t)(w->minflt * minflt_fix_ratio) + (include_exited_childs?((kernel_uint_t)(w->cminflt * cminflt_fix_ratio)):0ULL));
- }
- send_END();
-
- send_BEGIN(type, "major_faults", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, (kernel_uint_t)(w->majflt * majflt_fix_ratio) + (include_exited_childs?((kernel_uint_t)(w->cmajflt * cmajflt_fix_ratio)):0ULL));
- }
- send_END();
-
-#ifndef __FreeBSD__
- send_BEGIN(type, "lreads", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->io_logical_bytes_read);
- }
- send_END();
-
- send_BEGIN(type, "lwrites", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->io_logical_bytes_written);
- }
- send_END();
-#endif
-
- send_BEGIN(type, "preads", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->io_storage_bytes_read);
- }
- send_END();
-
- send_BEGIN(type, "pwrites", dt);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- send_SET(w->name, w->io_storage_bytes_written);
- }
- send_END();
-
- if(enable_file_charts) {
- send_BEGIN(type, "files", dt);
- for (w = root; w; w = w->next) {
- if (unlikely(w->exposed))
- send_SET(w->name, w->openfiles);
- }
- send_END();
-
- send_BEGIN(type, "sockets", dt);
- for (w = root; w; w = w->next) {
- if (unlikely(w->exposed))
- send_SET(w->name, w->opensockets);
- }
- send_END();
-
- send_BEGIN(type, "pipes", dt);
- for (w = root; w; w = w->next) {
- if (unlikely(w->exposed))
- send_SET(w->name, w->openpipes);
- }
- send_END();
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// generate the charts
-
-static void send_charts_updates_to_netdata(struct target *root, const char *type, const char *title)
-{
- struct target *w;
- int newly_added = 0;
-
- for(w = root ; w ; w = w->next) {
- if (w->target) continue;
-
- if (!w->exposed && w->processes) {
- newly_added++;
- w->exposed = 1;
- if (debug || w->debug) fprintf(stderr, "apps.plugin: %s just added - regenerating charts.\n", w->name);
- }
- }
-
- // nothing more to show
- if(!newly_added && show_guest_time == show_guest_time_old) return;
-
- // we have something new to show
- // update the charts
- fprintf(stdout, "CHART %s.cpu '' '%s CPU Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, hz * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
- }
-
- fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L);
- }
-
- fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MB' mem %s.vmem stacked 20005 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L);
- }
-
- fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20006 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
- }
-
- fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20007 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
- }
-
- fprintf(stdout, "CHART %s.cpu_user '' '%s CPU User Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
- }
-
- fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
- }
-
- if(show_guest_time) {
- fprintf(stdout, "CHART %s.cpu_guest '' '%s CPU Guest Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20022 %d\n", type, title, (processors * 100), processors, (processors > 1) ? "s" : "", type, update_every);
- for (w = root; w; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
- }
- }
-
-#ifndef __FreeBSD__
- fprintf(stdout, "CHART %s.swap '' '%s Swap Memory' 'MB' swap %s.swap stacked 20011 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L);
- }
-#endif
-
- fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20012 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
- }
-
- fprintf(stdout, "CHART %s.minor_faults '' '%s Minor Page Faults' 'page faults/s' mem %s.minor_faults stacked 20011 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
- }
-
-#ifdef __FreeBSD__
- fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'blocks/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
- }
-
- fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'blocks/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
- }
-#else
- fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'kilobytes/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
- }
-
- fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'kilobytes/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
- }
-
- fprintf(stdout, "CHART %s.lreads '' '%s Disk Logical Reads' 'kilobytes/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
- }
-
- fprintf(stdout, "CHART %s.lwrites '' '%s I/O Logical Writes' 'kilobytes/s' disk %s.lwrites stacked 20042 %d\n", type, title, type, update_every);
- for (w = root; w ; w = w->next) {
- if(unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
- }
-#endif
-
- if(enable_file_charts) {
- fprintf(stdout, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type,
- title, type, update_every);
- for (w = root; w; w = w->next) {
- if (unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
- }
-
- fprintf(stdout, "CHART %s.sockets '' '%s Open Sockets' 'open sockets' net %s.sockets stacked 20051 %d\n",
- type, title, type, update_every);
- for (w = root; w; w = w->next) {
- if (unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
- }
-
- fprintf(stdout, "CHART %s.pipes '' '%s Pipes' 'open pipes' processes %s.pipes stacked 20053 %d\n", type,
- title, type, update_every);
- for (w = root; w; w = w->next) {
- if (unlikely(w->exposed))
- fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
- }
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// parse command line arguments
-
-int check_proc_1_io() {
- int ret = 0;
-
- procfile *ff = procfile_open("/proc/1/io", NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
- if(!ff) goto cleanup;
-
- ff = procfile_readall(ff);
- if(!ff) goto cleanup;
-
- ret = 1;
-
-cleanup:
- procfile_close(ff);
- return ret;
-}
-
-static void parse_args(int argc, char **argv)
-{
- int i, freq = 0;
- char *name = NULL;
-
- for(i = 1; i < argc; i++) {
- if(!freq) {
- int n = (int)str2l(argv[i]);
- if(n > 0) {
- freq = n;
- continue;
- }
- }
-
- if(strcmp("version", argv[i]) == 0 || strcmp("-version", argv[i]) == 0 || strcmp("--version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0 || strcmp("-V", argv[i]) == 0) {
- printf("apps.plugin %s\n", VERSION);
- exit(0);
- }
-
- if(strcmp("test-permissions", argv[i]) == 0 || strcmp("-t", argv[i]) == 0) {
- if(!check_proc_1_io()) {
- perror("Tried to read /proc/1/io and it failed");
- exit(1);
- }
- printf("OK\n");
- exit(0);
- }
-
- if(strcmp("debug", argv[i]) == 0) {
- debug = 1;
- // debug_flags = 0xffffffff;
- continue;
- }
-
- if(strcmp("no-childs", argv[i]) == 0 || strcmp("without-childs", argv[i]) == 0) {
- include_exited_childs = 0;
- continue;
- }
-
- if(strcmp("with-childs", argv[i]) == 0) {
- include_exited_childs = 1;
- continue;
- }
-
- if(strcmp("with-guest", argv[i]) == 0) {
- enable_guest_charts = 1;
- continue;
- }
-
- if(strcmp("no-guest", argv[i]) == 0 || strcmp("without-guest", argv[i]) == 0) {
- enable_guest_charts = 0;
- continue;
- }
-
- if(strcmp("with-files", argv[i]) == 0) {
- enable_file_charts = 1;
- continue;
- }
-
- if(strcmp("no-files", argv[i]) == 0 || strcmp("without-files", argv[i]) == 0) {
- enable_file_charts = 0;
- continue;
- }
-
- if(strcmp("no-users", argv[i]) == 0 || strcmp("without-users", argv[i]) == 0) {
- enable_users_charts = 0;
- continue;
- }
-
- if(strcmp("no-groups", argv[i]) == 0 || strcmp("without-groups", argv[i]) == 0) {
- enable_groups_charts = 0;
- continue;
- }
-
- if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
- fprintf(stderr,
- "\n"
- " netdata apps.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 set the data collection frequency\n"
- "\n"
- " debug enable debugging (lot of output)\n"
- "\n"
- " with-childs\n"
- " without-childs enable / disable aggregating exited\n"
- " children resources into parents\n"
- " (default is enabled)\n"
- "\n"
- " with-guest\n"
- " without-guest enable / disable reporting guest charts\n"
- " (default is disabled)\n"
- "\n"
- " with-files\n"
- " without-files enable / disable reporting files, sockets, pipes\n"
- " (default is enabled)\n"
- "\n"
- " NAME read apps_NAME.conf instead of\n"
- " apps_groups.conf\n"
- " (default NAME=groups)\n"
- "\n"
- " version or -v or -V print program version and exit\n"
- "\n"
- , VERSION
- );
- exit(1);
- }
-
- if(!name) {
- name = argv[i];
- continue;
- }
-
- error("Cannot understand option %s", argv[i]);
- exit(1);
- }
-
- if(freq > 0) update_every = freq;
- if(!name) name = "groups";
-
- if(read_apps_groups_conf(name)) {
- error("Cannot read process groups '%s/apps_%s.conf'. There are no internal defaults. Failing.", config_dir, name);
- exit(1);
- }
-}
-
-static int am_i_running_as_root() {
- uid_t uid = getuid(), euid = geteuid();
-
- if(uid == 0 || euid == 0) {
- if(debug) info("I am running with escalated privileges, uid = %u, euid = %u.", uid, euid);
- return 1;
- }
-
- if(debug) info("I am not running with escalated privileges, uid = %u, euid = %u.", uid, euid);
- return 0;
-}
-
-#ifdef HAVE_CAPABILITY
-static int check_capabilities() {
- cap_t caps = cap_get_proc();
- if(!caps) {
- error("Cannot get current capabilities.");
- return 0;
- }
- else if(debug)
- info("Received my capabilities from the system.");
-
- int ret = 1;
-
- cap_flag_value_t cfv = CAP_CLEAR;
- if(cap_get_flag(caps, CAP_DAC_READ_SEARCH, CAP_EFFECTIVE, &cfv) == -1) {
- error("Cannot find if CAP_DAC_READ_SEARCH is effective.");
- ret = 0;
- }
- else {
- if(cfv != CAP_SET) {
- error("apps.plugin should run with CAP_DAC_READ_SEARCH.");
- ret = 0;
- }
- else if(debug)
- info("apps.plugin runs with CAP_DAC_READ_SEARCH.");
- }
-
- cfv = CAP_CLEAR;
- if(cap_get_flag(caps, CAP_SYS_PTRACE, CAP_EFFECTIVE, &cfv) == -1) {
- error("Cannot find if CAP_SYS_PTRACE is effective.");
- ret = 0;
- }
- else {
- if(cfv != CAP_SET) {
- error("apps.plugin should run with CAP_SYS_PTRACE.");
- ret = 0;
- }
- else if(debug)
- info("apps.plugin runs with CAP_SYS_PTRACE.");
- }
-
- cap_free(caps);
-
- return ret;
-}
-#else
-static int check_capabilities() {
- return 0;
-}
-#endif
-
-int main(int argc, char **argv) {
- // debug_flags = D_PROCFILE;
-
- pagesize = (size_t)sysconf(_SC_PAGESIZE);
-
- // set the name for logging
- program_name = "apps.plugin";
-
- // disable syslog for apps.plugin
- error_log_syslog = 0;
-
- // set errors flood protection to 100 logs per hour
- error_log_errors_per_period = 100;
- error_log_throttle_period = 3600;
-
- netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
- if(netdata_configured_host_prefix == NULL) {
- // info("NETDATA_HOST_PREFIX is not passed from netdata");
- netdata_configured_host_prefix = "";
- }
- // else info("Found NETDATA_HOST_PREFIX='%s'", netdata_configured_host_prefix);
-
- config_dir = getenv("NETDATA_CONFIG_DIR");
- if(config_dir == NULL) {
- // info("NETDATA_CONFIG_DIR is not passed from netdata");
- config_dir = CONFIG_DIR;
- }
- // else info("Found NETDATA_CONFIG_DIR='%s'", config_dir);
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(debug_flags != 0) {
- struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
- if(setrlimit(RLIMIT_CORE, &rl) != 0)
- info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
-#ifdef HAVE_SYS_PRCTL_H
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-#endif
- }
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- procfile_adaptive_initial_allocation = 1;
-
- time_t started_t = now_monotonic_sec();
- get_system_HZ();
- get_system_pid_max();
- get_system_cpus();
-
- parse_args(argc, argv);
-
- if(!check_capabilities() && !am_i_running_as_root() && !check_proc_1_io()) {
- uid_t uid = getuid(), euid = geteuid();
-#ifdef HAVE_CAPABILITY
- error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
- "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
- "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; "
- "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
- , uid, euid, argv[0], argv[0], argv[0]
- );
-#else
- error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
- "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
- "Your system does not support capabilities. "
- "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
- , uid, euid, argv[0], argv[0]
- );
-#endif
- }
-
- info("started on pid %d", getpid());
-
-#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
- all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max);
-#endif
-
- all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max);
-
- usec_t step = update_every * USEC_PER_SEC;
- global_iterations_counter = 1;
- heartbeat_t hb;
- heartbeat_init(&hb);
- for(;1; global_iterations_counter++) {
-
-#ifdef NETDATA_PROFILING
-#warning "compiling for profiling"
- static int profiling_count=0;
- profiling_count++;
- if(unlikely(profiling_count > 2000)) exit(0);
- usec_t dt = update_every * USEC_PER_SEC;
-#else
- usec_t dt = heartbeat_next(&hb, step);
-#endif
-
- if(!collect_data_for_all_processes()) {
- error("Cannot collect /proc data for running processes. Disabling apps.plugin...");
- printf("DISABLE\n");
- exit(1);
- }
-
- calculate_netdata_statistics();
- normalize_utilization(apps_groups_root_target);
-
- send_resource_usage_to_netdata(dt);
-
- // this is smart enough to show only newly added apps, when needed
- send_charts_updates_to_netdata(apps_groups_root_target, "apps", "Apps");
-
- if(likely(enable_users_charts))
- send_charts_updates_to_netdata(users_root_target, "users", "Users");
-
- if(likely(enable_groups_charts))
- send_charts_updates_to_netdata(groups_root_target, "groups", "User Groups");
-
- send_collected_data_to_netdata(apps_groups_root_target, "apps", dt);
-
- if(likely(enable_users_charts))
- send_collected_data_to_netdata(users_root_target, "users", dt);
-
- if(likely(enable_groups_charts))
- send_collected_data_to_netdata(groups_root_target, "groups", dt);
-
- fflush(stdout);
-
- show_guest_time_old = show_guest_time;
-
- if(unlikely(debug))
- fprintf(stderr, "apps.plugin: done Loop No %zu\n", global_iterations_counter);
-
- // restart check (14400 seconds)
- if(now_monotonic_sec() - started_t > 14400) exit(0);
- }
-}
diff --git a/src/avl.c b/src/avl.c
deleted file mode 100644
index a2c6911e7..000000000
--- a/src/avl.c
+++ /dev/null
@@ -1,403 +0,0 @@
-#include "common.h"
-
-/* ------------------------------------------------------------------------- */
-/*
- * avl_insert(), avl_remove() and avl_search()
- * are adaptations (by Costa Tsaousis) of the AVL algorithm found in libavl
- * v2.0.3, so that they do not use any memory allocations and their memory
- * footprint is optimized (by eliminating non-necessary data members).
- *
- * libavl - library for manipulation of binary trees.
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
- * Foundation, Inc.
- * GNU Lesser General Public License
-*/
-
-
-/* Search |tree| for an item matching |item|, and return it if found.
- Otherwise return |NULL|. */
-avl *avl_search(avl_tree *tree, avl *item) {
- avl *p;
-
- // assert (tree != NULL && item != NULL);
-
- for (p = tree->root; p != NULL; ) {
- int cmp = tree->compar(item, p);
-
- if (cmp < 0)
- p = p->avl_link[0];
- else if (cmp > 0)
- p = p->avl_link[1];
- else /* |cmp == 0| */
- return p;
- }
-
- return NULL;
-}
-
-/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
- If a duplicate item is found in the tree,
- returns a pointer to the duplicate without inserting |item|.
- */
-avl *avl_insert(avl_tree *tree, avl *item) {
- avl *y, *z; /* Top node to update balance factor, and parent. */
- avl *p, *q; /* Iterator, and parent. */
- avl *n; /* Newly inserted node. */
- avl *w; /* New root of rebalanced subtree. */
- int dir; /* Direction to descend. */
-
- unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
- int k = 0; /* Number of cached results. */
-
- // assert(tree != NULL && item != NULL);
-
- z = (avl *) &tree->root;
- y = tree->root;
- dir = 0;
- for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) {
- int cmp = tree->compar(item, p);
- if (cmp == 0)
- return p;
-
- if (p->avl_balance != 0)
- z = q, y = p, k = 0;
- da[k++] = dir = (cmp > 0);
- }
-
- n = q->avl_link[dir] = item;
-
- // tree->avl_count++;
- n->avl_link[0] = n->avl_link[1] = NULL;
- n->avl_balance = 0;
- if (y == NULL) return n;
-
- for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
- if (da[k] == 0)
- p->avl_balance--;
- else
- p->avl_balance++;
-
- if (y->avl_balance == -2) {
- avl *x = y->avl_link[0];
- if (x->avl_balance == -1) {
- w = x;
- y->avl_link[0] = x->avl_link[1];
- x->avl_link[1] = y;
- x->avl_balance = y->avl_balance = 0;
- }
- else {
- // assert (x->avl_balance == +1);
- w = x->avl_link[1];
- x->avl_link[1] = w->avl_link[0];
- w->avl_link[0] = x;
- y->avl_link[0] = w->avl_link[1];
- w->avl_link[1] = y;
- if (w->avl_balance == -1)
- x->avl_balance = 0, y->avl_balance = +1;
- else if (w->avl_balance == 0)
- x->avl_balance = y->avl_balance = 0;
- else /* |w->avl_balance == +1| */
- x->avl_balance = -1, y->avl_balance = 0;
- w->avl_balance = 0;
- }
- }
- else if (y->avl_balance == +2) {
- avl *x = y->avl_link[1];
- if (x->avl_balance == +1) {
- w = x;
- y->avl_link[1] = x->avl_link[0];
- x->avl_link[0] = y;
- x->avl_balance = y->avl_balance = 0;
- }
- else {
- // assert (x->avl_balance == -1);
- w = x->avl_link[0];
- x->avl_link[0] = w->avl_link[1];
- w->avl_link[1] = x;
- y->avl_link[1] = w->avl_link[0];
- w->avl_link[0] = y;
- if (w->avl_balance == +1)
- x->avl_balance = 0, y->avl_balance = -1;
- else if (w->avl_balance == 0)
- x->avl_balance = y->avl_balance = 0;
- else /* |w->avl_balance == -1| */
- x->avl_balance = +1, y->avl_balance = 0;
- w->avl_balance = 0;
- }
- }
- else return n;
-
- z->avl_link[y != z->avl_link[0]] = w;
-
- // tree->avl_generation++;
- return n;
-}
-
-/* Deletes from |tree| and returns an item matching |item|.
- Returns a null pointer if no matching item found. */
-avl *avl_remove(avl_tree *tree, avl *item) {
- /* Stack of nodes. */
- avl *pa[AVL_MAX_HEIGHT]; /* Nodes. */
- unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
- int k; /* Stack pointer. */
-
- avl *p; /* Traverses tree to find node to delete. */
- int cmp; /* Result of comparison between |item| and |p|. */
-
- // assert (tree != NULL && item != NULL);
-
- k = 0;
- p = (avl *) &tree->root;
- for(cmp = -1; cmp != 0; cmp = tree->compar(item, p)) {
- int dir = (cmp > 0);
-
- pa[k] = p;
- da[k++] = dir;
-
- p = p->avl_link[dir];
- if(p == NULL) return NULL;
- }
-
- item = p;
-
- if (p->avl_link[1] == NULL)
- pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
- else {
- avl *r = p->avl_link[1];
- if (r->avl_link[0] == NULL) {
- r->avl_link[0] = p->avl_link[0];
- r->avl_balance = p->avl_balance;
- pa[k - 1]->avl_link[da[k - 1]] = r;
- da[k] = 1;
- pa[k++] = r;
- }
- else {
- avl *s;
- int j = k++;
-
- for (;;) {
- da[k] = 0;
- pa[k++] = r;
- s = r->avl_link[0];
- if (s->avl_link[0] == NULL) break;
-
- r = s;
- }
-
- s->avl_link[0] = p->avl_link[0];
- r->avl_link[0] = s->avl_link[1];
- s->avl_link[1] = p->avl_link[1];
- s->avl_balance = p->avl_balance;
-
- pa[j - 1]->avl_link[da[j - 1]] = s;
- da[j] = 1;
- pa[j] = s;
- }
- }
-
- // assert (k > 0);
- while (--k > 0) {
- avl *y = pa[k];
-
- if (da[k] == 0) {
- y->avl_balance++;
- if (y->avl_balance == +1) break;
- else if (y->avl_balance == +2) {
- avl *x = y->avl_link[1];
- if (x->avl_balance == -1) {
- avl *w;
- // assert (x->avl_balance == -1);
- w = x->avl_link[0];
- x->avl_link[0] = w->avl_link[1];
- w->avl_link[1] = x;
- y->avl_link[1] = w->avl_link[0];
- w->avl_link[0] = y;
- if (w->avl_balance == +1)
- x->avl_balance = 0, y->avl_balance = -1;
- else if (w->avl_balance == 0)
- x->avl_balance = y->avl_balance = 0;
- else /* |w->avl_balance == -1| */
- x->avl_balance = +1, y->avl_balance = 0;
- w->avl_balance = 0;
- pa[k - 1]->avl_link[da[k - 1]] = w;
- }
- else {
- y->avl_link[1] = x->avl_link[0];
- x->avl_link[0] = y;
- pa[k - 1]->avl_link[da[k - 1]] = x;
- if (x->avl_balance == 0) {
- x->avl_balance = -1;
- y->avl_balance = +1;
- break;
- }
- else x->avl_balance = y->avl_balance = 0;
- }
- }
- }
- else
- {
- y->avl_balance--;
- if (y->avl_balance == -1) break;
- else if (y->avl_balance == -2) {
- avl *x = y->avl_link[0];
- if (x->avl_balance == +1) {
- avl *w;
- // assert (x->avl_balance == +1);
- w = x->avl_link[1];
- x->avl_link[1] = w->avl_link[0];
- w->avl_link[0] = x;
- y->avl_link[0] = w->avl_link[1];
- w->avl_link[1] = y;
- if (w->avl_balance == -1)
- x->avl_balance = 0, y->avl_balance = +1;
- else if (w->avl_balance == 0)
- x->avl_balance = y->avl_balance = 0;
- else /* |w->avl_balance == +1| */
- x->avl_balance = -1, y->avl_balance = 0;
- w->avl_balance = 0;
- pa[k - 1]->avl_link[da[k - 1]] = w;
- }
- else {
- y->avl_link[0] = x->avl_link[1];
- x->avl_link[1] = y;
- pa[k - 1]->avl_link[da[k - 1]] = x;
- if (x->avl_balance == 0) {
- x->avl_balance = +1;
- y->avl_balance = -1;
- break;
- }
- else x->avl_balance = y->avl_balance = 0;
- }
- }
- }
- }
-
- // tree->avl_count--;
- // tree->avl_generation++;
- return item;
-}
-
-/* ------------------------------------------------------------------------- */
-// below are functions by (C) Costa Tsaousis
-
-// ---------------------------
-// traversing
-
-int avl_walker(avl *node, int (*callback)(void *entry, void *data), void *data) {
- int total = 0, ret = 0;
-
- if(node->avl_link[0]) {
- ret = avl_walker(node->avl_link[0], callback, data);
- if(ret < 0) return ret;
- total += ret;
- }
-
- ret = callback(node, data);
- if(ret < 0) return ret;
- total += ret;
-
- if(node->avl_link[1]) {
- ret = avl_walker(node->avl_link[1], callback, data);
- if (ret < 0) return ret;
- total += ret;
- }
-
- return total;
-}
-
-int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *data) {
- if(t->root)
- return avl_walker(t->root, callback, data);
- else
- return 0;
-}
-
-// ---------------------------
-// locks
-
-void avl_read_lock(avl_tree_lock *t) {
-#ifndef AVL_WITHOUT_PTHREADS
-#ifdef AVL_LOCK_WITH_MUTEX
- netdata_mutex_lock(&t->mutex);
-#else
- netdata_rwlock_rdlock(&t->rwlock);
-#endif
-#endif /* AVL_WITHOUT_PTHREADS */
-}
-
-void avl_write_lock(avl_tree_lock *t) {
-#ifndef AVL_WITHOUT_PTHREADS
-#ifdef AVL_LOCK_WITH_MUTEX
- netdata_mutex_lock(&t->mutex);
-#else
- netdata_rwlock_wrlock(&t->rwlock);
-#endif
-#endif /* AVL_WITHOUT_PTHREADS */
-}
-
-void avl_unlock(avl_tree_lock *t) {
-#ifndef AVL_WITHOUT_PTHREADS
-#ifdef AVL_LOCK_WITH_MUTEX
- netdata_mutex_unlock(&t->mutex);
-#else
- netdata_rwlock_unlock(&t->rwlock);
-#endif
-#endif /* AVL_WITHOUT_PTHREADS */
-}
-
-// ---------------------------
-// operations with locking
-
-void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)) {
- avl_init(&t->avl_tree, compar);
-
-#ifndef AVL_WITHOUT_PTHREADS
- int lock;
-
-#ifdef AVL_LOCK_WITH_MUTEX
- lock = netdata_mutex_init(&t->mutex, NULL);
-#else
- lock = netdata_rwlock_init(&t->rwlock);
-#endif
-
- if(lock != 0)
- fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
-
-#endif /* AVL_WITHOUT_PTHREADS */
-}
-
-avl *avl_search_lock(avl_tree_lock *t, avl *a) {
- avl_read_lock(t);
- avl *ret = avl_search(&t->avl_tree, a);
- avl_unlock(t);
- return ret;
-}
-
-avl * avl_remove_lock(avl_tree_lock *t, avl *a) {
- avl_write_lock(t);
- avl *ret = avl_remove(&t->avl_tree, a);
- avl_unlock(t);
- return ret;
-}
-
-avl *avl_insert_lock(avl_tree_lock *t, avl *a) {
- avl_write_lock(t);
- avl * ret = avl_insert(&t->avl_tree, a);
- avl_unlock(t);
- return ret;
-}
-
-int avl_traverse_lock(avl_tree_lock *t, int (*callback)(void *entry, void *data), void *data) {
- int ret;
- avl_read_lock(t);
- ret = avl_traverse(&t->avl_tree, callback, data);
- avl_unlock(t);
- return ret;
-}
-
-void avl_init(avl_tree *t, int (*compar)(void *a, void *b)) {
- t->root = NULL;
- t->compar = compar;
-}
-
-// ------------------ \ No newline at end of file
diff --git a/src/avl.h b/src/avl.h
deleted file mode 100644
index 19648cd1d..000000000
--- a/src/avl.h
+++ /dev/null
@@ -1,86 +0,0 @@
-
-#ifndef _AVL_H
-#define _AVL_H 1
-
-/* Maximum AVL tree height. */
-#ifndef AVL_MAX_HEIGHT
-#define AVL_MAX_HEIGHT 92
-#endif
-
-#ifndef AVL_WITHOUT_PTHREADS
-#include <pthread.h>
-
-// #define AVL_LOCK_WITH_MUTEX 1
-
-#ifdef AVL_LOCK_WITH_MUTEX
-#define AVL_LOCK_INITIALIZER NETDATA_MUTEX_INITIALIZER
-#else /* AVL_LOCK_WITH_MUTEX */
-#define AVL_LOCK_INITIALIZER NETDATA_RWLOCK_INITIALIZER
-#endif /* AVL_LOCK_WITH_MUTEX */
-
-#else /* AVL_WITHOUT_PTHREADS */
-#define AVL_LOCK_INITIALIZER
-#endif /* AVL_WITHOUT_PTHREADS */
-
-/* Data structures */
-
-/* One element of the AVL tree */
-typedef struct avl {
- struct avl *avl_link[2]; /* Subtrees. */
- signed char avl_balance; /* Balance factor. */
-} avl;
-
-/* An AVL tree */
-typedef struct avl_tree {
- avl *root;
- int (*compar)(void *a, void *b);
-} avl_tree;
-
-typedef struct avl_tree_lock {
- avl_tree avl_tree;
-
-#ifndef AVL_WITHOUT_PTHREADS
-#ifdef AVL_LOCK_WITH_MUTEX
- netdata_mutex_t mutex;
-#else /* AVL_LOCK_WITH_MUTEX */
- netdata_rwlock_t rwlock;
-#endif /* AVL_LOCK_WITH_MUTEX */
-#endif /* AVL_WITHOUT_PTHREADS */
-} avl_tree_lock;
-
-/* Public methods */
-
-/* Insert element a into the AVL tree t
- * returns the added element a, or a pointer the
- * element that is equal to a (as returned by t->compar())
- * a is linked directly to the tree, so it has to
- * be properly allocated by the caller.
- */
-avl *avl_insert_lock(avl_tree_lock *t, avl *a) NEVERNULL WARNUNUSED;
-avl *avl_insert(avl_tree *t, avl *a) NEVERNULL WARNUNUSED;
-
-/* Remove an element a from the AVL tree t
- * returns a pointer to the removed element
- * or NULL if an element equal to a is not found
- * (equal as returned by t->compar())
- */
-avl *avl_remove_lock(avl_tree_lock *t, avl *a) WARNUNUSED;
-avl *avl_remove(avl_tree *t, avl *a) WARNUNUSED;
-
-/* Find the element into the tree that equal to a
- * (equal as returned by t->compar())
- * returns NULL is no element is equal to a
- */
-avl *avl_search_lock(avl_tree_lock *t, avl *a);
-avl *avl_search(avl_tree *t, avl *a);
-
-/* Initialize the avl_tree_lock
- */
-void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b));
-void avl_init(avl_tree *t, int (*compar)(void *a, void *b));
-
-
-int avl_traverse_lock(avl_tree_lock *t, int (*callback)(void *entry, void *data), void *data);
-int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *data);
-
-#endif /* avl.h */
diff --git a/src/backend_prometheus.c b/src/backend_prometheus.c
deleted file mode 100644
index bfcda9297..000000000
--- a/src/backend_prometheus.c
+++ /dev/null
@@ -1,479 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// PROMETHEUS
-// /api/v1/allmetrics?format=prometheus and /api/v1/allmetrics?format=prometheus_all_hosts
-
-static struct prometheus_server {
- const char *server;
- uint32_t hash;
- RRDHOST *host;
- time_t last_access;
- struct prometheus_server *next;
-} *prometheus_server_root = NULL;
-
-static inline time_t prometheus_server_last_access(const char *server, RRDHOST *host, time_t now) {
- static netdata_mutex_t prometheus_server_root_mutex = NETDATA_MUTEX_INITIALIZER;
-
- uint32_t hash = simple_hash(server);
-
- netdata_mutex_lock(&prometheus_server_root_mutex);
-
- struct prometheus_server *ps;
- for(ps = prometheus_server_root; ps ;ps = ps->next) {
- if (host == ps->host && hash == ps->hash && !strcmp(server, ps->server)) {
- time_t last = ps->last_access;
- ps->last_access = now;
- netdata_mutex_unlock(&prometheus_server_root_mutex);
- return last;
- }
- }
-
- ps = callocz(1, sizeof(struct prometheus_server));
- ps->server = strdupz(server);
- ps->hash = hash;
- ps->host = host;
- ps->last_access = now;
- ps->next = prometheus_server_root;
- prometheus_server_root = ps;
-
- netdata_mutex_unlock(&prometheus_server_root_mutex);
- return 0;
-}
-
-static inline size_t prometheus_name_copy(char *d, const char *s, size_t usable) {
- size_t n;
-
- for(n = 0; *s && n < usable ; d++, s++, n++) {
- register char c = *s;
-
- if(!isalnum(c)) *d = '_';
- else *d = c;
- }
- *d = '\0';
-
- return n;
-}
-
-static inline size_t prometheus_label_copy(char *d, const char *s, size_t usable) {
- size_t n;
-
- // make sure we can escape one character without overflowing the buffer
- usable--;
-
- for(n = 0; *s && n < usable ; d++, s++, n++) {
- register char c = *s;
-
- if(unlikely(c == '"' || c == '\\' || c == '\n')) {
- *d++ = '\\';
- n++;
- }
- *d = c;
- }
- *d = '\0';
-
- return n;
-}
-
-static inline char *prometheus_units_copy(char *d, const char *s, size_t usable) {
- const char *sorig = s;
- char *ret = d;
- size_t n;
-
- *d++ = '_';
- for(n = 1; *s && n < usable ; d++, s++, n++) {
- register char c = *s;
-
- if(!isalnum(c)) *d = '_';
- else *d = c;
- }
-
- if(n == 2 && sorig[0] == '%') {
- n = 0;
- d = ret;
- s = "_percent";
- for( ; *s && n < usable ; n++) *d++ = *s++;
- }
- else if(n > 3 && sorig[n-3] == '/' && sorig[n-2] == 's') {
- n = n - 2;
- d -= 2;
- s = "_persec";
- for( ; *s && n < usable ; n++) *d++ = *s++;
- }
-
- *d = '\0';
-
- return ret;
-}
-
-
-#define PROMETHEUS_ELEMENT_MAX 256
-#define PROMETHEUS_LABELS_MAX 1024
-
-static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb, const char *prefix, uint32_t options, time_t after, time_t before, int allhosts, int help, int types, int names, int timestamps) {
- rrdhost_rdlock(host);
-
- char hostname[PROMETHEUS_ELEMENT_MAX + 1];
- prometheus_label_copy(hostname, host->hostname, PROMETHEUS_ELEMENT_MAX);
-
- char labels[PROMETHEUS_LABELS_MAX + 1] = "";
- if(allhosts) {
- if(timestamps)
- buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1 %llu\n", hostname, host->program_name, host->program_version, now_realtime_usec() / USEC_PER_MS);
- else
- buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1\n", hostname, host->program_name, host->program_version);
-
- if(host->tags && *(host->tags)) {
- if(timestamps) {
- buffer_sprintf(wb, "netdata_host_tags_info{instance=\"%s\",%s} 1 %llu\n", hostname, host->tags, now_realtime_usec() / USEC_PER_MS);
-
- // deprecated, exists only for compatibility with older queries
- buffer_sprintf(wb, "netdata_host_tags{instance=\"%s\",%s} 1 %llu\n", hostname, host->tags, now_realtime_usec() / USEC_PER_MS);
- }
- else {
- buffer_sprintf(wb, "netdata_host_tags_info{instance=\"%s\",%s} 1\n", hostname, host->tags);
-
- // deprecated, exists only for compatibility with older queries
- buffer_sprintf(wb, "netdata_host_tags{instance=\"%s\",%s} 1\n", hostname, host->tags);
- }
-
- }
-
- snprintfz(labels, PROMETHEUS_LABELS_MAX, ",instance=\"%s\"", hostname);
- }
- else {
- if(timestamps)
- buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1 %llu\n", hostname, host->program_name, host->program_version, now_realtime_usec() / USEC_PER_MS);
- else
- buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1\n", hostname, host->program_name, host->program_version);
-
- if(host->tags && *(host->tags)) {
- if(timestamps) {
- buffer_sprintf(wb, "netdata_host_tags_info{%s} 1 %llu\n", host->tags, now_realtime_usec() / USEC_PER_MS);
-
- // deprecated, exists only for compatibility with older queries
- buffer_sprintf(wb, "netdata_host_tags{%s} 1 %llu\n", host->tags, now_realtime_usec() / USEC_PER_MS);
- }
- else {
- buffer_sprintf(wb, "netdata_host_tags_info{%s} 1\n", host->tags);
-
- // deprecated, exists only for compatibility with older queries
- buffer_sprintf(wb, "netdata_host_tags{%s} 1\n", host->tags);
- }
- }
- }
-
- // for each chart
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- char chart[PROMETHEUS_ELEMENT_MAX + 1];
- char context[PROMETHEUS_ELEMENT_MAX + 1];
- char family[PROMETHEUS_ELEMENT_MAX + 1];
- char units[PROMETHEUS_ELEMENT_MAX + 1] = "";
-
- prometheus_label_copy(chart, (names && st->name)?st->name:st->id, PROMETHEUS_ELEMENT_MAX);
- prometheus_label_copy(family, st->family, PROMETHEUS_ELEMENT_MAX);
- prometheus_name_copy(context, st->context, PROMETHEUS_ELEMENT_MAX);
-
- if(likely(backends_can_send_rrdset(options, st))) {
- rrdset_rdlock(st);
-
- int as_collected = ((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED);
- int homogeneus = 1;
- if(as_collected) {
- if(rrdset_flag_check(st, RRDSET_FLAG_HOMEGENEOUS_CHECK))
- rrdset_update_heterogeneous_flag(st);
-
- if(rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS))
- homogeneus = 0;
- }
- else {
- if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
- prometheus_units_copy(units, st->units, PROMETHEUS_ELEMENT_MAX);
- }
-
- if(unlikely(help))
- buffer_sprintf(wb, "\n# COMMENT %s chart \"%s\", context \"%s\", family \"%s\", units \"%s\"\n"
- , (homogeneus)?"homogeneus":"heterogeneous"
- , (names && st->name) ? st->name : st->id
- , st->context
- , st->family
- , st->units
- );
-
- // for each dimension
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rd->collections_counter) {
- char dimension[PROMETHEUS_ELEMENT_MAX + 1];
- char *suffix = "";
-
- if (as_collected) {
- // we need as-collected / raw data
-
- const char *t = "gauge", *h = "gives";
- if(rd->algorithm == RRD_ALGORITHM_INCREMENTAL ||
- rd->algorithm == RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL) {
- t = "counter";
- h = "delta gives";
- suffix = "_total";
- }
-
- if(homogeneus) {
- // all the dimensions of the chart, has the same algorithm, multiplier and divisor
- // we add all dimensions as labels
-
- prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
-
- if(unlikely(help))
- buffer_sprintf(wb
- , "# COMMENT %s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
- , prefix
- , context
- , suffix
- , (names && st->name) ? st->name : st->id
- , st->context
- , st->family
- , (names && rd->name) ? rd->name : rd->id
- , rd->multiplier
- , rd->divisor
- , h
- , st->units
- , t
- );
-
- if(unlikely(types))
- buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s %s\n"
- , prefix
- , context
- , suffix
- , t
- );
-
- if(timestamps)
- buffer_sprintf(wb
- , "%s_%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
- , prefix
- , context
- , suffix
- , chart
- , family
- , dimension
- , labels
- , rd->last_collected_value
- , timeval_msec(&rd->last_collected_time)
- );
- else
- buffer_sprintf(wb
- , "%s_%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " COLLECTED_NUMBER_FORMAT "\n"
- , prefix
- , context
- , suffix
- , chart
- , family
- , dimension
- , labels
- , rd->last_collected_value
- );
- }
- else {
- // the dimensions of the chart, do not have the same algorithm, multiplier or divisor
- // we create a metric per dimension
-
- prometheus_name_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
-
- if(unlikely(help))
- buffer_sprintf(wb
- , "# COMMENT %s_%s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
- , prefix
- , context
- , dimension
- , suffix
- , (names && st->name) ? st->name : st->id
- , st->context
- , st->family
- , (names && rd->name) ? rd->name : rd->id
- , rd->multiplier
- , rd->divisor
- , h
- , st->units
- , t
- );
-
- if(unlikely(types))
- buffer_sprintf(wb, "# COMMENT TYPE %s_%s_%s%s %s\n"
- , prefix
- , context
- , dimension
- , suffix
- , t
- );
-
- if(timestamps)
- buffer_sprintf(wb
- , "%s_%s_%s%s{chart=\"%s\",family=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
- , prefix
- , context
- , dimension
- , suffix
- , chart
- , family
- , labels
- , rd->last_collected_value
- , timeval_msec(&rd->last_collected_time)
- );
- else
- buffer_sprintf(wb
- , "%s_%s_%s%s{chart=\"%s\",family=\"%s\"%s} " COLLECTED_NUMBER_FORMAT "\n"
- , prefix
- , context
- , dimension
- , suffix
- , chart
- , family
- , labels
- , rd->last_collected_value
- );
- }
- }
- else {
- // we need average or sum of the data
-
- time_t first_t = after, last_t = before;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
-
- if(!isnan(value) && !isinf(value)) {
-
- if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
- suffix = "_average";
- else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM)
- suffix = "_sum";
-
- prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
-
- if (unlikely(help))
- buffer_sprintf(wb, "# COMMENT %s_%s%s%s: dimension \"%s\", value is %s, gauge, dt %llu to %llu inclusive\n"
- , prefix
- , context
- , units
- , suffix
- , (names && rd->name) ? rd->name : rd->id
- , st->units
- , (unsigned long long)first_t
- , (unsigned long long)last_t
- );
-
- if (unlikely(types))
- buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s%s gauge\n"
- , prefix
- , context
- , units
- , suffix
- );
-
- if(timestamps)
- buffer_sprintf(wb, "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " CALCULATED_NUMBER_FORMAT " %llu\n"
- , prefix
- , context
- , units
- , suffix
- , chart
- , family
- , dimension
- , labels
- , value
- , last_t * MSEC_PER_SEC
- );
- else
- buffer_sprintf(wb, "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " CALCULATED_NUMBER_FORMAT "\n"
- , prefix
- , context
- , units
- , suffix
- , chart
- , family
- , dimension
- , labels
- , value
- );
- }
- }
- }
- }
-
- rrdset_unlock(st);
- }
- }
-
- rrdhost_unlock(host);
-}
-
-static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, uint32_t options, const char *server, time_t now, int help) {
- if(!server || !*server) server = "default";
-
- time_t after = prometheus_server_last_access(server, host, now);
-
- int first_seen = 0;
- if(!after) {
- after = now - backend_update_every;
- first_seen = 1;
- }
-
- if(after > now) {
- // oops! this should never happen
- after = now - backend_update_every;
- }
-
- if(help) {
- int show_range = 1;
- char *mode;
- if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) {
- mode = "as collected";
- show_range = 0;
- }
- else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
- mode = "average";
- else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM)
- mode = "sum";
- else
- mode = "unknown";
-
- buffer_sprintf(wb, "# COMMENT netdata \"%s\" to %sprometheus \"%s\", source \"%s\", last seen %lu %s"
- , host->hostname
- , (first_seen)?"FIRST SEEN ":""
- , server
- , mode
- , (unsigned long)((first_seen)?0:(now - after))
- , (first_seen)?"never":"seconds ago"
- );
-
- if(show_range)
- buffer_sprintf(wb, ", time range %lu to %lu", (unsigned long)after, (unsigned long)now);
-
- buffer_strcat(wb, "\n\n");
- }
-
- return after;
-}
-
-void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps) {
- time_t before = now_realtime_sec();
-
- // we start at the point we had stopped before
- time_t after = prometheus_preparation(host, wb, options, server, before, help);
-
- rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, options, after, before, 0, help, types, names, timestamps);
-}
-
-void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps) {
- time_t before = now_realtime_sec();
-
- // we start at the point we had stopped before
- time_t after = prometheus_preparation(host, wb, options, server, before, help);
-
- rrd_rdlock();
- rrdhost_foreach_read(host) {
- rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, options, after, before, 1, help, types, names, timestamps);
- }
- rrd_unlock();
-}
diff --git a/src/backend_prometheus.h b/src/backend_prometheus.h
deleted file mode 100644
index b1a021baa..000000000
--- a/src/backend_prometheus.h
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-// Created by costa on 09/07/17.
-//
-
-#ifndef NETDATA_BACKEND_PROMETHEUS_H
-#define NETDATA_BACKEND_PROMETHEUS_H
-
-extern void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps);
-extern void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps);
-
-#endif //NETDATA_BACKEND_PROMETHEUS_H
diff --git a/src/backends.c b/src/backends.c
deleted file mode 100644
index 1360638f2..000000000
--- a/src/backends.c
+++ /dev/null
@@ -1,969 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// How backends work in netdata:
-//
-// 1. There is an independent thread that runs at the required interval
-// (for example, once every 10 seconds)
-//
-// 2. Every time it wakes, it calls the backend formatting functions to build
-// a buffer of data. This is a very fast, memory only operation.
-//
-// 3. If the buffer already includes data, the new data are appended.
-// If the buffer becomes too big, because the data cannot be sent, a
-// log is written and the buffer is discarded.
-//
-// 4. Then it tries to send all the data. It blocks until all the data are sent
-// or the socket returns an error.
-// If the time required for this is above the interval, it starts skipping
-// intervals, but the calculated values include the entire database, without
-// gaps (it remembers the timestamps and continues from where it stopped).
-//
-// 5. repeats the above forever.
-//
-
-const char *backend_prefix = "netdata";
-int backend_send_names = 1;
-int backend_update_every = 10;
-uint32_t backend_options = BACKEND_SOURCE_DATA_AVERAGE;
-
-// ----------------------------------------------------------------------------
-// helper functions for backends
-
-static inline size_t backend_name_copy(char *d, const char *s, size_t usable) {
- size_t n;
-
- for(n = 0; *s && n < usable ; d++, s++, n++) {
- char c = *s;
-
- if(c != '.' && !isalnum(c)) *d = '_';
- else *d = c;
- }
- *d = '\0';
-
- return n;
-}
-
-// calculate the SUM or AVERAGE of a dimension, for any timeframe
-// may return NAN if the database does not have any value in the give timeframe
-
-inline calculated_number backend_calculate_value_from_stored_data(
- RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
- , time_t *first_timestamp // the first point of the database used in this response
- , time_t *last_timestamp // the timestamp that should be reported to backend
-) {
- RRDHOST *host = st->rrdhost;
-
- // find the edges of the rrd database for this chart
- time_t first_t = rrdset_first_entry_t(st);
- time_t last_t = rrdset_last_entry_t(st);
- time_t update_every = st->update_every;
-
- // step back a little, to make sure we have complete data collection
- // for all metrics
- after -= update_every * 2;
- before -= update_every * 2;
-
- // align the time-frame
- after = after - (after % update_every);
- before = before - (before % update_every);
-
- // for before, loose another iteration
- // the latest point will be reported the next time
- before -= update_every;
-
- if(unlikely(after > before))
- // this can happen when update_every > before - after
- after = before;
-
- if(unlikely(after < first_t))
- after = first_t;
-
- if(unlikely(before > last_t))
- before = last_t;
-
- if(unlikely(before < first_t || after > last_t)) {
- // the chart has not been updated in the wanted timeframe
- debug(D_BACKEND, "BACKEND: %s.%s.%s: aligned timeframe %lu to %lu is outside the chart's database range %lu to %lu",
- host->hostname, st->id, rd->id,
- (unsigned long)after, (unsigned long)before,
- (unsigned long)first_t, (unsigned long)last_t
- );
- return NAN;
- }
-
- *first_timestamp = after;
- *last_timestamp = before;
-
- size_t counter = 0;
- calculated_number sum = 0;
-
- long start_at_slot = rrdset_time2slot(st, before),
- stop_at_slot = rrdset_time2slot(st, after),
- slot, stop_now = 0;
-
- for(slot = start_at_slot; !stop_now ; slot--) {
-
- if(unlikely(slot < 0)) slot = st->entries - 1;
- if(unlikely(slot == stop_at_slot)) stop_now = 1;
-
- storage_number n = rd->values[slot];
-
- if(unlikely(!does_storage_number_exist(n))) {
- // not collected
- continue;
- }
-
- calculated_number value = unpack_storage_number(n);
- sum += value;
-
- counter++;
- }
-
- if(unlikely(!counter)) {
- debug(D_BACKEND, "BACKEND: %s.%s.%s: no values stored in database for range %lu to %lu",
- host->hostname, st->id, rd->id,
- (unsigned long)after, (unsigned long)before
- );
- return NAN;
- }
-
- if(unlikely((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM))
- return sum;
-
- return sum / (calculated_number)counter;
-}
-
-
-// discard a response received by a backend
-// after logging a simple of it to error.log
-
-static inline int discard_response(BUFFER *b, const char *backend) {
- char sample[1024];
- const char *s = buffer_tostring(b);
- char *d = sample, *e = &sample[sizeof(sample) - 1];
-
- for(; *s && d < e ;s++) {
- char c = *s;
- if(unlikely(!isprint(c))) c = ' ';
- *d++ = c;
- }
- *d = '\0';
-
- info("BACKEND: received %zu bytes from %s backend. Ignoring them. Sample: '%s'", buffer_strlen(b), backend, sample);
- buffer_flush(b);
- return 0;
-}
-
-
-// ----------------------------------------------------------------------------
-// graphite backend
-
-static inline int format_dimension_collected_graphite_plaintext(
- BUFFER *b // the buffer to write data to
- , const char *prefix // the prefix to use
- , RRDHOST *host // the host this chart comes from
- , const char *hostname // the hostname (to override host->hostname)
- , RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
-) {
- (void)host;
- (void)after;
- (void)before;
- (void)options;
-
- char chart_name[RRD_ID_LENGTH_MAX + 1];
- char dimension_name[RRD_ID_LENGTH_MAX + 1];
- backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
- backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
-
- buffer_sprintf(
- b
- , "%s.%s.%s.%s " COLLECTED_NUMBER_FORMAT " %u\n"
- , prefix
- , hostname
- , chart_name
- , dimension_name
- , rd->last_collected_value
- , (uint32_t)rd->last_collected_time.tv_sec
- );
-
- return 1;
-}
-
-static inline int format_dimension_stored_graphite_plaintext(
- BUFFER *b // the buffer to write data to
- , const char *prefix // the prefix to use
- , RRDHOST *host // the host this chart comes from
- , const char *hostname // the hostname (to override host->hostname)
- , RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
-) {
- (void)host;
-
- char chart_name[RRD_ID_LENGTH_MAX + 1];
- char dimension_name[RRD_ID_LENGTH_MAX + 1];
- backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
- backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
-
- time_t first_t = after, last_t = before;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
-
- if(!isnan(value)) {
-
- buffer_sprintf(
- b
- , "%s.%s.%s.%s " CALCULATED_NUMBER_FORMAT " %u\n"
- , prefix
- , hostname
- , chart_name
- , dimension_name
- , value
- , (uint32_t) last_t
- );
-
- return 1;
- }
- return 0;
-}
-
-static inline int process_graphite_response(BUFFER *b) {
- return discard_response(b, "graphite");
-}
-
-
-// ----------------------------------------------------------------------------
-// opentsdb backend
-
-static inline int format_dimension_collected_opentsdb_telnet(
- BUFFER *b // the buffer to write data to
- , const char *prefix // the prefix to use
- , RRDHOST *host // the host this chart comes from
- , const char *hostname // the hostname (to override host->hostname)
- , RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
-) {
- (void)host;
- (void)after;
- (void)before;
- (void)options;
-
- char chart_name[RRD_ID_LENGTH_MAX + 1];
- char dimension_name[RRD_ID_LENGTH_MAX + 1];
- backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
- backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
-
- buffer_sprintf(
- b
- , "put %s.%s.%s %u " COLLECTED_NUMBER_FORMAT " host=%s%s%s\n"
- , prefix
- , chart_name
- , dimension_name
- , (uint32_t)rd->last_collected_time.tv_sec
- , rd->last_collected_value
- , hostname
- , (host->tags)?" ":""
- , (host->tags)?host->tags:""
- );
-
- return 1;
-}
-
-static inline int format_dimension_stored_opentsdb_telnet(
- BUFFER *b // the buffer to write data to
- , const char *prefix // the prefix to use
- , RRDHOST *host // the host this chart comes from
- , const char *hostname // the hostname (to override host->hostname)
- , RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
-) {
- (void)host;
-
- time_t first_t = after, last_t = before;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
-
- char chart_name[RRD_ID_LENGTH_MAX + 1];
- char dimension_name[RRD_ID_LENGTH_MAX + 1];
- backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
- backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
-
- if(!isnan(value)) {
-
- buffer_sprintf(
- b
- , "put %s.%s.%s %u " CALCULATED_NUMBER_FORMAT " host=%s%s%s\n"
- , prefix
- , chart_name
- , dimension_name
- , (uint32_t) last_t
- , value
- , hostname
- , (host->tags)?" ":""
- , (host->tags)?host->tags:""
- );
-
- return 1;
- }
- return 0;
-}
-
-static inline int process_opentsdb_response(BUFFER *b) {
- return discard_response(b, "opentsdb");
-}
-
-
-// ----------------------------------------------------------------------------
-// json backend
-
-static inline int format_dimension_collected_json_plaintext(
- BUFFER *b // the buffer to write data to
- , const char *prefix // the prefix to use
- , RRDHOST *host // the host this chart comes from
- , const char *hostname // the hostname (to override host->hostname)
- , RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
-) {
- (void)host;
- (void)after;
- (void)before;
- (void)options;
-
- const char *tags_pre = "", *tags_post = "", *tags = host->tags;
- if(!tags) tags = "";
-
- if(*tags) {
- if(*tags == '{' || *tags == '[' || *tags == '"') {
- tags_pre = "\"host_tags\":";
- tags_post = ",";
- }
- else {
- tags_pre = "\"host_tags\":\"";
- tags_post = "\",";
- }
- }
-
- buffer_sprintf(b, "{"
- "\"prefix\":\"%s\","
- "\"hostname\":\"%s\","
- "%s%s%s"
-
- "\"chart_id\":\"%s\","
- "\"chart_name\":\"%s\","
- "\"chart_family\":\"%s\","
- "\"chart_context\": \"%s\","
- "\"chart_type\":\"%s\","
- "\"units\": \"%s\","
-
- "\"id\":\"%s\","
- "\"name\":\"%s\","
- "\"value\":" COLLECTED_NUMBER_FORMAT ","
-
- "\"timestamp\": %u}\n",
- prefix,
- hostname,
- tags_pre, tags, tags_post,
-
- st->id,
- st->name,
- st->family,
- st->context,
- st->type,
- st->units,
-
- rd->id,
- rd->name,
- rd->last_collected_value,
-
- (uint32_t)rd->last_collected_time.tv_sec
- );
-
- return 1;
-}
-
-static inline int format_dimension_stored_json_plaintext(
- BUFFER *b // the buffer to write data to
- , const char *prefix // the prefix to use
- , RRDHOST *host // the host this chart comes from
- , const char *hostname // the hostname (to override host->hostname)
- , RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
-) {
- (void)host;
-
- time_t first_t = after, last_t = before;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
-
- if(!isnan(value)) {
- const char *tags_pre = "", *tags_post = "", *tags = host->tags;
- if(!tags) tags = "";
-
- if(*tags) {
- if(*tags == '{' || *tags == '[' || *tags == '"') {
- tags_pre = "\"host_tags\":";
- tags_post = ",";
- }
- else {
- tags_pre = "\"host_tags\":\"";
- tags_post = "\",";
- }
- }
-
- buffer_sprintf(b, "{"
- "\"prefix\":\"%s\","
- "\"hostname\":\"%s\","
- "%s%s%s"
-
- "\"chart_id\":\"%s\","
- "\"chart_name\":\"%s\","
- "\"chart_family\":\"%s\","
- "\"chart_context\": \"%s\","
- "\"chart_type\":\"%s\","
- "\"units\": \"%s\","
-
- "\"id\":\"%s\","
- "\"name\":\"%s\","
- "\"value\":" CALCULATED_NUMBER_FORMAT ","
-
- "\"timestamp\": %u}\n",
- prefix,
- hostname,
- tags_pre, tags, tags_post,
-
- st->id,
- st->name,
- st->family,
- st->context,
- st->type,
- st->units,
-
- rd->id,
- rd->name,
- value,
-
- (uint32_t) last_t
- );
-
- return 1;
- }
- return 0;
-}
-
-static inline int process_json_response(BUFFER *b) {
- return discard_response(b, "json");
-}
-
-
-// ----------------------------------------------------------------------------
-// the backend thread
-
-static SIMPLE_PATTERN *charts_pattern = NULL;
-static SIMPLE_PATTERN *hosts_pattern = NULL;
-
-inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) {
- RRDHOST *host = st->rrdhost;
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_BACKEND_IGNORE)))
- return 0;
-
- if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_BACKEND_SEND))) {
- // we have not checked this chart
- if(simple_pattern_matches(charts_pattern, st->id) || simple_pattern_matches(charts_pattern, st->name))
- rrdset_flag_set(st, RRDSET_FLAG_BACKEND_SEND);
- else {
- rrdset_flag_set(st, RRDSET_FLAG_BACKEND_IGNORE);
- debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s', because it is disabled for backends.", st->id, host->hostname);
- return 0;
- }
- }
-
- if(unlikely(!rrdset_is_available_for_backends(st))) {
- debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s', because it is not available for backends.", st->id, host->hostname);
- return 0;
- }
-
- if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE && !((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED))) {
- debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s' because its memory mode is '%s' and the backend requires database access.", st->id, host->hostname, rrd_memory_mode_name(host->rrd_memory_mode));
- return 0;
- }
-
- return 1;
-}
-
-inline uint32_t backend_parse_data_source(const char *source, uint32_t mode) {
- if(!strcmp(source, "raw") || !strcmp(source, "as collected") || !strcmp(source, "as-collected") || !strcmp(source, "as_collected") || !strcmp(source, "ascollected")) {
- mode |= BACKEND_SOURCE_DATA_AS_COLLECTED;
- mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AS_COLLECTED);
- }
- else if(!strcmp(source, "average")) {
- mode |= BACKEND_SOURCE_DATA_AVERAGE;
- mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AVERAGE);
- }
- else if(!strcmp(source, "sum") || !strcmp(source, "volume")) {
- mode |= BACKEND_SOURCE_DATA_SUM;
- mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_SUM);
- }
- else {
- error("BACKEND: invalid data source method '%s'.", source);
- }
-
- return mode;
-}
-
-static void backends_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *backends_main(void *ptr) {
- netdata_thread_cleanup_push(backends_main_cleanup, ptr);
-
- int default_port = 0;
- int sock = -1;
- BUFFER *b = buffer_create(1), *response = buffer_create(1);
- int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL;
- int (*backend_response_checker)(BUFFER *) = NULL;
-
- // ------------------------------------------------------------------------
- // collect configuration options
-
- struct timeval timeout = {
- .tv_sec = 0,
- .tv_usec = 0
- };
- int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0);
- const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average");
- const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite");
- const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost");
- backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata");
- const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname);
- backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", backend_update_every);
- int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10);
- long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", backend_update_every * 2 * 1000);
- backend_send_names = config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", backend_send_names);
-
- charts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send charts matching", "*"), NULL, SIMPLE_PATTERN_EXACT);
- hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
-
-
- // ------------------------------------------------------------------------
- // validate configuration options
- // and prepare for sending data to our backend
-
- backend_options = backend_parse_data_source(source, backend_options);
-
- if(timeoutms < 1) {
- error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, backend_update_every * 2 * 1000);
- timeoutms = backend_update_every * 2 * 1000;
- }
- timeout.tv_sec = (timeoutms * 1000) / 1000000;
- timeout.tv_usec = (timeoutms * 1000) % 1000000;
-
- if(!enabled || backend_update_every < 1)
- goto cleanup;
-
- // ------------------------------------------------------------------------
- // select the backend type
-
- if(!strcmp(type, "graphite") || !strcmp(type, "graphite:plaintext")) {
-
- default_port = 2003;
- backend_response_checker = process_graphite_response;
-
- if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
- backend_request_formatter = format_dimension_collected_graphite_plaintext;
- else
- backend_request_formatter = format_dimension_stored_graphite_plaintext;
-
- }
- else if(!strcmp(type, "opentsdb") || !strcmp(type, "opentsdb:telnet")) {
-
- default_port = 4242;
- backend_response_checker = process_opentsdb_response;
-
- if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
- backend_request_formatter = format_dimension_collected_opentsdb_telnet;
- else
- backend_request_formatter = format_dimension_stored_opentsdb_telnet;
-
- }
- else if (!strcmp(type, "json") || !strcmp(type, "json:plaintext")) {
-
- default_port = 5448;
- backend_response_checker = process_json_response;
-
- if ((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
- backend_request_formatter = format_dimension_collected_json_plaintext;
- else
- backend_request_formatter = format_dimension_stored_json_plaintext;
-
- }
- else {
- error("BACKEND: Unknown backend type '%s'", type);
- goto cleanup;
- }
-
- if(backend_request_formatter == NULL || backend_response_checker == NULL) {
- error("BACKEND: backend is misconfigured - disabling it.");
- goto cleanup;
- }
-
-
- // ------------------------------------------------------------------------
- // prepare the charts for monitoring the backend operation
-
- struct rusage thread;
-
- collected_number
- chart_buffered_metrics = 0,
- chart_lost_metrics = 0,
- chart_sent_metrics = 0,
- chart_buffered_bytes = 0,
- chart_received_bytes = 0,
- chart_sent_bytes = 0,
- chart_receptions = 0,
- chart_transmission_successes = 0,
- chart_transmission_failures = 0,
- chart_data_lost_events = 0,
- chart_lost_bytes = 0,
- chart_backend_reconnects = 0,
- chart_backend_latency = 0;
-
- RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, backend_update_every, RRDSET_TYPE_LINE);
- rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, backend_update_every, RRDSET_TYPE_AREA);
- rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
-
- RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_LINE);
- rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_ops, "failure", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(chart_ops, "read", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- /*
- * this is misleading - we can only measure the time we need to send data
- * this time is not related to the time required for the data to travel to
- * the backend database and the time that server needed to process them
- *
- * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html
- *
- RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, backend_update_every, RRDSET_TYPE_AREA);
- rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- */
-
- RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_STACKED);
- rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
-
-
- // ------------------------------------------------------------------------
- // prepare the backend main loop
-
- info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, backend_update_every, hostname, backend_prefix);
-
- usec_t step_ut = backend_update_every * USEC_PER_SEC;
- time_t after = now_realtime_sec();
- int failures = 0;
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- while(!netdata_exit) {
-
- // ------------------------------------------------------------------------
- // Wait for the next iteration point.
-
- heartbeat_next(&hb, step_ut);
- time_t before = now_realtime_sec();
- debug(D_BACKEND, "BACKEND: preparing buffer for timeframe %lu to %lu", (unsigned long)after, (unsigned long)before);
-
- // ------------------------------------------------------------------------
- // add to the buffer the data we need to send to the backend
-
- netdata_thread_disable_cancelability();
-
- size_t count_hosts = 0;
- size_t count_charts_total = 0;
- size_t count_dims_total = 0;
-
- rrd_rdlock();
- RRDHOST *host;
- rrdhost_foreach_read(host) {
- if(unlikely(!rrdhost_flag_check(host, RRDHOST_FLAG_BACKEND_SEND|RRDHOST_FLAG_BACKEND_DONT_SEND))) {
- char *name = (host == localhost)?"localhost":host->hostname;
- if (!hosts_pattern || simple_pattern_matches(hosts_pattern, name)) {
- rrdhost_flag_set(host, RRDHOST_FLAG_BACKEND_SEND);
- info("enabled backend for host '%s'", name);
- }
- else {
- rrdhost_flag_set(host, RRDHOST_FLAG_BACKEND_DONT_SEND);
- info("disabled backend for host '%s'", name);
- }
- }
-
- if(unlikely(!rrdhost_flag_check(host, RRDHOST_FLAG_BACKEND_SEND)))
- continue;
-
- rrdhost_rdlock(host);
-
- count_hosts++;
- size_t count_charts = 0;
- size_t count_dims = 0;
- size_t count_dims_skipped = 0;
-
- const char *__hostname = (host == localhost)?hostname:host->hostname;
-
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- if(likely(backends_can_send_rrdset(backend_options, st))) {
- rrdset_rdlock(st);
-
- count_charts++;
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if (likely(rd->last_collected_time.tv_sec >= after)) {
- chart_buffered_metrics += backend_request_formatter(b, backend_prefix, host, __hostname, st, rd, after, before, backend_options);
- count_dims++;
- }
- else {
- debug(D_BACKEND, "BACKEND: not sending dimension '%s' of chart '%s' from host '%s', its last data collection (%lu) is not within our timeframe (%lu to %lu)", rd->id, st->id, __hostname, (unsigned long)rd->last_collected_time.tv_sec, (unsigned long)after, (unsigned long)before);
- count_dims_skipped++;
- }
- }
-
- rrdset_unlock(st);
- }
- }
-
- debug(D_BACKEND, "BACKEND: sending host '%s', metrics of %zu dimensions, of %zu charts. Skipped %zu dimensions.", __hostname, count_dims, count_charts, count_dims_skipped);
- count_charts_total += count_charts;
- count_dims_total += count_dims;
-
- rrdhost_unlock(host);
- }
- rrd_unlock();
-
- netdata_thread_enable_cancelability();
-
- debug(D_BACKEND, "BACKEND: buffer has %zu bytes, added metrics for %zu dimensions, of %zu charts, from %zu hosts", buffer_strlen(b), count_dims_total, count_charts_total, count_hosts);
-
- // ------------------------------------------------------------------------
-
- chart_buffered_bytes = (collected_number)buffer_strlen(b);
-
- // reset the monitoring chart counters
- chart_received_bytes =
- chart_sent_bytes =
- chart_sent_metrics =
- chart_lost_metrics =
- chart_transmission_successes =
- chart_transmission_failures =
- chart_data_lost_events =
- chart_lost_bytes =
- chart_backend_reconnects =
- chart_backend_latency = 0;
-
- if(unlikely(netdata_exit)) break;
-
- //fprintf(stderr, "\nBACKEND BEGIN:\n%s\nBACKEND END\n", buffer_tostring(b)); // FIXME
- //fprintf(stderr, "after = %lu, before = %lu\n", after, before);
-
- // prepare for the next iteration
- // to add incrementally data to buffer
- after = before;
-
- // ------------------------------------------------------------------------
- // if we are connected, receive a response, without blocking
-
- if(likely(sock != -1)) {
- errno = 0;
-
- // loop through to collect all data
- while(sock != -1 && errno != EWOULDBLOCK) {
- buffer_need_bytes(response, 4096);
-
- ssize_t r = recv(sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
- if(likely(r > 0)) {
- // we received some data
- response->len += r;
- chart_received_bytes += r;
- chart_receptions++;
- }
- else if(r == 0) {
- error("BACKEND: '%s' closed the socket", destination);
- close(sock);
- sock = -1;
- }
- else {
- // failed to receive data
- if(errno != EAGAIN && errno != EWOULDBLOCK) {
- error("BACKEND: cannot receive data from backend '%s'.", destination);
- }
- }
- }
-
- // if we received data, process them
- if(buffer_strlen(response))
- backend_response_checker(response);
- }
-
- // ------------------------------------------------------------------------
- // if we are not connected, connect to a backend server
-
- if(unlikely(sock == -1)) {
- usec_t start_ut = now_monotonic_usec();
- size_t reconnects = 0;
-
- sock = connect_to_one_of(destination, default_port, &timeout, &reconnects, NULL, 0);
-
- chart_backend_reconnects += reconnects;
- chart_backend_latency += now_monotonic_usec() - start_ut;
- }
-
- if(unlikely(netdata_exit)) break;
-
- // ------------------------------------------------------------------------
- // if we are connected, send our buffer to the backend server
-
- if(likely(sock != -1)) {
- size_t len = buffer_strlen(b);
- usec_t start_ut = now_monotonic_usec();
- int flags = 0;
-#ifdef MSG_NOSIGNAL
- flags += MSG_NOSIGNAL;
-#endif
-
- ssize_t written = send(sock, buffer_tostring(b), len, flags);
- chart_backend_latency += now_monotonic_usec() - start_ut;
- if(written != -1 && (size_t)written == len) {
- // we sent the data successfully
- chart_transmission_successes++;
- chart_sent_bytes += written;
- chart_sent_metrics = chart_buffered_metrics;
-
- // reset the failures count
- failures = 0;
-
- // empty the buffer
- buffer_flush(b);
- }
- else {
- // oops! we couldn't send (all or some of the) data
- error("BACKEND: failed to write data to database backend '%s'. Willing to write %zu bytes, wrote %zd bytes. Will re-connect.", destination, len, written);
- chart_transmission_failures++;
-
- if(written != -1)
- chart_sent_bytes += written;
-
- // increment the counter we check for data loss
- failures++;
-
- // close the socket - we will re-open it next time
- close(sock);
- sock = -1;
- }
- }
- else {
- error("BACKEND: failed to update database backend '%s'", destination);
- chart_transmission_failures++;
-
- // increment the counter we check for data loss
- failures++;
- }
-
- if(failures > buffer_on_failures) {
- // too bad! we are going to lose data
- chart_lost_bytes += buffer_strlen(b);
- error("BACKEND: reached %d backend failures. Flushing buffers to protect this host - this results in data loss on back-end server '%s'", failures, destination);
- buffer_flush(b);
- failures = 0;
- chart_data_lost_events++;
- chart_lost_metrics = chart_buffered_metrics;
- }
-
- if(unlikely(netdata_exit)) break;
-
- // ------------------------------------------------------------------------
- // update the monitoring charts
-
- if(likely(chart_ops->counter_done)) rrdset_next(chart_ops);
- rrddim_set(chart_ops, "read", chart_receptions);
- rrddim_set(chart_ops, "write", chart_transmission_successes);
- rrddim_set(chart_ops, "discard", chart_data_lost_events);
- rrddim_set(chart_ops, "failure", chart_transmission_failures);
- rrddim_set(chart_ops, "reconnect", chart_backend_reconnects);
- rrdset_done(chart_ops);
-
- if(likely(chart_metrics->counter_done)) rrdset_next(chart_metrics);
- rrddim_set(chart_metrics, "buffered", chart_buffered_metrics);
- rrddim_set(chart_metrics, "lost", chart_lost_metrics);
- rrddim_set(chart_metrics, "sent", chart_sent_metrics);
- rrdset_done(chart_metrics);
-
- if(likely(chart_bytes->counter_done)) rrdset_next(chart_bytes);
- rrddim_set(chart_bytes, "buffered", chart_buffered_bytes);
- rrddim_set(chart_bytes, "lost", chart_lost_bytes);
- rrddim_set(chart_bytes, "sent", chart_sent_bytes);
- rrddim_set(chart_bytes, "received", chart_received_bytes);
- rrdset_done(chart_bytes);
-
- /*
- if(likely(chart_latency->counter_done)) rrdset_next(chart_latency);
- rrddim_set(chart_latency, "latency", chart_backend_latency);
- rrdset_done(chart_latency);
- */
-
- getrusage(RUSAGE_THREAD, &thread);
- if(likely(chart_rusage->counter_done)) rrdset_next(chart_rusage);
- rrddim_set(chart_rusage, "user", thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
- rrddim_set(chart_rusage, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
- rrdset_done(chart_rusage);
-
- if(likely(buffer_strlen(b) == 0))
- chart_buffered_metrics = 0;
-
- if(unlikely(netdata_exit)) break;
- }
-
-cleanup:
- if(sock != -1)
- close(sock);
-
- buffer_free(b);
- buffer_free(response);
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/backends.h b/src/backends.h
deleted file mode 100644
index e882f3db1..000000000
--- a/src/backends.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef NETDATA_BACKENDS_H
-#define NETDATA_BACKENDS_H 1
-
-#define BACKEND_SOURCE_DATA_AS_COLLECTED 0x00000001
-#define BACKEND_SOURCE_DATA_AVERAGE 0x00000002
-#define BACKEND_SOURCE_DATA_SUM 0x00000004
-
-#define BACKEND_SOURCE_BITS (BACKEND_SOURCE_DATA_AS_COLLECTED|BACKEND_SOURCE_DATA_AVERAGE|BACKEND_SOURCE_DATA_SUM)
-
-extern int backend_send_names;
-extern int backend_update_every;
-extern uint32_t backend_options;
-extern const char *backend_prefix;
-
-extern void *backends_main(void *ptr);
-
-extern int backends_can_send_rrdset(uint32_t options, RRDSET *st);
-extern uint32_t backend_parse_data_source(const char *source, uint32_t mode);
-
-extern calculated_number backend_calculate_value_from_stored_data(
- RRDSET *st // the chart
- , RRDDIM *rd // the dimension
- , time_t after // the start timestamp
- , time_t before // the end timestamp
- , uint32_t options // BACKEND_SOURCE_* bitmap
- , time_t *first_timestamp // the timestamp of the first point used in this response
- , time_t *last_timestamp // the timestamp that should be reported to backend
-);
-
-#endif /* NETDATA_BACKENDS_H */
diff --git a/src/cgroup-network.c b/src/cgroup-network.c
deleted file mode 100644
index 0e2d5163a..000000000
--- a/src/cgroup-network.c
+++ /dev/null
@@ -1,651 +0,0 @@
-#include "common.h"
-#include <libgen.h>
-
-#ifdef HAVE_SETNS
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* See feature_test_macros(7) */
-#endif
-#include <sched.h>
-#endif
-
-char *host_prefix = "";
-
-char environment_variable2[FILENAME_MAX + 50] = "";
-char *environment[] = {
- "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
- environment_variable2,
- NULL
-};
-
-
-// ----------------------------------------------------------------------------
-// callback required by fatal()
-
-void netdata_cleanup_and_exit(int ret) {
- exit(ret);
-}
-void health_reload(void) {};
-void rrdhost_save_all(void) {};
-
-
-// ----------------------------------------------------------------------------
-
-struct iface {
- const char *device;
- uint32_t hash;
-
- unsigned int ifindex;
- unsigned int iflink;
-
- struct iface *next;
-};
-
-unsigned int read_iface_iflink(const char *prefix, const char *iface) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/iflink", prefix?prefix:"", iface);
-
- unsigned long long iflink = 0;
- int ret = read_single_number_file(filename, &iflink);
- if(ret) error("Cannot read '%s'.", filename);
-
- return (unsigned int)iflink;
-}
-
-unsigned int read_iface_ifindex(const char *prefix, const char *iface) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/ifindex", prefix?prefix:"", iface);
-
- unsigned long long ifindex = 0;
- int ret = read_single_number_file(filename, &ifindex);
- if(ret) error("Cannot read '%s'.", filename);
-
- return (unsigned int)ifindex;
-}
-
-struct iface *read_proc_net_dev(const char *prefix) {
- procfile *ff = NULL;
- char filename[FILENAME_MAX + 1];
-
- snprintfz(filename, FILENAME_MAX, "%s%s", prefix?prefix:"", "/proc/net/dev");
- ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- error("Cannot open file '%s'", filename);
- return NULL;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) {
- error("Cannot read file '%s'", filename);
- return NULL;
- }
-
- size_t lines = procfile_lines(ff), l;
- struct iface *root = NULL;
- for(l = 2; l < lines ;l++) {
- if (unlikely(procfile_linewords(ff, l) < 1)) continue;
-
- struct iface *t = callocz(1, sizeof(struct iface));
- t->device = strdupz(procfile_lineword(ff, l, 0));
- t->hash = simple_hash(t->device);
- t->ifindex = read_iface_ifindex(prefix, t->device);
- t->iflink = read_iface_iflink(prefix, t->device);
- t->next = root;
- root = t;
- }
-
- procfile_close(ff);
-
- return root;
-}
-
-void free_iface(struct iface *iface) {
- freez((void *)iface->device);
- freez(iface);
-}
-
-void free_host_ifaces(struct iface *iface) {
- while(iface) {
- struct iface *t = iface->next;
- free_iface(iface);
- iface = t;
- }
-}
-
-int iface_is_eligible(struct iface *iface) {
- if(iface->iflink != iface->ifindex)
- return 1;
-
- return 0;
-}
-
-int eligible_ifaces(struct iface *root) {
- int eligible = 0;
-
- struct iface *t;
- for(t = root; t ; t = t->next)
- if(iface_is_eligible(t))
- eligible++;
-
- return eligible;
-}
-
-static void continue_as_child(void) {
- pid_t child = fork();
- int status;
- pid_t ret;
-
- if (child < 0)
- error("fork() failed");
-
- /* Only the child returns */
- if (child == 0)
- return;
-
- for (;;) {
- ret = waitpid(child, &status, WUNTRACED);
- if ((ret == child) && (WIFSTOPPED(status))) {
- /* The child suspended so suspend us as well */
- kill(getpid(), SIGSTOP);
- kill(child, SIGCONT);
- } else {
- break;
- }
- }
-
- /* Return the child's exit code if possible */
- if (WIFEXITED(status)) {
- exit(WEXITSTATUS(status));
- } else if (WIFSIGNALED(status)) {
- kill(getpid(), WTERMSIG(status));
- }
-
- exit(EXIT_FAILURE);
-}
-
-int proc_pid_fd(const char *prefix, const char *ns, pid_t pid) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/%s", prefix?prefix:"", (int)pid, ns);
- int fd = open(filename, O_RDONLY);
-
- if(fd == -1)
- error("Cannot open file '%s'", filename);
-
- return fd;
-}
-
-static struct ns {
- int nstype;
- int fd;
- int status;
- const char *name;
- const char *path;
-} all_ns[] = {
- // { .nstype = CLONE_NEWUSER, .fd = -1, .status = -1, .name = "user", .path = "ns/user" },
- // { .nstype = CLONE_NEWCGROUP, .fd = -1, .status = -1, .name = "cgroup", .path = "ns/cgroup" },
- // { .nstype = CLONE_NEWIPC, .fd = -1, .status = -1, .name = "ipc", .path = "ns/ipc" },
- // { .nstype = CLONE_NEWUTS, .fd = -1, .status = -1, .name = "uts", .path = "ns/uts" },
- { .nstype = CLONE_NEWNET, .fd = -1, .status = -1, .name = "network", .path = "ns/net" },
- { .nstype = CLONE_NEWPID, .fd = -1, .status = -1, .name = "pid", .path = "ns/pid" },
- { .nstype = CLONE_NEWNS, .fd = -1, .status = -1, .name = "mount", .path = "ns/mnt" },
-
- // terminator
- { .nstype = 0, .fd = -1, .status = -1, .name = NULL, .path = NULL }
-};
-
-int switch_namespace(const char *prefix, pid_t pid) {
-#ifdef HAVE_SETNS
-
- int i;
- for(i = 0; all_ns[i].name ; i++)
- all_ns[i].fd = proc_pid_fd(prefix, all_ns[i].path, pid);
-
- int root_fd = proc_pid_fd(prefix, "root", pid);
- int cwd_fd = proc_pid_fd(prefix, "cwd", pid);
-
- setgroups(0, NULL);
-
- // 2 passes - found it at nsenter source code
- // this is related CLONE_NEWUSER functionality
-
- // FIXME: this code cannot switch user namespace
- // Fortunately, we don't need it.
-
- int pass, errors = 0;
- for(pass = 0; pass < 2 ;pass++) {
- for(i = 0; all_ns[i].name ; i++) {
- if (all_ns[i].fd != -1 && all_ns[i].status == -1) {
- if(setns(all_ns[i].fd, all_ns[i].nstype) == -1) {
- if(pass == 1) {
- all_ns[i].status = 0;
- error("Cannot switch to %s namespace of pid %d", all_ns[i].name, (int) pid);
- errors++;
- }
- }
- else
- all_ns[i].status = 1;
- }
- }
- }
-
- setgroups(0, NULL);
-
- if(root_fd != -1) {
- if(fchdir(root_fd) < 0)
- error("Cannot fchdir() to pid %d root directory", (int)pid);
-
- if(chroot(".") < 0)
- error("Cannot chroot() to pid %d root directory", (int)pid);
-
- close(root_fd);
- }
-
- if(cwd_fd != -1) {
- if(fchdir(cwd_fd) < 0)
- error("Cannot fchdir() to pid %d current working directory", (int)pid);
-
- close(cwd_fd);
- }
-
- int do_fork = 0;
- for(i = 0; all_ns[i].name ; i++)
- if(all_ns[i].fd != -1) {
-
- // CLONE_NEWPID requires a fork() to become effective
- if(all_ns[i].nstype == CLONE_NEWPID && all_ns[i].status)
- do_fork = 1;
-
- close(all_ns[i].fd);
- }
-
- if(do_fork)
- continue_as_child();
-
- return 0;
-
-#else
-
- errno = ENOSYS;
- error("setns() is missing on this system.");
- return 1;
-
-#endif
-}
-
-pid_t read_pid_from_cgroup_file(const char *filename) {
- FILE *fp = fopen(filename, "r");
- if(!fp) {
- error("Cannot read file '%s'.", filename);
- return 0;
- }
-
- char buffer[100 + 1];
- pid_t pid = 0;
- char *s;
- while((s = fgets(buffer, 100, fp))) {
- buffer[100] = '\0';
- pid = atoi(s);
- if(pid > 0) break;
- }
-
- fclose(fp);
- return pid;
-}
-
-pid_t read_pid_from_cgroup_files(const char *path) {
- char filename[FILENAME_MAX + 1];
-
- snprintfz(filename, FILENAME_MAX, "%s/cgroup.procs", path);
- pid_t pid = read_pid_from_cgroup_file(filename);
- if(pid > 0) return pid;
-
- snprintfz(filename, FILENAME_MAX, "%s/tasks", path);
- return read_pid_from_cgroup_file(filename);
-}
-
-pid_t read_pid_from_cgroup(const char *path) {
- pid_t pid = read_pid_from_cgroup_files(path);
- if (pid > 0) return pid;
-
- DIR *dir = opendir(path);
- if (!dir) {
- error("cannot read directory '%s'", path);
- return 0;
- }
-
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- if (de->d_type == DT_DIR
- && (
- (de->d_name[0] == '.' && de->d_name[1] == '\0')
- || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- ))
- continue;
-
- if (de->d_type == DT_DIR) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name);
- pid = read_pid_from_cgroup(filename);
- if(pid > 0) break;
- }
- }
- closedir(dir);
- return pid;
-}
-
-// ----------------------------------------------------------------------------
-// send the result to netdata
-
-struct found_device {
- const char *host_device;
- const char *guest_device;
-
- uint32_t host_device_hash;
-
- struct found_device *next;
-} *detected_devices = NULL;
-
-void add_device(const char *host, const char *guest) {
- uint32_t hash = simple_hash(host);
-
- if(guest && (!*guest || strcmp(host, guest) == 0))
- guest = NULL;
-
- struct found_device *f;
- for(f = detected_devices; f ; f = f->next) {
- if(f->host_device_hash == hash && strcmp(host, f->host_device) == 0) {
-
- if(guest && !f->guest_device)
- f->guest_device = strdupz(guest);
-
- return;
- }
- }
-
- f = mallocz(sizeof(struct found_device));
- f->host_device = strdupz(host);
- f->host_device_hash = hash;
- f->guest_device = (guest)?strdupz(guest):NULL;
- f->next = detected_devices;
- detected_devices = f;
-}
-
-int send_devices(void) {
- int found = 0;
-
- struct found_device *f;
- for(f = detected_devices; f ; f = f->next) {
- found++;
- printf("%s %s\n", f->host_device, (f->guest_device)?f->guest_device:f->host_device);
- }
-
- return found;
-}
-
-// ----------------------------------------------------------------------------
-// this function should be called only **ONCE**
-// also it has to be the **LAST** to be called
-// since it switches namespaces, so after this call, everything is different!
-
-void detect_veth_interfaces(pid_t pid) {
- struct iface *host, *cgroup, *h, *c;
- const char *prefix = getenv("NETDATA_HOST_PREFIX");
-
- host = read_proc_net_dev(prefix);
- if(!host) {
- errno = 0;
- error("cannot read host interface list.");
- return;
- }
-
- if(!eligible_ifaces(host)) {
- errno = 0;
- error("there are no double-linked host interfaces available.");
- goto cleanup;
- }
-
- if(switch_namespace(prefix, pid)) {
- errno = 0;
- error("cannot switch to the namespace of pid %u", (unsigned int) pid);
- goto cleanup;
- }
-
- cgroup = read_proc_net_dev(NULL);
- if(!cgroup) {
- errno = 0;
- error("cannot read cgroup interface list.");
- goto cleanup;
- }
-
- if(!eligible_ifaces(cgroup)) {
- errno = 0;
- error("there are not double-linked cgroup interfaces available.");
- goto cleanup;
- }
-
- for(h = host; h ; h = h->next) {
- if(iface_is_eligible(h)) {
- for (c = cgroup; c; c = c->next) {
- if(iface_is_eligible(c) && h->ifindex == c->iflink && h->iflink == c->ifindex) {
- add_device(h->device, c->device);
- }
- }
- }
- }
-
-cleanup:
- free_host_ifaces(host);
-}
-
-// ----------------------------------------------------------------------------
-// call the external helper
-
-#define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048
-void call_the_helper(pid_t pid, const char *cgroup) {
- if(setresuid(0, 0, 0) == -1)
- error("setresuid(0, 0, 0) failed.");
-
- char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
- if(cgroup)
- snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup);
- else
- snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid);
-
- info("running: %s", buffer);
-
- pid_t cgroup_pid;
- FILE *fp = mypopene(buffer, &cgroup_pid, environment);
- if(fp) {
- char *s;
- while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) {
- trim(s);
-
- if(*s && *s != '\n') {
- char *t = s;
- while(*t && *t != ' ') t++;
- if(*t == ' ') {
- *t = '\0';
- t++;
- }
-
- if(!*s || !*t) continue;
- add_device(s, t);
- }
- }
-
- mypclose(fp, cgroup_pid);
- }
- else
- error("cannot execute cgroup-network helper script: %s", buffer);
-}
-
-int is_valid_path_symbol(char c) {
- switch(c) {
- case '/': // path separators
- case '\\': // needed for virsh domains \x2d1\x2dname
- case ' ': // space
- case '-': // hyphen
- case '_': // underscore
- case '.': // dot
- case ',': // comma
- return 1;
-
- default:
- return 0;
- }
-}
-
-// we will pass this path a shell script running as root
-// so, we need to make sure the path will be valid
-// and will not include anything that could allow
-// the caller use shell expansion for gaining escalated
-// privileges.
-int verify_path(const char *path) {
- struct stat sb;
-
- char c;
- const char *s = path;
- while((c = *s++)) {
- if(!( isalnum(c) || is_valid_path_symbol(c) )) {
- error("invalid character in path '%s'", path);
- return -1;
- }
- }
-
- if(strstr(path, "\\") && !strstr(path, "\\x")) {
- error("invalid escape sequence in path '%s'", path);
- return 1;
- }
-
- if(strstr(path, "/../")) {
- error("invalid parent path sequence detected in '%s'", path);
- return 1;
- }
-
- if(path[0] != '/') {
- error("only absolute path names are supported - invalid path '%s'", path);
- return -1;
- }
-
- if (stat(path, &sb) == -1) {
- error("cannot stat() path '%s'", path);
- return -1;
- }
-
- if((sb.st_mode & S_IFMT) != S_IFDIR) {
- error("path '%s' is not a directory", path);
- return -1;
- }
-
- return 0;
-}
-
-/*
-char *fix_path_variable(void) {
- const char *path = getenv("PATH");
- if(!path || !*path) return 0;
-
- char *p = strdupz(path);
- char *safe_path = callocz(1, strlen(p) + strlen("PATH=") + 1);
- strcpy(safe_path, "PATH=");
-
- int added = 0;
- char *ptr = p;
- while(ptr && *ptr) {
- char *s = strsep(&ptr, ":");
- if(s && *s) {
- if(verify_path(s) == -1) {
- error("the PATH variable includes an invalid path '%s' - removed it.", s);
- }
- else {
- info("the PATH variable includes a valid path '%s'.", s);
- if(added) strcat(safe_path, ":");
- strcat(safe_path, s);
- added++;
- }
- }
- }
-
- info("unsafe PATH: '%s'.", path);
- info(" safe PATH: '%s'.", safe_path);
-
- freez(p);
- return safe_path;
-}
-*/
-
-// ----------------------------------------------------------------------------
-// main
-
-void usage(void) {
- fprintf(stderr, "%s [ -p PID | --pid PID | --cgroup /path/to/cgroup ]\n", program_name);
- exit(1);
-}
-
-int main(int argc, char **argv) {
- pid_t pid = 0;
-
- program_name = argv[0];
- program_version = VERSION;
- error_log_syslog = 0;
-
-
- // ------------------------------------------------------------------------
- // make sure NETDATA_HOST_PREFIX is safe
-
- host_prefix = getenv("NETDATA_HOST_PREFIX");
- if(!host_prefix || !*host_prefix)
- host_prefix = "";
-
- if(host_prefix[0] != '\0' && verify_path(host_prefix) == -1)
- fatal("invalid NETDATA_HOST_PREFIX '%s'", host_prefix);
-
- // ------------------------------------------------------------------------
- // build a safe environment for our script
-
- // the first environment variable is a fixed PATH=
- snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", host_prefix);
-
- // ------------------------------------------------------------------------
-
- if(argc == 2 && (!strcmp(argv[1], "version") || !strcmp(argv[1], "-version") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "-v") || !strcmp(argv[1], "-V"))) {
- fprintf(stderr, "cgroup-network %s\n", VERSION);
- exit(0);
- }
-
- if(argc != 3)
- usage();
-
- if(!strcmp(argv[1], "-p") || !strcmp(argv[1], "--pid")) {
- pid = atoi(argv[2]);
-
- if(pid <= 0) {
- errno = 0;
- error("Invalid pid %d given", (int) pid);
- return 2;
- }
-
- call_the_helper(pid, NULL);
- }
- else if(!strcmp(argv[1], "--cgroup")) {
- char *cgroup = argv[2];
- if(verify_path(cgroup) == -1)
- fatal("cgroup '%s' does not exist or is not valid.", cgroup);
-
- pid = read_pid_from_cgroup(cgroup);
- call_the_helper(pid, cgroup);
-
- if(pid <= 0 && !detected_devices) {
- errno = 0;
- error("Cannot find a cgroup PID from cgroup '%s'", cgroup);
- }
- }
- else
- usage();
-
- if(pid > 0)
- detect_veth_interfaces(pid);
-
- int found = send_devices();
- if(found <= 0) return 1;
- return 0;
-}
diff --git a/src/clocks.c b/src/clocks.c
deleted file mode 100644
index 2b1c36e3f..000000000
--- a/src/clocks.c
+++ /dev/null
@@ -1,137 +0,0 @@
-#include "common.h"
-
-#ifndef HAVE_CLOCK_GETTIME
-inline int clock_gettime(clockid_t clk_id, struct timespec *ts) {
- struct timeval tv;
- if(unlikely(gettimeofday(&tv, NULL) == -1))
- return -1;
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC;
- return 0;
-}
-#endif
-
-static inline time_t now_sec(clockid_t clk_id) {
- struct timespec ts;
- if(unlikely(clock_gettime(clk_id, &ts) == -1))
- return 0;
- return ts.tv_sec;
-}
-
-static inline usec_t now_usec(clockid_t clk_id) {
- struct timespec ts;
- if(unlikely(clock_gettime(clk_id, &ts) == -1))
- return 0;
- return (usec_t)ts.tv_sec * USEC_PER_SEC + (ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC;
-}
-
-static inline int now_timeval(clockid_t clk_id, struct timeval *tv) {
- struct timespec ts;
-
- 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;
-}
-
-inline time_t now_realtime_sec(void) {
- return now_sec(CLOCK_REALTIME);
-}
-
-inline usec_t now_realtime_usec(void) {
- return now_usec(CLOCK_REALTIME);
-}
-
-inline int now_realtime_timeval(struct timeval *tv) {
- return now_timeval(CLOCK_REALTIME, tv);
-}
-
-inline time_t now_monotonic_sec(void) {
- return now_sec(CLOCK_MONOTONIC);
-}
-
-inline usec_t now_monotonic_usec(void) {
- return now_usec(CLOCK_MONOTONIC);
-}
-
-inline int now_monotonic_timeval(struct timeval *tv) {
- return now_timeval(CLOCK_MONOTONIC, tv);
-}
-
-inline time_t now_boottime_sec(void) {
- return now_sec(CLOCK_BOOTTIME);
-}
-
-inline usec_t now_boottime_usec(void) {
- return now_usec(CLOCK_BOOTTIME);
-}
-
-inline int now_boottime_timeval(struct timeval *tv) {
- return now_timeval(CLOCK_BOOTTIME, tv);
-}
-
-inline usec_t timeval_usec(struct timeval *tv) {
- return (usec_t)tv->tv_sec * USEC_PER_SEC + (tv->tv_usec % USEC_PER_SEC);
-}
-
-inline msec_t timeval_msec(struct timeval *tv) {
- return (msec_t)tv->tv_sec * MSEC_PER_SEC + ((tv->tv_usec % USEC_PER_SEC) / MSEC_PER_SEC);
-}
-
-inline susec_t dt_usec_signed(struct timeval *now, struct timeval *old) {
- usec_t ts1 = timeval_usec(now);
- usec_t ts2 = timeval_usec(old);
-
- if(likely(ts1 >= ts2)) return (susec_t)(ts1 - ts2);
- return -((susec_t)(ts2 - ts1));
-}
-
-inline usec_t dt_usec(struct timeval *now, struct timeval *old) {
- usec_t ts1 = timeval_usec(now);
- usec_t ts2 = timeval_usec(old);
- return (ts1 > ts2) ? (ts1 - ts2) : (ts2 - ts1);
-}
-
-inline void heartbeat_init(heartbeat_t *hb)
-{
- *hb = 0ULL;
-}
-
-usec_t heartbeat_next(heartbeat_t *hb, usec_t tick)
-{
- heartbeat_t now = now_monotonic_usec();
- usec_t next = now - (now % tick) + tick;
-
- while(now < next) {
- sleep_usec(next - now);
- now = now_monotonic_usec();
- }
-
- if(likely(*hb != 0ULL)) {
- usec_t dt = now - *hb;
- *hb = now;
-
- if(unlikely(dt >= tick + tick / 2)) {
- errno = 0;
- error("heartbeat missed %llu microseconds", dt - tick);
- }
-
- return dt;
- }
- else {
- *hb = now;
- return 0ULL;
- }
-}
-
-inline usec_t heartbeat_dt_usec(heartbeat_t *hb)
-{
- if(!*hb)
- return 0ULL;
- return now_monotonic_usec() - *hb;
-}
diff --git a/src/clocks.h b/src/clocks.h
deleted file mode 100644
index ca5715254..000000000
--- a/src/clocks.h
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef NETDATA_CLOCKS_H
-#define NETDATA_CLOCKS_H 1
-
-#ifndef HAVE_STRUCT_TIMESPEC
-struct timespec {
- time_t tv_sec; /* seconds */
- long tv_nsec; /* nanoseconds */
-};
-#endif
-
-#ifndef HAVE_CLOCKID_T
-typedef int clockid_t;
-#endif
-
-typedef unsigned long long nsec_t;
-typedef unsigned long long msec_t;
-typedef unsigned long long usec_t;
-typedef long long susec_t;
-
-typedef usec_t heartbeat_t;
-
-/* Linux value is as good as any other */
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME 0
-#endif
-
-#ifndef CLOCK_MONOTONIC
-/* fallback to CLOCK_REALTIME if not available */
-#define CLOCK_MONOTONIC CLOCK_REALTIME
-#endif
-
-#ifndef CLOCK_BOOTTIME
-
-#ifdef CLOCK_UPTIME
-/* CLOCK_BOOTTIME falls back to CLOCK_UPTIME on FreeBSD */
-#define CLOCK_BOOTTIME CLOCK_UPTIME
-#else // CLOCK_UPTIME
-/* CLOCK_BOOTTIME falls back to CLOCK_MONOTONIC */
-#define CLOCK_BOOTTIME CLOCK_MONOTONIC
-#endif // CLOCK_UPTIME
-
-#else // CLOCK_BOOTTIME
-
-#ifdef HAVE_CLOCK_GETTIME
-#define CLOCK_BOOTTIME_IS_AVAILABLE 1 // required for /proc/uptime
-#endif // HAVE_CLOCK_GETTIME
-
-#endif // CLOCK_BOOTTIME
-
-#define NSEC_PER_MSEC 1000000ULL
-
-#define NSEC_PER_SEC 1000000000ULL
-#define NSEC_PER_USEC 1000ULL
-
-#define USEC_PER_SEC 1000000ULL
-#define MSEC_PER_SEC 1000ULL
-
-#define USEC_PER_MS 1000ULL
-
-#ifndef HAVE_CLOCK_GETTIME
-/* Fallback function for POSIX.1-2001 clock_gettime() function.
- *
- * We use a realtime clock from gettimeofday(), this will
- * make systems without clock_gettime() support sensitive
- * to time jumps or hibernation/suspend side effects.
- */
-extern int clock_gettime(clockid_t clk_id, struct timespec *ts);
-#endif
-
-/*
- * Three clocks are available (cf. man 3 clock_gettime):
- *
- * REALTIME clock (i.e. wall-clock):
- * This clock is affected by discontinuous jumps in the system time
- * (e.g., if the system administrator manually changes the clock), and by the incremental adjustments performed by adjtime(3) and NTP.
- *
- * MONOTONIC clock
- * Clock that cannot be set and represents monotonic time since some unspecified starting point.
- * This clock is not affected by discontinuous jumps in the system time
- * (e.g., if the system administrator manually changes the clock), but is affected by the incremental adjustments performed by adjtime(3) and NTP.
- * If not available on the system, this clock falls back to REALTIME clock.
- *
- * BOOTTIME clock
- * Identical to CLOCK_MONOTONIC, except it also includes any time that the system is suspended.
- * This allows applications to get a suspend-aware monotonic clock without having to deal with the complications of CLOCK_REALTIME,
- * which may have discontinuities if the time is changed using settimeofday(2).
- * If not available on the system, this clock falls back to MONOTONIC clock.
- *
- * All now_*_timeval() functions fill the `struct timeval` with the time from the appropriate clock.
- * Those functions return 0 on success, -1 else with errno set appropriately.
- *
- * All now_*_sec() functions return the time in seconds from the approriate clock, or 0 on error.
- * All now_*_usec() functions return the time in microseconds from the approriate clock, or 0 on error.
- */
-extern int now_realtime_timeval(struct timeval *tv);
-extern time_t now_realtime_sec(void);
-extern usec_t now_realtime_usec(void);
-
-extern int now_monotonic_timeval(struct timeval *tv);
-extern time_t now_monotonic_sec(void);
-extern usec_t now_monotonic_usec(void);
-
-extern int now_boottime_timeval(struct timeval *tv);
-extern time_t now_boottime_sec(void);
-extern usec_t now_boottime_usec(void);
-
-
-extern usec_t timeval_usec(struct timeval *ts);
-extern msec_t timeval_msec(struct timeval *tv);
-
-extern usec_t dt_usec(struct timeval *now, struct timeval *old);
-extern susec_t dt_usec_signed(struct timeval *now, struct timeval *old);
-
-extern void heartbeat_init(heartbeat_t *hb);
-
-/* Sleeps until next multiple of tick using monotonic clock.
- * Returns elapsed time in microseconds since previous heartbeat
- */
-extern usec_t heartbeat_next(heartbeat_t *hb, usec_t tick);
-
-/* Returns elapsed time in microseconds since last heartbeat */
-extern usec_t heartbeat_dt_usec(heartbeat_t *hb);
-
-#endif /* NETDATA_CLOCKS_H */
diff --git a/src/common.c b/src/common.c
deleted file mode 100644
index 94fd5e429..000000000
--- a/src/common.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-#include "common.h"
-
-#ifdef __APPLE__
-#define INHERIT_NONE 0
-#endif /* __APPLE__ */
-#if defined(__FreeBSD__) || defined(__APPLE__)
-# define O_NOATIME 0
-# define MADV_DONTFORK INHERIT_NONE
-#endif /* __FreeBSD__ || __APPLE__*/
-
-char *netdata_configured_hostname = NULL;
-char *netdata_configured_config_dir = NULL;
-char *netdata_configured_log_dir = NULL;
-char *netdata_configured_plugins_dir = NULL;
-char *netdata_configured_web_dir = NULL;
-char *netdata_configured_cache_dir = NULL;
-char *netdata_configured_varlib_dir = NULL;
-char *netdata_configured_home_dir = NULL;
-char *netdata_configured_host_prefix = NULL;
-char *netdata_configured_timezone = NULL;
-
-struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 };
-int enable_ksm = 1;
-
-volatile sig_atomic_t netdata_exit = 0;
-const char *os_type = NETDATA_OS_TYPE;
-const char *program_version = VERSION;
-
-// ----------------------------------------------------------------------------
-// memory allocation functions that handle failures
-
-// although netdata does not use memory allocations too often (netdata tries to
-// maintain its memory footprint stable during runtime, i.e. all buffers are
-// allocated during initialization and are adapted to current use throughout
-// its lifetime), these can be used to override the default system allocation
-// routines.
-
-#ifdef NETDATA_LOG_ALLOCATIONS
-static struct memory_statistics {
- volatile size_t malloc_calls_made;
- volatile size_t calloc_calls_made;
- volatile size_t realloc_calls_made;
- volatile size_t strdup_calls_made;
- volatile size_t free_calls_made;
- volatile size_t memory_calls_made;
- volatile size_t allocated_memory;
- volatile size_t mmapped_memory;
-} memory_statistics;
-
-static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
- static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- //if(unlikely(!(memory_statistics.memory_calls_made % 5))) {
- fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n",
- line, file, function,
- (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
- (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
- memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
- memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
- memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
- memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
- memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
- );
-
- memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
- //}
-}
-
-static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
- // this is for debugging - we don't care locking it
- memory_statistics.memory_calls_made++;
- memory_statistics.malloc_calls_made++;
- memory_statistics.allocated_memory += size;
-#endif
- print_allocations(file, function, line);
-}
-
-static inline void mmap_accounting(size_t size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST);
-#else
- // this is for debugging - we don't care locking it
- memory_statistics.memory_calls_made++;
- memory_statistics.mmapped_memory += size;
-#endif
-}
-
-static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
- // this is for debugging - we don't care locking it
- memory_statistics.memory_calls_made++;
- memory_statistics.calloc_calls_made++;
- memory_statistics.allocated_memory += size;
-#endif
- print_allocations(file, function, line);
-}
-
-static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
- (void)ptr;
-
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
- // this is for debugging - we don't care locking it
- memory_statistics.memory_calls_made++;
- memory_statistics.realloc_calls_made++;
- memory_statistics.allocated_memory += size;
-#endif
- print_allocations(file, function, line);
-}
-
-static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
- size_t size = strlen(s) + 1;
-
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
-#else
- // this is for debugging - we don't care locking it
- memory_statistics.memory_calls_made++;
- memory_statistics.strdup_calls_made++;
- memory_statistics.allocated_memory += size;
-#endif
- print_allocations(file, function, line);
-}
-
-static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) {
- (void)file;
- (void)function;
- (void)line;
-
- if(likely(ptr)) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST);
-#else
- // this is for debugging - we don't care locking it
- memory_statistics.memory_calls_made++;
- memory_statistics.free_calls_made++;
-#endif
- }
-}
-#endif
-
-#ifdef NETDATA_LOG_ALLOCATIONS
-char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
- strdup_accounting(file, function, line, s);
-#else
-char *strdupz(const char *s) {
-#endif
-
- char *t = strdup(s);
- if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
- return t;
-}
-
-#ifdef NETDATA_LOG_ALLOCATIONS
-void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
- malloc_accounting(file, function, line, size);
-#else
-void *mallocz(size_t size) {
-#endif
-
- void *p = malloc(size);
- if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
- return p;
-}
-
-#ifdef NETDATA_LOG_ALLOCATIONS
-void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
- calloc_accounting(file, function, line, nmemb * size);
-#else
-void *callocz(size_t nmemb, size_t size) {
-#endif
-
- void *p = calloc(nmemb, size);
- if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
- return p;
-}
-
-#ifdef NETDATA_LOG_ALLOCATIONS
-void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
- realloc_accounting(file, function, line, ptr, size);
-#else
-void *reallocz(void *ptr, size_t size) {
-#endif
-
- void *p = realloc(ptr, size);
- if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
- return p;
-}
-
-#ifdef NETDATA_LOG_ALLOCATIONS
-void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
- free_accounting(file, function, line, ptr);
-#else
-void freez(void *ptr) {
-#endif
-
- free(ptr);
-}
-
-void json_escape_string(char *dst, const char *src, size_t size) {
- const char *t;
- char *d = dst, *e = &dst[size - 1];
-
- for(t = src; *t && d < e ;t++) {
- if(unlikely(*t == '\\' || *t == '"')) {
- if(unlikely(d + 1 >= e)) break;
- *d++ = '\\';
- }
- *d++ = *t;
- }
-
- *d = '\0';
-}
-
-void json_fix_string(char *s) {
- unsigned char c;
- while((c = (unsigned char)*s)) {
- if(unlikely(c == '\\'))
- *s++ = '/';
- else if(unlikely(c == '"'))
- *s++ = '\'';
- else if(unlikely(isspace(c) || iscntrl(c)))
- *s++ = ' ';
- else if(unlikely(!isprint(c) || c > 127))
- *s++ = '_';
- else
- s++;
- }
-}
-
-int sleep_usec(usec_t usec) {
-
-#ifndef NETDATA_WITH_USLEEP
- // we expect microseconds (1.000.000 per second)
- // but timespec is nanoseconds (1.000.000.000 per second)
- struct timespec rem, req = {
- .tv_sec = (time_t) (usec / 1000000),
- .tv_nsec = (suseconds_t) ((usec % 1000000) * 1000)
- };
-
- while (nanosleep(&req, &rem) == -1) {
- if (likely(errno == EINTR)) {
- debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
- req.tv_sec = rem.tv_sec;
- req.tv_nsec = rem.tv_nsec;
- } else {
- error("Cannot nanosleep() for %llu microseconds.", usec);
- break;
- }
- }
-
- return 0;
-#else
- int ret = usleep(usec);
- if(unlikely(ret == -1 && errno == EINVAL)) {
- // on certain systems, usec has to be up to 999999
- if(usec > 999999) {
- int counter = usec / 999999;
- while(counter--)
- usleep(999999);
-
- usleep(usec % 999999);
- }
- else {
- error("Cannot usleep() for %llu microseconds.", usec);
- return ret;
- }
- }
-
- if(ret != 0)
- error("usleep() failed for %llu microseconds.", usec);
-
- return ret;
-#endif
-}
-
-unsigned char netdata_map_chart_names[256] = {
- [0] = '\0', //
- [1] = '_', //
- [2] = '_', //
- [3] = '_', //
- [4] = '_', //
- [5] = '_', //
- [6] = '_', //
- [7] = '_', //
- [8] = '_', //
- [9] = '_', //
- [10] = '_', //
- [11] = '_', //
- [12] = '_', //
- [13] = '_', //
- [14] = '_', //
- [15] = '_', //
- [16] = '_', //
- [17] = '_', //
- [18] = '_', //
- [19] = '_', //
- [20] = '_', //
- [21] = '_', //
- [22] = '_', //
- [23] = '_', //
- [24] = '_', //
- [25] = '_', //
- [26] = '_', //
- [27] = '_', //
- [28] = '_', //
- [29] = '_', //
- [30] = '_', //
- [31] = '_', //
- [32] = '_', //
- [33] = '_', // !
- [34] = '_', // "
- [35] = '_', // #
- [36] = '_', // $
- [37] = '_', // %
- [38] = '_', // &
- [39] = '_', // '
- [40] = '_', // (
- [41] = '_', // )
- [42] = '_', // *
- [43] = '_', // +
- [44] = '.', // ,
- [45] = '-', // -
- [46] = '.', // .
- [47] = '/', // /
- [48] = '0', // 0
- [49] = '1', // 1
- [50] = '2', // 2
- [51] = '3', // 3
- [52] = '4', // 4
- [53] = '5', // 5
- [54] = '6', // 6
- [55] = '7', // 7
- [56] = '8', // 8
- [57] = '9', // 9
- [58] = '_', // :
- [59] = '_', // ;
- [60] = '_', // <
- [61] = '_', // =
- [62] = '_', // >
- [63] = '_', // ?
- [64] = '_', // @
- [65] = 'a', // A
- [66] = 'b', // B
- [67] = 'c', // C
- [68] = 'd', // D
- [69] = 'e', // E
- [70] = 'f', // F
- [71] = 'g', // G
- [72] = 'h', // H
- [73] = 'i', // I
- [74] = 'j', // J
- [75] = 'k', // K
- [76] = 'l', // L
- [77] = 'm', // M
- [78] = 'n', // N
- [79] = 'o', // O
- [80] = 'p', // P
- [81] = 'q', // Q
- [82] = 'r', // R
- [83] = 's', // S
- [84] = 't', // T
- [85] = 'u', // U
- [86] = 'v', // V
- [87] = 'w', // W
- [88] = 'x', // X
- [89] = 'y', // Y
- [90] = 'z', // Z
- [91] = '_', // [
- [92] = '/', // backslash
- [93] = '_', // ]
- [94] = '_', // ^
- [95] = '_', // _
- [96] = '_', // `
- [97] = 'a', // a
- [98] = 'b', // b
- [99] = 'c', // c
- [100] = 'd', // d
- [101] = 'e', // e
- [102] = 'f', // f
- [103] = 'g', // g
- [104] = 'h', // h
- [105] = 'i', // i
- [106] = 'j', // j
- [107] = 'k', // k
- [108] = 'l', // l
- [109] = 'm', // m
- [110] = 'n', // n
- [111] = 'o', // o
- [112] = 'p', // p
- [113] = 'q', // q
- [114] = 'r', // r
- [115] = 's', // s
- [116] = 't', // t
- [117] = 'u', // u
- [118] = 'v', // v
- [119] = 'w', // w
- [120] = 'x', // x
- [121] = 'y', // y
- [122] = 'z', // z
- [123] = '_', // {
- [124] = '_', // |
- [125] = '_', // }
- [126] = '_', // ~
- [127] = '_', //
- [128] = '_', //
- [129] = '_', //
- [130] = '_', //
- [131] = '_', //
- [132] = '_', //
- [133] = '_', //
- [134] = '_', //
- [135] = '_', //
- [136] = '_', //
- [137] = '_', //
- [138] = '_', //
- [139] = '_', //
- [140] = '_', //
- [141] = '_', //
- [142] = '_', //
- [143] = '_', //
- [144] = '_', //
- [145] = '_', //
- [146] = '_', //
- [147] = '_', //
- [148] = '_', //
- [149] = '_', //
- [150] = '_', //
- [151] = '_', //
- [152] = '_', //
- [153] = '_', //
- [154] = '_', //
- [155] = '_', //
- [156] = '_', //
- [157] = '_', //
- [158] = '_', //
- [159] = '_', //
- [160] = '_', //
- [161] = '_', //
- [162] = '_', //
- [163] = '_', //
- [164] = '_', //
- [165] = '_', //
- [166] = '_', //
- [167] = '_', //
- [168] = '_', //
- [169] = '_', //
- [170] = '_', //
- [171] = '_', //
- [172] = '_', //
- [173] = '_', //
- [174] = '_', //
- [175] = '_', //
- [176] = '_', //
- [177] = '_', //
- [178] = '_', //
- [179] = '_', //
- [180] = '_', //
- [181] = '_', //
- [182] = '_', //
- [183] = '_', //
- [184] = '_', //
- [185] = '_', //
- [186] = '_', //
- [187] = '_', //
- [188] = '_', //
- [189] = '_', //
- [190] = '_', //
- [191] = '_', //
- [192] = '_', //
- [193] = '_', //
- [194] = '_', //
- [195] = '_', //
- [196] = '_', //
- [197] = '_', //
- [198] = '_', //
- [199] = '_', //
- [200] = '_', //
- [201] = '_', //
- [202] = '_', //
- [203] = '_', //
- [204] = '_', //
- [205] = '_', //
- [206] = '_', //
- [207] = '_', //
- [208] = '_', //
- [209] = '_', //
- [210] = '_', //
- [211] = '_', //
- [212] = '_', //
- [213] = '_', //
- [214] = '_', //
- [215] = '_', //
- [216] = '_', //
- [217] = '_', //
- [218] = '_', //
- [219] = '_', //
- [220] = '_', //
- [221] = '_', //
- [222] = '_', //
- [223] = '_', //
- [224] = '_', //
- [225] = '_', //
- [226] = '_', //
- [227] = '_', //
- [228] = '_', //
- [229] = '_', //
- [230] = '_', //
- [231] = '_', //
- [232] = '_', //
- [233] = '_', //
- [234] = '_', //
- [235] = '_', //
- [236] = '_', //
- [237] = '_', //
- [238] = '_', //
- [239] = '_', //
- [240] = '_', //
- [241] = '_', //
- [242] = '_', //
- [243] = '_', //
- [244] = '_', //
- [245] = '_', //
- [246] = '_', //
- [247] = '_', //
- [248] = '_', //
- [249] = '_', //
- [250] = '_', //
- [251] = '_', //
- [252] = '_', //
- [253] = '_', //
- [254] = '_', //
- [255] = '_' //
-};
-
-// make sure the supplied string
-// is good for a netdata chart/dimension ID/NAME
-void netdata_fix_chart_name(char *s) {
- while ((*s = netdata_map_chart_names[(unsigned char) *s])) s++;
-}
-
-unsigned char netdata_map_chart_ids[256] = {
- [0] = '\0', //
- [1] = '_', //
- [2] = '_', //
- [3] = '_', //
- [4] = '_', //
- [5] = '_', //
- [6] = '_', //
- [7] = '_', //
- [8] = '_', //
- [9] = '_', //
- [10] = '_', //
- [11] = '_', //
- [12] = '_', //
- [13] = '_', //
- [14] = '_', //
- [15] = '_', //
- [16] = '_', //
- [17] = '_', //
- [18] = '_', //
- [19] = '_', //
- [20] = '_', //
- [21] = '_', //
- [22] = '_', //
- [23] = '_', //
- [24] = '_', //
- [25] = '_', //
- [26] = '_', //
- [27] = '_', //
- [28] = '_', //
- [29] = '_', //
- [30] = '_', //
- [31] = '_', //
- [32] = '_', //
- [33] = '_', // !
- [34] = '_', // "
- [35] = '_', // #
- [36] = '_', // $
- [37] = '_', // %
- [38] = '_', // &
- [39] = '_', // '
- [40] = '_', // (
- [41] = '_', // )
- [42] = '_', // *
- [43] = '_', // +
- [44] = '.', // ,
- [45] = '-', // -
- [46] = '.', // .
- [47] = '_', // /
- [48] = '0', // 0
- [49] = '1', // 1
- [50] = '2', // 2
- [51] = '3', // 3
- [52] = '4', // 4
- [53] = '5', // 5
- [54] = '6', // 6
- [55] = '7', // 7
- [56] = '8', // 8
- [57] = '9', // 9
- [58] = '_', // :
- [59] = '_', // ;
- [60] = '_', // <
- [61] = '_', // =
- [62] = '_', // >
- [63] = '_', // ?
- [64] = '_', // @
- [65] = 'a', // A
- [66] = 'b', // B
- [67] = 'c', // C
- [68] = 'd', // D
- [69] = 'e', // E
- [70] = 'f', // F
- [71] = 'g', // G
- [72] = 'h', // H
- [73] = 'i', // I
- [74] = 'j', // J
- [75] = 'k', // K
- [76] = 'l', // L
- [77] = 'm', // M
- [78] = 'n', // N
- [79] = 'o', // O
- [80] = 'p', // P
- [81] = 'q', // Q
- [82] = 'r', // R
- [83] = 's', // S
- [84] = 't', // T
- [85] = 'u', // U
- [86] = 'v', // V
- [87] = 'w', // W
- [88] = 'x', // X
- [89] = 'y', // Y
- [90] = 'z', // Z
- [91] = '_', // [
- [92] = '/', // backslash
- [93] = '_', // ]
- [94] = '_', // ^
- [95] = '_', // _
- [96] = '_', // `
- [97] = 'a', // a
- [98] = 'b', // b
- [99] = 'c', // c
- [100] = 'd', // d
- [101] = 'e', // e
- [102] = 'f', // f
- [103] = 'g', // g
- [104] = 'h', // h
- [105] = 'i', // i
- [106] = 'j', // j
- [107] = 'k', // k
- [108] = 'l', // l
- [109] = 'm', // m
- [110] = 'n', // n
- [111] = 'o', // o
- [112] = 'p', // p
- [113] = 'q', // q
- [114] = 'r', // r
- [115] = 's', // s
- [116] = 't', // t
- [117] = 'u', // u
- [118] = 'v', // v
- [119] = 'w', // w
- [120] = 'x', // x
- [121] = 'y', // y
- [122] = 'z', // z
- [123] = '_', // {
- [124] = '_', // |
- [125] = '_', // }
- [126] = '_', // ~
- [127] = '_', //
- [128] = '_', //
- [129] = '_', //
- [130] = '_', //
- [131] = '_', //
- [132] = '_', //
- [133] = '_', //
- [134] = '_', //
- [135] = '_', //
- [136] = '_', //
- [137] = '_', //
- [138] = '_', //
- [139] = '_', //
- [140] = '_', //
- [141] = '_', //
- [142] = '_', //
- [143] = '_', //
- [144] = '_', //
- [145] = '_', //
- [146] = '_', //
- [147] = '_', //
- [148] = '_', //
- [149] = '_', //
- [150] = '_', //
- [151] = '_', //
- [152] = '_', //
- [153] = '_', //
- [154] = '_', //
- [155] = '_', //
- [156] = '_', //
- [157] = '_', //
- [158] = '_', //
- [159] = '_', //
- [160] = '_', //
- [161] = '_', //
- [162] = '_', //
- [163] = '_', //
- [164] = '_', //
- [165] = '_', //
- [166] = '_', //
- [167] = '_', //
- [168] = '_', //
- [169] = '_', //
- [170] = '_', //
- [171] = '_', //
- [172] = '_', //
- [173] = '_', //
- [174] = '_', //
- [175] = '_', //
- [176] = '_', //
- [177] = '_', //
- [178] = '_', //
- [179] = '_', //
- [180] = '_', //
- [181] = '_', //
- [182] = '_', //
- [183] = '_', //
- [184] = '_', //
- [185] = '_', //
- [186] = '_', //
- [187] = '_', //
- [188] = '_', //
- [189] = '_', //
- [190] = '_', //
- [191] = '_', //
- [192] = '_', //
- [193] = '_', //
- [194] = '_', //
- [195] = '_', //
- [196] = '_', //
- [197] = '_', //
- [198] = '_', //
- [199] = '_', //
- [200] = '_', //
- [201] = '_', //
- [202] = '_', //
- [203] = '_', //
- [204] = '_', //
- [205] = '_', //
- [206] = '_', //
- [207] = '_', //
- [208] = '_', //
- [209] = '_', //
- [210] = '_', //
- [211] = '_', //
- [212] = '_', //
- [213] = '_', //
- [214] = '_', //
- [215] = '_', //
- [216] = '_', //
- [217] = '_', //
- [218] = '_', //
- [219] = '_', //
- [220] = '_', //
- [221] = '_', //
- [222] = '_', //
- [223] = '_', //
- [224] = '_', //
- [225] = '_', //
- [226] = '_', //
- [227] = '_', //
- [228] = '_', //
- [229] = '_', //
- [230] = '_', //
- [231] = '_', //
- [232] = '_', //
- [233] = '_', //
- [234] = '_', //
- [235] = '_', //
- [236] = '_', //
- [237] = '_', //
- [238] = '_', //
- [239] = '_', //
- [240] = '_', //
- [241] = '_', //
- [242] = '_', //
- [243] = '_', //
- [244] = '_', //
- [245] = '_', //
- [246] = '_', //
- [247] = '_', //
- [248] = '_', //
- [249] = '_', //
- [250] = '_', //
- [251] = '_', //
- [252] = '_', //
- [253] = '_', //
- [254] = '_', //
- [255] = '_' //
-};
-
-// make sure the supplied string
-// is good for a netdata chart/dimension ID/NAME
-void netdata_fix_chart_id(char *s) {
- while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
-}
-
-/*
-// http://stackoverflow.com/questions/7666509/hash-function-for-string
-uint32_t simple_hash(const char *name)
-{
- const char *s = name;
- uint32_t hash = 5381;
- int i;
-
- while((i = *s++)) hash = ((hash << 5) + hash) + i;
-
- // fprintf(stderr, "HASH: %lu %s\n", hash, name);
-
- return hash;
-}
-*/
-
-/*
-// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
-uint32_t simple_hash(const char *name) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5;
-
- // FNV-1a algorithm
- while (*s) {
- // multiply by the 32 bit FNV magic prime mod 2^32
- // NOTE: No need to optimize with left shifts.
- // GCC will use imul instruction anyway.
- // Tested with 'gcc -O3 -S'
- //hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
- hval *= 16777619;
-
- // xor the bottom with the current octet
- hval ^= (uint32_t) *s++;
- }
-
- // fprintf(stderr, "HASH: %u = %s\n", hval, name);
- return hval;
-}
-
-uint32_t simple_uhash(const char *name) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5, c;
-
- // FNV-1a algorithm
- while ((c = *s++)) {
- if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
- hval *= 16777619;
- hval ^= c;
- }
- return hval;
-}
-*/
-
-/*
-// http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
-// one at a time hash
-uint32_t simple_hash(const char *name) {
- unsigned char *s = (unsigned char *)name;
- uint32_t h = 0;
-
- while(*s) {
- h += *s++;
- h += (h << 10);
- h ^= (h >> 6);
- }
-
- h += (h << 3);
- h ^= (h >> 11);
- h += (h << 15);
-
- // fprintf(stderr, "HASH: %u = %s\n", h, name);
-
- return h;
-}
-*/
-
-void strreverse(char *begin, char *end) {
- while (end > begin) {
- // clearer code.
- char aux = *end;
- *end-- = *begin;
- *begin++ = aux;
- }
-}
-
-char *strsep_on_1char(char **ptr, char c) {
- if(unlikely(!ptr || !*ptr))
- return NULL;
-
- // remember the position we started
- char *s = *ptr;
-
- // skip separators in front
- while(*s == c) s++;
- char *ret = s;
-
- // find the next separator
- while(*s++) {
- if(unlikely(*s == c)) {
- *s++ = '\0';
- *ptr = s;
- return ret;
- }
- }
-
- *ptr = NULL;
- return ret;
-}
-
-char *mystrsep(char **ptr, char *s) {
- char *p = "";
- while (p && !p[0] && *ptr) p = strsep(ptr, s);
- return (p);
-}
-
-char *trim(char *s) {
- // skip leading spaces
- while (*s && isspace(*s)) s++;
- if (!*s) return NULL;
-
- // skip tailing spaces
- // this way is way faster. Writes only one NUL char.
- ssize_t l = strlen(s);
- if (--l >= 0) {
- char *p = s + l;
- while (p > s && isspace(*p)) p--;
- *++p = '\0';
- }
-
- if (!*s) return NULL;
-
- return s;
-}
-
-inline char *trim_all(char *buffer) {
- char *d = buffer, *s = buffer;
-
- // skip spaces
- while(isspace(*s)) s++;
-
- while(*s) {
- // copy the non-space part
- while(*s && !isspace(*s)) *d++ = *s++;
-
- // add a space if we have to
- if(*s && isspace(*s)) {
- *d++ = ' ';
- s++;
- }
-
- // skip spaces
- while(isspace(*s)) s++;
- }
-
- *d = '\0';
-
- if(d > buffer) {
- d--;
- if(isspace(*d)) *d = '\0';
- }
-
- if(!buffer[0]) return NULL;
- return buffer;
-}
-
-static int memory_file_open(const char *filename, size_t size) {
- // info("memory_file_open('%s', %zu", filename, size);
-
- int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
- if (fd != -1) {
- if (lseek(fd, size, SEEK_SET) == (off_t) size) {
- if (write(fd, "", 1) == 1) {
- if (ftruncate(fd, size))
- error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
- }
- else error("Cannot write to file '%s' at position %zu.", filename, size);
- }
- else error("Cannot seek file '%s' to size %zu.", filename, size);
- }
- else error("Cannot create/open file '%s'.", filename);
-
- return fd;
-}
-
-// mmap_shared is used for memory mode = map
-static void *memory_file_mmap(const char *filename, size_t size, int flags) {
- // info("memory_file_mmap('%s', %zu", filename, size);
- static int log_madvise = 1;
-
- int fd = -1;
- if(filename) {
- fd = memory_file_open(filename, size);
- if(fd == -1) return MAP_FAILED;
- }
-
- void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
- if (mem != MAP_FAILED) {
-#ifdef NETDATA_LOG_ALLOCATIONS
- mmap_accounting(size);
-#endif
- int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
- if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
-
- if (madvise(mem, size, advise) != 0 && log_madvise) {
- error("Cannot advise the kernel about shared memory usage.");
- log_madvise--;
- }
- }
-
- if(fd != -1)
- close(fd);
-
- return mem;
-}
-
-#ifdef MADV_MERGEABLE
-static void *memory_file_mmap_ksm(const char *filename, size_t size, int flags) {
- // info("memory_file_mmap_ksm('%s', %zu", filename, size);
- static int log_madvise_2 = 1, log_madvise_3 = 1;
-
- int fd = -1;
- if(filename) {
- fd = memory_file_open(filename, size);
- if(fd == -1) return MAP_FAILED;
- }
-
- void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
- if (mem != MAP_FAILED) {
-#ifdef NETDATA_LOG_ALLOCATIONS
- mmap_accounting(size);
-#endif
- if(fd != -1) {
- if (lseek(fd, 0, SEEK_SET) == 0) {
- if (read(fd, mem, size) != (ssize_t) size)
- error("Cannot read from file '%s'", filename);
- }
- else error("Cannot seek to beginning of file '%s'.", filename);
- }
-
- // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
- if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
- error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.", filename);
- log_madvise_2--;
- }
-
- if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
- error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.", filename);
- log_madvise_3--;
- }
- }
-
- if(fd != -1)
- close(fd);
-
- return mem;
-}
-#else
-static void *memory_file_mmap_ksm(const char *filename, size_t size, int flags) {
- // info("memory_file_mmap_ksm FALLBACK ('%s', %zu", filename, size);
-
- if(filename)
- return memory_file_mmap(filename, size, flags);
-
- // when KSM is not available and no filename is given (memory mode = ram),
- // we just report failure
- return MAP_FAILED;
-}
-#endif
-
-void *mymmap(const char *filename, size_t size, int flags, int ksm) {
- void *mem = NULL;
-
- if (filename && (flags & MAP_SHARED || !enable_ksm || !ksm))
- // memory mode = map | save
- // when KSM is not enabled
- // MAP_SHARED is used for memory mode = map (no KSM possible)
- mem = memory_file_mmap(filename, size, flags);
-
- else
- // memory mode = save | ram
- // when KSM is enabled
- // for memory mode = ram, the filename is NULL
- mem = memory_file_mmap_ksm(filename, size, flags);
-
- if(mem == MAP_FAILED) return NULL;
-
- errno = 0;
- return mem;
-}
-
-int memory_file_save(const char *filename, void *mem, size_t size) {
- char tmpfilename[FILENAME_MAX + 1];
-
- snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
-
- int fd = open(tmpfilename, O_RDWR | O_CREAT | O_NOATIME, 0664);
- if (fd < 0) {
- error("Cannot create/open file '%s'.", filename);
- return -1;
- }
-
- if (write(fd, mem, size) != (ssize_t) size) {
- error("Cannot write to file '%s' %ld bytes.", filename, (long) size);
- close(fd);
- return -1;
- }
-
- close(fd);
-
- if (rename(tmpfilename, filename)) {
- error("Cannot rename '%s' to '%s'", tmpfilename, filename);
- return -1;
- }
-
- return 0;
-}
-
-int fd_is_valid(int fd) {
- return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
-}
-
-char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
- char *s = fgets(buf, (int)buf_size, fp);
- if (!s) return NULL;
-
- char *t = s;
- if (*t != '\0') {
- // find the string end
- while (*++t != '\0');
-
- // trim trailing spaces/newlines/tabs
- while (--t > s && *t == '\n')
- *t = '\0';
- }
-
- if (len)
- *len = t - s + 1;
-
- return s;
-}
-
-int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
- int size = vsnprintf(dst, n, fmt, args);
-
- if (unlikely((size_t) size > n)) {
- // truncated
- size = (int)n;
- }
-
- dst[size] = '\0';
- return size;
-}
-
-int snprintfz(char *dst, size_t n, const char *fmt, ...) {
- va_list args;
-
- va_start(args, fmt);
- int ret = vsnprintfz(dst, n, fmt, args);
- va_end(args);
-
- return ret;
-}
-
-// ----------------------------------------------------------------------------
-// system functions
-// to retrieve settings of the system
-
-int processors = 1;
-long get_system_cpus(void) {
- processors = 1;
-
- #ifdef __APPLE__
- int32_t tmp_processors;
-
- if (unlikely(GETSYSCTL_BY_NAME("hw.logicalcpu", tmp_processors))) {
- error("Assuming system has %d processors.", processors);
- } else {
- processors = tmp_processors;
- }
-
- return processors;
- #elif __FreeBSD__
- int32_t tmp_processors;
-
- if (unlikely(GETSYSCTL_BY_NAME("hw.ncpu", tmp_processors))) {
- error("Assuming system has %d processors.", processors);
- } else {
- processors = tmp_processors;
- }
-
- return processors;
- #else
-
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix);
-
- procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
- if(!ff) {
- error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
- return processors;
- }
-
- ff = procfile_readall(ff);
- if(!ff) {
- error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
- return processors;
- }
-
- processors = 0;
- unsigned int i;
- for(i = 0; i < procfile_lines(ff); i++) {
- if(!procfile_linewords(ff, i)) continue;
-
- if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++;
- }
- processors--;
- if(processors < 1) processors = 1;
-
- procfile_close(ff);
-
- debug(D_SYSTEM, "System has %d processors.", processors);
- return processors;
-
- #endif /* __APPLE__, __FreeBSD__ */
-}
-
-pid_t pid_max = 32768;
-pid_t get_system_pid_max(void) {
- #ifdef __APPLE__
- // As we currently do not know a solution to query pid_max from the os
- // we use the number defined in bsd/sys/proc_internal.h in XNU sources
- pid_max = 99999;
- return pid_max;
- #elif __FreeBSD__
- int32_t tmp_pid_max;
-
- if (unlikely(GETSYSCTL_BY_NAME("kern.pid_max", tmp_pid_max))) {
- pid_max = 99999;
- error("Assuming system's maximum pid is %d.", pid_max);
- } else {
- pid_max = tmp_pid_max;
- }
-
- return pid_max;
- #else
-
- static char read = 0;
- if(unlikely(read)) return pid_max;
- read = 1;
-
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", netdata_configured_host_prefix);
-
- unsigned long long max = 0;
- if(read_single_number_file(filename, &max) != 0) {
- error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
- return pid_max;
- }
-
- if(!max) {
- error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max);
- return pid_max;
- }
-
- pid_max = (pid_t) max;
- return pid_max;
-
- #endif /* __APPLE__, __FreeBSD__ */
-}
-
-unsigned int hz;
-void get_system_HZ(void) {
- long ticks;
-
- if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
- error("Cannot get system clock ticks");
- }
-
- hz = (unsigned int) ticks;
-}
-
-/*
-// poor man cycle counting
-static unsigned long tsc;
-void begin_tsc(void) {
- unsigned long a, d;
- asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
- tsc = ((unsigned long)d << 32) | (unsigned long)a;
-}
-unsigned long end_tsc(void) {
- unsigned long a, d;
- asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
- return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
-}
-*/
-
-int recursively_delete_dir(const char *path, const char *reason) {
- DIR *dir = opendir(path);
- if(!dir) {
- error("Cannot read %s directory to be deleted '%s'", reason?reason:"", path);
- return -1;
- }
-
- int ret = 0;
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type == DT_DIR
- && (
- (de->d_name[0] == '.' && de->d_name[1] == '\0')
- || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- ))
- continue;
-
- char fullpath[FILENAME_MAX + 1];
- snprintfz(fullpath, FILENAME_MAX, "%s/%s", path, de->d_name);
-
- if(de->d_type == DT_DIR) {
- int r = recursively_delete_dir(fullpath, reason);
- if(r > 0) ret += r;
- continue;
- }
-
- info("Deleting %s file '%s'", reason?reason:"", fullpath);
- if(unlikely(unlink(fullpath) == -1))
- error("Cannot delete %s file '%s'", reason?reason:"", fullpath);
- else
- ret++;
- }
-
- info("Deleting empty directory '%s'", path);
- if(unlikely(rmdir(path) == -1))
- error("Cannot delete empty directory '%s'", path);
- else
- ret++;
-
- closedir(dir);
-
- return ret;
-}
diff --git a/src/common.h b/src/common.h
deleted file mode 100644
index 15fc50a6a..000000000
--- a/src/common.h
+++ /dev/null
@@ -1,360 +0,0 @@
-#ifndef NETDATA_COMMON_H
-#define NETDATA_COMMON_H 1
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-// ----------------------------------------------------------------------------
-// system include files for all netdata C programs
-
-/* select the memory allocator, based on autoconf findings */
-#if defined(ENABLE_JEMALLOC)
-
-#if defined(HAVE_JEMALLOC_JEMALLOC_H)
-#include <jemalloc/jemalloc.h>
-#else
-#include <malloc.h>
-#endif
-
-#elif defined(ENABLE_TCMALLOC)
-
-#include <google/tcmalloc.h>
-
-#else /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
-
-#if !(defined(__FreeBSD__) || defined(__APPLE__))
-#include <malloc.h>
-#endif /* __FreeBSD__ || __APPLE__ */
-
-#endif
-
-#include <pthread.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <ctype.h>
-#include <string.h>
-#include <strings.h>
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
-#include <sys/ioctl.h>
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_RESOLV_H
-#include <resolv.h>
-#endif
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <grp.h>
-#include <pwd.h>
-#include <locale.h>
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#include <net/if.h>
-
-#include <poll.h>
-#include <signal.h>
-#include <syslog.h>
-#include <sys/mman.h>
-
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/un.h>
-#include <time.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-
-// #1408
-#ifdef MAJOR_IN_MKDEV
-#include <sys/mkdev.h>
-#endif
-#ifdef MAJOR_IN_SYSMACROS
-#include <sys/sysmacros.h>
-#endif
-
-/*
-#include <mntent.h>
-*/
-
-#ifdef STORAGE_WITH_MATH
-#include <math.h>
-#include <float.h>
-#endif
-
-#if defined(HAVE_INTTYPES_H)
-#include <inttypes.h>
-#elif defined(HAVE_STDINT_H)
-#include <stdint.h>
-#endif
-
-#ifdef NETDATA_WITH_ZLIB
-#include <zlib.h>
-#endif
-
-#ifdef HAVE_CAPABILITY
-#include <sys/capability.h>
-#endif
-
-// ----------------------------------------------------------------------------
-// netdata chart priorities
-
-// This is a work in progress - to scope is to collect here all chart priorities.
-// These should be based on the CONTEXT of the charts + the chart id when needed
-// - for each SECTION +1000 (or +X000 for big sections)
-// - for each FAMILY +100
-// - for each CHART +10
-
-// Memory Section - 1xxx
-#define NETDATA_CHART_PRIO_MEM_SYSTEM 1000
-#define NETDATA_CHART_PRIO_MEM_SYSTEM_AVAILABLE 1010
-#define NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED 1020
-#define NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS 1030
-#define NETDATA_CHART_PRIO_MEM_KERNEL 1100
-#define NETDATA_CHART_PRIO_MEM_SLAB 1200
-#define NETDATA_CHART_PRIO_MEM_HUGEPAGES 1250
-#define NETDATA_CHART_PRIO_MEM_KSM 1300
-#define NETDATA_CHART_PRIO_MEM_NUMA 1400
-#define NETDATA_CHART_PRIO_MEM_HW 1500
-
-
-// ----------------------------------------------------------------------------
-// netdata common definitions
-
-#if (SIZEOF_VOID_P == 8)
-#define ENVIRONMENT64
-#elif (SIZEOF_VOID_P == 4)
-#define ENVIRONMENT32
-#else
-#error "Cannot detect if this is a 32 or 64 bit CPU"
-#endif
-
-#ifdef __GNUC__
-#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-#endif // __GNUC__
-
-#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
-#define NEVERNULL __attribute__((returns_nonnull))
-#else
-#define NEVERNULL
-#endif
-
-#ifdef HAVE_FUNC_ATTRIBUTE_NOINLINE
-#define NOINLINE __attribute__((noinline))
-#else
-#define NOINLINE
-#endif
-
-#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
-#define MALLOCLIKE __attribute__((malloc))
-#else
-#define MALLOCLIKE
-#endif
-
-#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT
-#define PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a)))
-#else
-#define PRINTFLIKE(f, a)
-#endif
-
-#ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
-#define NORETURN __attribute__ ((noreturn))
-#else
-#define NORETURN
-#endif
-
-#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
-#define WARNUNUSED __attribute__ ((warn_unused_result))
-#else
-#define WARNUNUSED
-#endif
-
-#ifdef abs
-#undef abs
-#endif
-#define abs(x) (((x) < 0)? (-(x)) : (x))
-
-#define GUID_LEN 36
-
-// ----------------------------------------------------------------------------
-// netdata include files
-
-#include "clocks.h"
-#include "log.h"
-#include "threads.h"
-#include "locks.h"
-#include "simple_pattern.h"
-#include "avl.h"
-#include "global_statistics.h"
-#include "storage_number.h"
-#include "web_buffer.h"
-#include "web_buffer_svg.h"
-#include "url.h"
-#include "popen.h"
-
-#include "procfile.h"
-#include "appconfig.h"
-#include "dictionary.h"
-#include "proc_self_mountinfo.h"
-#include "plugin_checks.h"
-#include "plugin_idlejitter.h"
-#include "plugin_nfacct.h"
-
-#if defined(__FreeBSD__)
-#include <pthread_np.h>
-#include "plugin_freebsd.h"
-#define NETDATA_OS_TYPE "freebsd"
-#elif defined(__APPLE__)
-#include "plugin_macos.h"
-#define NETDATA_OS_TYPE "macos"
-#else
-#include "plugin_proc.h"
-#include "plugin_proc_diskspace.h"
-#define NETDATA_OS_TYPE "linux"
-#endif /* __FreeBSD__, __APPLE__*/
-
-typedef enum rrdcalc_status {
- RRDCALC_STATUS_REMOVED = -2,
- RRDCALC_STATUS_UNDEFINED = -1,
- RRDCALC_STATUS_UNINITIALIZED = 0,
- RRDCALC_STATUS_CLEAR = 1,
- RRDCALC_STATUS_RAISED = 2,
- RRDCALC_STATUS_WARNING = 3,
- RRDCALC_STATUS_CRITICAL = 4
-} RRDCALC_STATUS;
-
-#include "eval.h"
-#include "health.h"
-
-#include "statistical.h"
-#include "socket.h"
-#include "rrd.h"
-#include "plugin_tc.h"
-#include "plugins_d.h"
-#include "statsd.h"
-#include "rrd2json.h"
-#include "rrd2json_api_old.h"
-#include "web_client.h"
-#include "web_server.h"
-#include "registry.h"
-#include "signals.h"
-#include "daemon.h"
-#include "main.h"
-#include "unit_test.h"
-#include "ipc.h"
-#include "backends.h"
-#include "backend_prometheus.h"
-#include "inlined.h"
-#include "adaptive_resortable_list.h"
-#include "rrdpush.h"
-#include "web_api_v1.h"
-#include "web_api_old.h"
-
-extern char *netdata_configured_hostname;
-extern char *netdata_configured_config_dir;
-extern char *netdata_configured_log_dir;
-extern char *netdata_configured_plugins_dir_base;
-extern char *netdata_configured_plugins_dir;
-extern char *netdata_configured_web_dir;
-extern char *netdata_configured_cache_dir;
-extern char *netdata_configured_varlib_dir;
-extern char *netdata_configured_home_dir;
-extern char *netdata_configured_host_prefix;
-extern char *netdata_configured_timezone;
-
-extern void netdata_fix_chart_id(char *s);
-extern void netdata_fix_chart_name(char *s);
-
-extern void strreverse(char* begin, char* end);
-extern char *mystrsep(char **ptr, char *s);
-extern char *trim(char *s); // remove leading and trailing spaces; may return NULL
-extern char *trim_all(char *buffer); // like trim(), but also remove duplicate spaces inside the string; may return NULL
-
-extern int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args);
-extern int snprintfz(char *dst, size_t n, const char *fmt, ...) PRINTFLIKE(3, 4);
-
-// memory allocation functions that handle failures
-#ifdef NETDATA_LOG_ALLOCATIONS
-#define strdupz(s) strdupz_int(__FILE__, __FUNCTION__, __LINE__, s)
-#define callocz(nmemb, size) callocz_int(__FILE__, __FUNCTION__, __LINE__, nmemb, size)
-#define mallocz(size) mallocz_int(__FILE__, __FUNCTION__, __LINE__, size)
-#define reallocz(ptr, size) reallocz_int(__FILE__, __FUNCTION__, __LINE__, ptr, size)
-#define freez(ptr) freez_int(__FILE__, __FUNCTION__, __LINE__, ptr)
-
-extern char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s);
-extern void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size);
-extern void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size);
-extern void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size);
-extern void freez_int(const char *file, const char *function, const unsigned long line, void *ptr);
-#else
-extern char *strdupz(const char *s) MALLOCLIKE NEVERNULL;
-extern void *callocz(size_t nmemb, size_t size) MALLOCLIKE NEVERNULL;
-extern void *mallocz(size_t size) MALLOCLIKE NEVERNULL;
-extern void *reallocz(void *ptr, size_t size) MALLOCLIKE NEVERNULL;
-extern void freez(void *ptr);
-#endif
-
-extern void json_escape_string(char *dst, const char *src, size_t size);
-extern void json_fix_string(char *s);
-
-extern void *mymmap(const char *filename, size_t size, int flags, int ksm);
-extern int memory_file_save(const char *filename, void *mem, size_t size);
-
-extern int fd_is_valid(int fd);
-
-extern struct rlimit rlimit_nofile;
-
-extern int enable_ksm;
-
-extern int sleep_usec(usec_t usec);
-
-extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
-
-extern int processors;
-extern long get_system_cpus(void);
-
-extern pid_t pid_max;
-extern pid_t get_system_pid_max(void);
-
-/* Number of ticks per second */
-extern unsigned int hz;
-extern void get_system_HZ(void);
-
-extern int recursively_delete_dir(const char *path, const char *reason);
-
-extern volatile sig_atomic_t netdata_exit;
-extern const char *os_type;
-
-extern const char *program_version;
-
-/* fix for alpine linux */
-#ifndef RUSAGE_THREAD
-#ifdef RUSAGE_CHILDREN
-#define RUSAGE_THREAD RUSAGE_CHILDREN
-#endif
-#endif
-
-#define BITS_IN_A_KILOBIT 1000
-
-#endif /* NETDATA_COMMON_H */
diff --git a/src/daemon.c b/src/daemon.c
deleted file mode 100644
index 471c62c6e..000000000
--- a/src/daemon.c
+++ /dev/null
@@ -1,396 +0,0 @@
-#include "common.h"
-#include <sched.h>
-
-char pidfile[FILENAME_MAX + 1] = "";
-
-static void chown_open_file(int fd, uid_t uid, gid_t gid) {
- if(fd == -1) return;
-
- struct stat buf;
-
- if(fstat(fd, &buf) == -1) {
- error("Cannot fstat() fd %d", fd);
- return;
- }
-
- if((buf.st_uid != uid || buf.st_gid != gid) && S_ISREG(buf.st_mode)) {
- if(fchown(fd, uid, gid) == -1)
- error("Cannot fchown() fd %d.", fd);
- }
-}
-
-void create_needed_dir(const char *dir, uid_t uid, gid_t gid)
-{
- // attempt to create the directory
- if(mkdir(dir, 0755) == 0) {
- // we created it
-
- // chown it to match the required user
- if(chown(dir, uid, gid) == -1)
- error("Cannot chown directory '%s' to %u:%u", dir, (unsigned int)uid, (unsigned int)gid);
- }
- else if(errno != EEXIST)
- // log an error only if the directory does not exist
- error("Cannot create directory '%s'", dir);
-}
-
-int become_user(const char *username, int pid_fd) {
- int am_i_root = (getuid() == 0)?1:0;
-
- struct passwd *pw = getpwnam(username);
- if(!pw) {
- error("User %s is not present.", username);
- return -1;
- }
-
- uid_t uid = pw->pw_uid;
- gid_t gid = pw->pw_gid;
-
- create_needed_dir(netdata_configured_cache_dir, uid, gid);
- create_needed_dir(netdata_configured_varlib_dir, uid, gid);
-
- if(pidfile[0]) {
- if(chown(pidfile, uid, gid) == -1)
- error("Cannot chown '%s' to %u:%u", pidfile, (unsigned int)uid, (unsigned int)gid);
- }
-
- int ngroups = (int)sysconf(_SC_NGROUPS_MAX);
- gid_t *supplementary_groups = NULL;
- if(ngroups > 0) {
- supplementary_groups = mallocz(sizeof(gid_t) * ngroups);
- if(getgrouplist(username, gid, supplementary_groups, &ngroups) == -1) {
- if(am_i_root)
- error("Cannot get supplementary groups of user '%s'.", username);
-
- ngroups = 0;
- }
- }
-
- chown_open_file(STDOUT_FILENO, uid, gid);
- chown_open_file(STDERR_FILENO, uid, gid);
- chown_open_file(stdaccess_fd, uid, gid);
- chown_open_file(pid_fd, uid, gid);
-
- if(supplementary_groups && ngroups > 0) {
- if(setgroups((size_t)ngroups, supplementary_groups) == -1) {
- if(am_i_root)
- error("Cannot set supplementary groups for user '%s'", username);
- }
- ngroups = 0;
- }
-
- if(supplementary_groups)
- freez(supplementary_groups);
-
-#ifdef __APPLE__
- if(setregid(gid, gid) != 0) {
-#else
- if(setresgid(gid, gid, gid) != 0) {
-#endif /* __APPLE__ */
- error("Cannot switch to user's %s group (gid: %u).", username, gid);
- return -1;
- }
-
-#ifdef __APPLE__
- if(setreuid(uid, uid) != 0) {
-#else
- if(setresuid(uid, uid, uid) != 0) {
-#endif /* __APPLE__ */
- error("Cannot switch to user %s (uid: %u).", username, uid);
- return -1;
- }
-
- if(setgid(gid) != 0) {
- error("Cannot switch to user's %s group (gid: %u).", username, gid);
- return -1;
- }
- if(setegid(gid) != 0) {
- error("Cannot effectively switch to user's %s group (gid: %u).", username, gid);
- return -1;
- }
- if(setuid(uid) != 0) {
- error("Cannot switch to user %s (uid: %u).", username, uid);
- return -1;
- }
- if(seteuid(uid) != 0) {
- error("Cannot effectively switch to user %s (uid: %u).", username, uid);
- return -1;
- }
-
- return(0);
-}
-
-#ifndef OOM_SCORE_ADJ_MAX
-#define OOM_SCORE_ADJ_MAX (1000)
-#endif
-#ifndef OOM_SCORE_ADJ_MIN
-#define OOM_SCORE_ADJ_MIN (-1000)
-#endif
-
-static void oom_score_adj(void) {
- char buf[30 + 1];
- long long int old_score, wanted_score = OOM_SCORE_ADJ_MAX, final_score = 0;
-
- // read the existing score
- if(read_single_signed_number_file("/proc/self/oom_score_adj", &old_score)) {
- error("Out-Of-Memory (OOM) score setting is not supported on this system.");
- return;
- }
-
- if(old_score != 0)
- wanted_score = old_score;
-
- // check the environment
- char *s = getenv("OOMScoreAdjust");
- if(!s || !*s) {
- snprintfz(buf, 30, "%d", (int)wanted_score);
- s = buf;
- }
-
- // check netdata.conf configuration
- s = config_get(CONFIG_SECTION_GLOBAL, "OOM score", s);
- if(s && *s && (isdigit(*s) || *s == '-' || *s == '+'))
- wanted_score = atoll(s);
- else {
- info("Out-Of-Memory (OOM) score not changed due to non-numeric setting: '%s' (running with %d)", s, (int)old_score);
- return;
- }
-
- if(wanted_score < OOM_SCORE_ADJ_MIN) {
- error("Wanted Out-Of-Memory (OOM) score %d is too small. Using %d", (int)wanted_score, (int)OOM_SCORE_ADJ_MIN);
- wanted_score = OOM_SCORE_ADJ_MIN;
- }
-
- if(wanted_score > OOM_SCORE_ADJ_MAX) {
- error("Wanted Out-Of-Memory (OOM) score %d is too big. Using %d", (int)wanted_score, (int)OOM_SCORE_ADJ_MAX);
- wanted_score = OOM_SCORE_ADJ_MAX;
- }
-
- if(old_score == wanted_score) {
- info("Out-Of-Memory (OOM) score is already set to the wanted value %d", (int)old_score);
- return;
- }
-
- int written = 0;
- int fd = open("/proc/self/oom_score_adj", O_WRONLY);
- if(fd != -1) {
- snprintfz(buf, 30, "%d", (int)wanted_score);
- ssize_t len = strlen(buf);
- if(len > 0 && write(fd, buf, (size_t)len) == len) written = 1;
- close(fd);
-
- if(written) {
- if(read_single_signed_number_file("/proc/self/oom_score_adj", &final_score))
- error("Adjusted my Out-Of-Memory (OOM) score to %d, but cannot verify it.", (int)wanted_score);
- else if(final_score == wanted_score)
- info("Adjusted my Out-Of-Memory (OOM) score from %d to %d.", (int)old_score, (int)final_score);
- else
- error("Adjusted my Out-Of-Memory (OOM) score from %d to %d, but it has been set to %d.", (int)old_score, (int)wanted_score, (int)final_score);
- }
- else
- error("Failed to adjust my Out-Of-Memory (OOM) score to %d. Running with %d. (systemd systems may change it via netdata.service)", (int)wanted_score, (int)old_score);
- }
- else
- error("Failed to adjust my Out-Of-Memory (OOM) score. Cannot open /proc/self/oom_score_adj for writing.");
-}
-
-static void process_nice_level(void) {
-#ifdef HAVE_NICE
- int nice_level = (int)config_get_number(CONFIG_SECTION_GLOBAL, "process nice level", 19);
- if(nice(nice_level) == -1) error("Cannot set netdata CPU nice level to %d.", nice_level);
- else debug(D_SYSTEM, "Set netdata nice level to %d.", nice_level);
-#endif // HAVE_NICE
-};
-
-#ifdef HAVE_SCHED_SETSCHEDULER
-
-#define SCHED_FLAG_NONE 0x00
-#define SCHED_FLAG_PRIORITY_CONFIGURABLE 0x01 // the priority is user configurable
-#define SCHED_FLAG_KEEP_AS_IS 0x04 // do not attempt to set policy, priority or nice()
-#define SCHED_FLAG_USE_NICE 0x08 // use nice() after setting this policy
-
-struct sched_def {
- char *name;
- int policy;
- int priority;
- uint8_t flags;
-} scheduler_defaults[] = {
-
- // the order of array members is important!
- // the first defined is the default used by netdata
-
- // the available members are important too!
- // these are all the possible scheduling policies supported by netdata
-
-#ifdef SCHED_IDLE
- { "idle", SCHED_IDLE, 0, SCHED_FLAG_NONE },
-#endif
-
-#ifdef SCHED_OTHER
- { "nice", SCHED_OTHER, 0, SCHED_FLAG_USE_NICE },
- { "other", SCHED_OTHER, 0, SCHED_FLAG_USE_NICE },
-#endif
-
-#ifdef SCHED_RR
- { "rr", SCHED_RR, 0, SCHED_FLAG_PRIORITY_CONFIGURABLE },
-#endif
-
-#ifdef SCHED_FIFO
- { "fifo", SCHED_FIFO, 0, SCHED_FLAG_PRIORITY_CONFIGURABLE },
-#endif
-
-#ifdef SCHED_BATCH
- { "batch", SCHED_BATCH, 0, SCHED_FLAG_USE_NICE },
-#endif
-
- // do not change the scheduling priority
- { "keep", 0, 0, SCHED_FLAG_KEEP_AS_IS },
- { "none", 0, 0, SCHED_FLAG_KEEP_AS_IS },
-
- // array termination
- { NULL, 0, 0, 0 }
-};
-
-static void sched_setscheduler_set(void) {
-
- if(scheduler_defaults[0].name) {
- const char *name = scheduler_defaults[0].name;
- int policy = scheduler_defaults[0].policy, priority = scheduler_defaults[0].priority;
- uint8_t flags = scheduler_defaults[0].flags;
- int found = 0;
-
- // read the configuration
- name = config_get(CONFIG_SECTION_GLOBAL, "process scheduling policy", name);
- int i;
- for(i = 0 ; scheduler_defaults[i].name ; i++) {
- if(!strcmp(name, scheduler_defaults[i].name)) {
- found = 1;
- policy = scheduler_defaults[i].policy;
- priority = scheduler_defaults[i].priority;
- flags = scheduler_defaults[i].flags;
-
- if(flags & SCHED_FLAG_KEEP_AS_IS)
- return;
-
- if(flags & SCHED_FLAG_PRIORITY_CONFIGURABLE)
- priority = (int)config_get_number(CONFIG_SECTION_GLOBAL, "process scheduling priority", priority);
-
-#ifdef HAVE_SCHED_GET_PRIORITY_MIN
- errno = 0;
- if(priority < sched_get_priority_min(policy)) {
- error("scheduler %s (%d) priority %d is below the minimum %d. Using the minimum.", name, policy, priority, sched_get_priority_min(policy));
- priority = sched_get_priority_min(policy);
- }
-#endif
-#ifdef HAVE_SCHED_GET_PRIORITY_MAX
- errno = 0;
- if(priority > sched_get_priority_max(policy)) {
- error("scheduler %s (%d) priority %d is above the maximum %d. Using the maximum.", name, policy, priority, sched_get_priority_max(policy));
- priority = sched_get_priority_max(policy);
- }
-#endif
- break;
- }
- }
-
- if(!found) {
- error("Unknown scheduling policy '%s' - falling back to nice", name);
- goto fallback;
- }
-
- const struct sched_param param = {
- .sched_priority = priority
- };
-
- errno = 0;
- i = sched_setscheduler(0, policy, &param);
- if(i != 0) {
- error("Cannot adjust netdata scheduling policy to %s (%d), with priority %d. Falling back to nice.", name, policy, priority);
- }
- else {
- info("Adjusted netdata scheduling policy to %s (%d), with priority %d.", name, policy, priority);
- if(!(flags & SCHED_FLAG_USE_NICE))
- return;
- }
- }
-
-fallback:
- process_nice_level();
-}
-#else
-static void sched_setscheduler_set(void) {
- process_nice_level();
-}
-#endif
-
-int become_daemon(int dont_fork, const char *user)
-{
- if(!dont_fork) {
- int i = fork();
- if(i == -1) {
- perror("cannot fork");
- exit(1);
- }
- if(i != 0) {
- exit(0); // the parent
- }
-
- // become session leader
- if (setsid() < 0) {
- perror("Cannot become session leader.");
- exit(2);
- }
-
- // fork() again
- i = fork();
- if(i == -1) {
- perror("cannot fork");
- exit(1);
- }
- if(i != 0) {
- exit(0); // the parent
- }
- }
-
- // generate our pid file
- int pidfd = -1;
- if(pidfile[0]) {
- pidfd = open(pidfile, O_WRONLY | O_CREAT, 0644);
- if(pidfd >= 0) {
- if(ftruncate(pidfd, 0) != 0)
- error("Cannot truncate pidfile '%s'.", pidfile);
-
- char b[100];
- sprintf(b, "%d\n", getpid());
- ssize_t i = write(pidfd, b, strlen(b));
- if(i <= 0)
- error("Cannot write pidfile '%s'.", pidfile);
- }
- else error("Failed to open pidfile '%s'.", pidfile);
- }
-
- // Set new file permissions
- umask(0007);
-
- // adjust my Out-Of-Memory score
- oom_score_adj();
-
- // never become a problem
- sched_setscheduler_set();
-
- if(user && *user) {
- if(become_user(user, pidfd) != 0) {
- error("Cannot become user '%s'. Continuing as we are.", user);
- }
- else debug(D_SYSTEM, "Successfully became user '%s'.", user);
- }
- else {
- create_needed_dir(netdata_configured_cache_dir, getuid(), getgid());
- create_needed_dir(netdata_configured_varlib_dir, getuid(), getgid());
- }
-
- if(pidfd != -1)
- close(pidfd);
-
- return(0);
-}
diff --git a/src/daemon.h b/src/daemon.h
deleted file mode 100644
index 150d74e3a..000000000
--- a/src/daemon.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef NETDATA_DAEMON_H
-#define NETDATA_DAEMON_H 1
-
-extern int become_user(const char *username, int pid_fd);
-
-extern int become_daemon(int dont_fork, const char *user);
-
-extern void netdata_cleanup_and_exit(int i);
-
-extern char pidfile[];
-
-#endif /* NETDATA_DAEMON_H */
diff --git a/src/dictionary.c b/src/dictionary.c
deleted file mode 100644
index 512b4bbe6..000000000
--- a/src/dictionary.c
+++ /dev/null
@@ -1,292 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// dictionary statistics
-
-static inline void NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(DICTIONARY *dict) {
- if(likely(dict->stats))
- dict->stats->inserts++;
-}
-static inline void NETDATA_DICTIONARY_STATS_DELETES_PLUS1(DICTIONARY *dict) {
- if(likely(dict->stats))
- dict->stats->deletes++;
-}
-static inline void NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(DICTIONARY *dict) {
- if(likely(dict->stats))
- dict->stats->searches++;
-}
-static inline void NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(DICTIONARY *dict) {
- if(likely(dict->stats))
- dict->stats->entries++;
-}
-static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
- if(likely(dict->stats))
- dict->stats->entries--;
-}
-
-
-// ----------------------------------------------------------------------------
-// dictionary locks
-
-static inline void dictionary_read_lock(DICTIONARY *dict) {
- if(likely(dict->rwlock)) {
- // debug(D_DICTIONARY, "Dictionary READ lock");
- netdata_rwlock_rdlock(dict->rwlock);
- }
-}
-
-static inline void dictionary_write_lock(DICTIONARY *dict) {
- if(likely(dict->rwlock)) {
- // debug(D_DICTIONARY, "Dictionary WRITE lock");
- netdata_rwlock_wrlock(dict->rwlock);
- }
-}
-
-static inline void dictionary_unlock(DICTIONARY *dict) {
- if(likely(dict->rwlock)) {
- // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
- netdata_rwlock_unlock(dict->rwlock);
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// avl index
-
-static int name_value_compare(void* a, void* b) {
- if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
- else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
- else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
-}
-
-static inline NAME_VALUE *dictionary_name_value_index_find_nolock(DICTIONARY *dict, const char *name, uint32_t hash) {
- NAME_VALUE tmp;
- tmp.hash = (hash)?hash:simple_hash(name);
- tmp.name = (char *)name;
-
- NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict);
- return (NAME_VALUE *)avl_search(&(dict->values_index), (avl *) &tmp);
-}
-
-// ----------------------------------------------------------------------------
-// internal methods
-
-static NAME_VALUE *dictionary_name_value_create_nolock(DICTIONARY *dict, const char *name, void *value, size_t value_len, uint32_t hash) {
- debug(D_DICTIONARY, "Creating name value entry for name '%s'.", name);
-
- NAME_VALUE *nv = callocz(1, sizeof(NAME_VALUE));
-
- if(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)
- nv->name = (char *)name;
- else {
- nv->name = strdupz(name);
- }
-
- nv->hash = (hash)?hash:simple_hash(nv->name);
-
- if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)
- nv->value = value;
- else {
- nv->value = mallocz(value_len);
- memcpy(nv->value, value, value_len);
- }
-
- // index it
- NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict);
- if(unlikely(avl_insert(&((dict)->values_index), (avl *)(nv)) != (avl *)nv))
- error("dictionary: INTERNAL ERROR: duplicate insertion to dictionary.");
-
- NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict);
-
- return nv;
-}
-
-static void dictionary_name_value_destroy_nolock(DICTIONARY *dict, NAME_VALUE *nv) {
- debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
-
- NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict);
- if(unlikely(avl_remove(&(dict->values_index), (avl *)(nv)) != (avl *)nv))
- error("dictionary: INTERNAL ERROR: dictionary invalid removal of node.");
-
- NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict);
-
- if(!(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)) {
- debug(D_REGISTRY, "Dictionary freeing value of '%s'", nv->name);
- freez(nv->value);
- }
-
- if(!(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)) {
- debug(D_REGISTRY, "Dictionary freeing name '%s'", nv->name);
- freez(nv->name);
- }
-
- freez(nv);
-}
-
-// ----------------------------------------------------------------------------
-// API - basic methods
-
-DICTIONARY *dictionary_create(uint8_t flags) {
- debug(D_DICTIONARY, "Creating dictionary.");
-
- DICTIONARY *dict = callocz(1, sizeof(DICTIONARY));
-
- if(flags & DICTIONARY_FLAG_WITH_STATISTICS)
- dict->stats = callocz(1, sizeof(struct dictionary_stats));
-
- if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
- dict->rwlock = callocz(1, sizeof(netdata_rwlock_t));
- netdata_rwlock_init(dict->rwlock);
- }
-
- avl_init(&dict->values_index, name_value_compare);
- dict->flags = flags;
-
- return dict;
-}
-
-void dictionary_destroy(DICTIONARY *dict) {
- debug(D_DICTIONARY, "Destroying dictionary.");
-
- dictionary_write_lock(dict);
-
- while(dict->values_index.root)
- dictionary_name_value_destroy_nolock(dict, (NAME_VALUE *)dict->values_index.root);
-
- dictionary_unlock(dict);
-
- if(dict->stats)
- freez(dict->stats);
-
- if(dict->rwlock) {
- netdata_rwlock_destroy(dict->rwlock);
- freez(dict->rwlock);
- }
-
- freez(dict);
-}
-
-// ----------------------------------------------------------------------------
-
-void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
- debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
-
- uint32_t hash = simple_hash(name);
-
- dictionary_write_lock(dict);
-
- NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, hash);
- if(unlikely(!nv)) {
- debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
-
- nv = dictionary_name_value_create_nolock(dict, name, value, value_len, hash);
- if(unlikely(!nv))
- fatal("Cannot create name_value.");
- }
- else {
- debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
-
- if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE) {
- debug(D_REGISTRY, "Dictionary: linking value to '%s'", name);
- nv->value = value;
- }
- else {
- debug(D_REGISTRY, "Dictionary: cloning value to '%s'", name);
-
- // copy the new value without breaking
- // any other thread accessing the same entry
- void *new = mallocz(value_len),
- *old = nv->value;
-
- memcpy(new, value, value_len);
- nv->value = new;
-
- debug(D_REGISTRY, "Dictionary: freeing old value of '%s'", name);
- freez(old);
- }
- }
-
- dictionary_unlock(dict);
-
- return nv->value;
-}
-
-void *dictionary_get(DICTIONARY *dict, const char *name) {
- debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
-
- dictionary_read_lock(dict);
- NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
- dictionary_unlock(dict);
-
- if(unlikely(!nv)) {
- debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
- return NULL;
- }
-
- debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
- return nv->value;
-}
-
-int dictionary_del(DICTIONARY *dict, const char *name) {
- int ret;
-
- debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
-
- dictionary_write_lock(dict);
-
- NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
- if(unlikely(!nv)) {
- debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
- ret = -1;
- }
- else {
- debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
- dictionary_name_value_destroy_nolock(dict, nv);
- ret = 0;
- }
-
- dictionary_unlock(dict);
-
- return ret;
-}
-
-
-// ----------------------------------------------------------------------------
-// API - walk through the dictionary
-// the dictionary is locked for reading while this happens
-// do not user other dictionary calls while walking the dictionary - deadlock!
-
-static int dictionary_walker(avl *a, int (*callback)(void *entry, void *data), void *data) {
- int total = 0, ret = 0;
-
- if(a->avl_link[0]) {
- ret = dictionary_walker(a->avl_link[0], callback, data);
- if(ret < 0) return ret;
- total += ret;
- }
-
- ret = callback(((NAME_VALUE *)a)->value, data);
- if(ret < 0) return ret;
- total += ret;
-
- if(a->avl_link[1]) {
- ret = dictionary_walker(a->avl_link[1], callback, data);
- if (ret < 0) return ret;
- total += ret;
- }
-
- return total;
-}
-
-int dictionary_get_all(DICTIONARY *dict, int (*callback)(void *entry, void *data), void *data) {
- int ret = 0;
-
- dictionary_read_lock(dict);
-
- if(likely(dict->values_index.root))
- ret = dictionary_walker(dict->values_index.root, callback, data);
-
- dictionary_unlock(dict);
-
- return ret;
-}
diff --git a/src/dictionary.h b/src/dictionary.h
deleted file mode 100644
index f028dbb30..000000000
--- a/src/dictionary.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef NETDATA_DICTIONARY_H
-#define NETDATA_DICTIONARY_H 1
-
-struct dictionary_stats {
- unsigned long long inserts;
- unsigned long long deletes;
- unsigned long long searches;
- unsigned long long entries;
-};
-
-typedef struct name_value {
- avl avl; // the index - this has to be first!
-
- uint32_t hash; // a simple hash to speed up searching
- // we first compare hashes, and only if the hashes are equal we do string comparisons
-
- char *name;
- void *value;
-} NAME_VALUE;
-
-typedef struct dictionary {
- avl_tree values_index;
-
- uint8_t flags;
-
- struct dictionary_stats *stats;
- netdata_rwlock_t *rwlock;
-} DICTIONARY;
-
-#define DICTIONARY_FLAG_DEFAULT 0x00000000
-#define DICTIONARY_FLAG_SINGLE_THREADED 0x00000001
-#define DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE 0x00000002
-#define DICTIONARY_FLAG_NAME_LINK_DONT_CLONE 0x00000004
-#define DICTIONARY_FLAG_WITH_STATISTICS 0x00000008
-
-extern DICTIONARY *dictionary_create(uint8_t flags);
-extern void dictionary_destroy(DICTIONARY *dict);
-extern void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len);
-extern void *dictionary_get(DICTIONARY *dict, const char *name);
-extern int dictionary_del(DICTIONARY *dict, const char *name);
-
-extern int dictionary_get_all(DICTIONARY *dict, int (*callback)(void *entry, void *d), void *data);
-
-#endif /* NETDATA_DICTIONARY_H */
diff --git a/src/eval.c b/src/eval.c
deleted file mode 100644
index 84369f6d4..000000000
--- a/src/eval.c
+++ /dev/null
@@ -1,1188 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// data structures for storing the parsed expression in memory
-
-typedef struct eval_value {
- int type;
-
- union {
- calculated_number number;
- EVAL_VARIABLE *variable;
- struct eval_node *expression;
- };
-} EVAL_VALUE;
-
-typedef struct eval_node {
- int id;
- unsigned char operator;
- int precedence;
-
- int count;
- EVAL_VALUE ops[];
-} EVAL_NODE;
-
-// these are used for EVAL_NODE.operator
-// they are used as internal IDs to identify an operator
-// THEY ARE NOT USED FOR PARSING OPERATORS LIKE THAT
-#define EVAL_OPERATOR_NOP '\0'
-#define EVAL_OPERATOR_EXPRESSION_OPEN '('
-#define EVAL_OPERATOR_EXPRESSION_CLOSE ')'
-#define EVAL_OPERATOR_NOT '!'
-#define EVAL_OPERATOR_PLUS '+'
-#define EVAL_OPERATOR_MINUS '-'
-#define EVAL_OPERATOR_AND '&'
-#define EVAL_OPERATOR_OR '|'
-#define EVAL_OPERATOR_GREATER_THAN_OR_EQUAL 'G'
-#define EVAL_OPERATOR_LESS_THAN_OR_EQUAL 'L'
-#define EVAL_OPERATOR_NOT_EQUAL '~'
-#define EVAL_OPERATOR_EQUAL '='
-#define EVAL_OPERATOR_LESS '<'
-#define EVAL_OPERATOR_GREATER '>'
-#define EVAL_OPERATOR_MULTIPLY '*'
-#define EVAL_OPERATOR_DIVIDE '/'
-#define EVAL_OPERATOR_SIGN_PLUS 'P'
-#define EVAL_OPERATOR_SIGN_MINUS 'M'
-#define EVAL_OPERATOR_ABS 'A'
-#define EVAL_OPERATOR_IF_THEN_ELSE '?'
-
-// ----------------------------------------------------------------------------
-// forward function definitions
-
-static inline void eval_node_free(EVAL_NODE *op);
-static inline EVAL_NODE *parse_full_expression(const char **string, int *error);
-static inline EVAL_NODE *parse_one_full_operand(const char **string, int *error);
-static inline calculated_number eval_node(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error);
-static inline void print_parsed_as_node(BUFFER *out, EVAL_NODE *op, int *error);
-static inline void print_parsed_as_constant(BUFFER *out, calculated_number n);
-
-// ----------------------------------------------------------------------------
-// evaluation of expressions
-
-static inline calculated_number eval_variable(EVAL_EXPRESSION *exp, EVAL_VARIABLE *v, int *error) {
- static uint32_t this_hash = 0, now_hash = 0, after_hash = 0, before_hash = 0, status_hash = 0, removed_hash = 0, uninitialized_hash = 0, undefined_hash = 0, clear_hash = 0, warning_hash = 0, critical_hash = 0;
- calculated_number n;
-
- if(unlikely(this_hash == 0)) {
- this_hash = simple_hash("this");
- now_hash = simple_hash("now");
- after_hash = simple_hash("after");
- before_hash = simple_hash("before");
- status_hash = simple_hash("status");
- removed_hash = simple_hash("REMOVED");
- uninitialized_hash = simple_hash("UNINITIALIZED");
- undefined_hash = simple_hash("UNDEFINED");
- clear_hash = simple_hash("CLEAR");
- warning_hash = simple_hash("WARNING");
- critical_hash = simple_hash("CRITICAL");
- }
-
- if(unlikely(v->hash == this_hash && !strcmp(v->name, "this"))) {
- n = (exp->this)?*exp->this:NAN;
- buffer_strcat(exp->error_msg, "[ $this = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == after_hash && !strcmp(v->name, "after"))) {
- n = (exp->after && *exp->after)?*exp->after:NAN;
- buffer_strcat(exp->error_msg, "[ $after = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == before_hash && !strcmp(v->name, "before"))) {
- n = (exp->before && *exp->before)?*exp->before:NAN;
- buffer_strcat(exp->error_msg, "[ $before = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == now_hash && !strcmp(v->name, "now"))) {
- n = now_realtime_sec();
- buffer_strcat(exp->error_msg, "[ $now = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == status_hash && !strcmp(v->name, "status"))) {
- n = (exp->status)?*exp->status:RRDCALC_STATUS_UNINITIALIZED;
- buffer_strcat(exp->error_msg, "[ $status = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == removed_hash && !strcmp(v->name, "REMOVED"))) {
- n = RRDCALC_STATUS_REMOVED;
- buffer_strcat(exp->error_msg, "[ $REMOVED = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == uninitialized_hash && !strcmp(v->name, "UNINITIALIZED"))) {
- n = RRDCALC_STATUS_UNINITIALIZED;
- buffer_strcat(exp->error_msg, "[ $UNINITIALIZED = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == undefined_hash && !strcmp(v->name, "UNDEFINED"))) {
- n = RRDCALC_STATUS_UNDEFINED;
- buffer_strcat(exp->error_msg, "[ $UNDEFINED = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == clear_hash && !strcmp(v->name, "CLEAR"))) {
- n = RRDCALC_STATUS_CLEAR;
- buffer_strcat(exp->error_msg, "[ $CLEAR = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == warning_hash && !strcmp(v->name, "WARNING"))) {
- n = RRDCALC_STATUS_WARNING;
- buffer_strcat(exp->error_msg, "[ $WARNING = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(unlikely(v->hash == critical_hash && !strcmp(v->name, "CRITICAL"))) {
- n = RRDCALC_STATUS_CRITICAL;
- buffer_strcat(exp->error_msg, "[ $CRITICAL = ");
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- if(exp->rrdcalc && health_variable_lookup(v->name, v->hash, exp->rrdcalc, &n)) {
- buffer_sprintf(exp->error_msg, "[ ${%s} = ", v->name);
- print_parsed_as_constant(exp->error_msg, n);
- buffer_strcat(exp->error_msg, " ] ");
- return n;
- }
-
- *error = EVAL_ERROR_UNKNOWN_VARIABLE;
- buffer_sprintf(exp->error_msg, "[ undefined variable '%s' ] ", v->name);
- return 0;
-}
-
-static inline calculated_number eval_value(EVAL_EXPRESSION *exp, EVAL_VALUE *v, int *error) {
- calculated_number n;
-
- switch(v->type) {
- case EVAL_VALUE_EXPRESSION:
- n = eval_node(exp, v->expression, error);
- break;
-
- case EVAL_VALUE_NUMBER:
- n = v->number;
- break;
-
- case EVAL_VALUE_VARIABLE:
- n = eval_variable(exp, v->variable, error);
- break;
-
- default:
- *error = EVAL_ERROR_INVALID_VALUE;
- n = 0;
- break;
- }
-
- return n;
-}
-
-static inline int is_true(calculated_number n) {
- if(isnan(n)) return 0;
- if(isinf(n)) return 1;
- if(n == 0) return 0;
- return 1;
-}
-
-calculated_number eval_and(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- return is_true(eval_value(exp, &op->ops[0], error)) && is_true(eval_value(exp, &op->ops[1], error));
-}
-calculated_number eval_or(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- return is_true(eval_value(exp, &op->ops[0], error)) || is_true(eval_value(exp, &op->ops[1], error));
-}
-calculated_number eval_greater_than_or_equal(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- return isgreaterequal(n1, n2);
-}
-calculated_number eval_less_than_or_equal(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- return islessequal(n1, n2);
-}
-calculated_number eval_equal(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- if(isnan(n1) && isnan(n2)) return 1;
- if(isinf(n1) && isinf(n2)) return 1;
- if(isnan(n1) || isnan(n2)) return 0;
- if(isinf(n1) || isinf(n2)) return 0;
- return calculated_number_equal(n1, n2);
-}
-calculated_number eval_not_equal(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- return !eval_equal(exp, op, error);
-}
-calculated_number eval_less(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- return isless(n1, n2);
-}
-calculated_number eval_greater(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- return isgreater(n1, n2);
-}
-calculated_number eval_plus(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- if(isnan(n1) || isnan(n2)) return NAN;
- if(isinf(n1) || isinf(n2)) return INFINITY;
- return n1 + n2;
-}
-calculated_number eval_minus(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- if(isnan(n1) || isnan(n2)) return NAN;
- if(isinf(n1) || isinf(n2)) return INFINITY;
- return n1 - n2;
-}
-calculated_number eval_multiply(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- if(isnan(n1) || isnan(n2)) return NAN;
- if(isinf(n1) || isinf(n2)) return INFINITY;
- return n1 * n2;
-}
-calculated_number eval_divide(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- calculated_number n2 = eval_value(exp, &op->ops[1], error);
- if(isnan(n1) || isnan(n2)) return NAN;
- if(isinf(n1) || isinf(n2)) return INFINITY;
- return n1 / n2;
-}
-calculated_number eval_nop(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- return eval_value(exp, &op->ops[0], error);
-}
-calculated_number eval_not(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- return !is_true(eval_value(exp, &op->ops[0], error));
-}
-calculated_number eval_sign_plus(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- return eval_value(exp, &op->ops[0], error);
-}
-calculated_number eval_sign_minus(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- if(isnan(n1)) return NAN;
- if(isinf(n1)) return INFINITY;
- return -n1;
-}
-calculated_number eval_abs(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- calculated_number n1 = eval_value(exp, &op->ops[0], error);
- if(isnan(n1)) return NAN;
- if(isinf(n1)) return INFINITY;
- return abs(n1);
-}
-calculated_number eval_if_then_else(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- if(is_true(eval_value(exp, &op->ops[0], error)))
- return eval_value(exp, &op->ops[1], error);
- else
- return eval_value(exp, &op->ops[2], error);
-}
-
-static struct operator {
- const char *print_as;
- char precedence;
- char parameters;
- char isfunction;
- calculated_number (*eval)(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error);
-} operators[256] = {
- // this is a random access array
- // we always access it with a known EVAL_OPERATOR_X
-
- [EVAL_OPERATOR_AND] = { "&&", 2, 2, 0, eval_and },
- [EVAL_OPERATOR_OR] = { "||", 2, 2, 0, eval_or },
- [EVAL_OPERATOR_GREATER_THAN_OR_EQUAL] = { ">=", 3, 2, 0, eval_greater_than_or_equal },
- [EVAL_OPERATOR_LESS_THAN_OR_EQUAL] = { "<=", 3, 2, 0, eval_less_than_or_equal },
- [EVAL_OPERATOR_NOT_EQUAL] = { "!=", 3, 2, 0, eval_not_equal },
- [EVAL_OPERATOR_EQUAL] = { "==", 3, 2, 0, eval_equal },
- [EVAL_OPERATOR_LESS] = { "<", 3, 2, 0, eval_less },
- [EVAL_OPERATOR_GREATER] = { ">", 3, 2, 0, eval_greater },
- [EVAL_OPERATOR_PLUS] = { "+", 4, 2, 0, eval_plus },
- [EVAL_OPERATOR_MINUS] = { "-", 4, 2, 0, eval_minus },
- [EVAL_OPERATOR_MULTIPLY] = { "*", 5, 2, 0, eval_multiply },
- [EVAL_OPERATOR_DIVIDE] = { "/", 5, 2, 0, eval_divide },
- [EVAL_OPERATOR_NOT] = { "!", 6, 1, 0, eval_not },
- [EVAL_OPERATOR_SIGN_PLUS] = { "+", 6, 1, 0, eval_sign_plus },
- [EVAL_OPERATOR_SIGN_MINUS] = { "-", 6, 1, 0, eval_sign_minus },
- [EVAL_OPERATOR_ABS] = { "abs(",6,1, 1, eval_abs },
- [EVAL_OPERATOR_IF_THEN_ELSE] = { "?", 7, 3, 0, eval_if_then_else },
- [EVAL_OPERATOR_NOP] = { NULL, 8, 1, 0, eval_nop },
- [EVAL_OPERATOR_EXPRESSION_OPEN] = { NULL, 8, 1, 0, eval_nop },
-
- // this should exist in our evaluation list
- [EVAL_OPERATOR_EXPRESSION_CLOSE] = { NULL, 99, 1, 0, eval_nop }
-};
-
-#define eval_precedence(operator) (operators[(unsigned char)(operator)].precedence)
-
-static inline calculated_number eval_node(EVAL_EXPRESSION *exp, EVAL_NODE *op, int *error) {
- if(unlikely(op->count != operators[op->operator].parameters)) {
- *error = EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS;
- return 0;
- }
-
- calculated_number n = operators[op->operator].eval(exp, op, error);
-
- return n;
-}
-
-// ----------------------------------------------------------------------------
-// parsed-as generation
-
-static inline void print_parsed_as_variable(BUFFER *out, EVAL_VARIABLE *v, int *error) {
- (void)error;
- buffer_sprintf(out, "${%s}", v->name);
-}
-
-static inline void print_parsed_as_constant(BUFFER *out, calculated_number n) {
- if(unlikely(isnan(n))) {
- buffer_strcat(out, "nan");
- return;
- }
-
- if(unlikely(isinf(n))) {
- buffer_strcat(out, "inf");
- return;
- }
-
- char b[100+1], *s;
- snprintfz(b, 100, CALCULATED_NUMBER_FORMAT, n);
-
- s = &b[strlen(b) - 1];
- while(s > b && *s == '0') {
- *s ='\0';
- s--;
- }
-
- if(s > b && *s == '.')
- *s = '\0';
-
- buffer_strcat(out, b);
-}
-
-static inline void print_parsed_as_value(BUFFER *out, EVAL_VALUE *v, int *error) {
- switch(v->type) {
- case EVAL_VALUE_EXPRESSION:
- print_parsed_as_node(out, v->expression, error);
- break;
-
- case EVAL_VALUE_NUMBER:
- print_parsed_as_constant(out, v->number);
- break;
-
- case EVAL_VALUE_VARIABLE:
- print_parsed_as_variable(out, v->variable, error);
- break;
-
- default:
- *error = EVAL_ERROR_INVALID_VALUE;
- break;
- }
-}
-
-static inline void print_parsed_as_node(BUFFER *out, EVAL_NODE *op, int *error) {
- if(unlikely(op->count != operators[op->operator].parameters)) {
- *error = EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS;
- return;
- }
-
- if(operators[op->operator].parameters == 1) {
-
- if(operators[op->operator].print_as)
- buffer_sprintf(out, "%s", operators[op->operator].print_as);
-
- //if(op->operator == EVAL_OPERATOR_EXPRESSION_OPEN)
- // buffer_strcat(out, "(");
-
- print_parsed_as_value(out, &op->ops[0], error);
-
- //if(op->operator == EVAL_OPERATOR_EXPRESSION_OPEN)
- // buffer_strcat(out, ")");
- }
-
- else if(operators[op->operator].parameters == 2) {
- buffer_strcat(out, "(");
- print_parsed_as_value(out, &op->ops[0], error);
-
- if(operators[op->operator].print_as)
- buffer_sprintf(out, " %s ", operators[op->operator].print_as);
-
- print_parsed_as_value(out, &op->ops[1], error);
- buffer_strcat(out, ")");
- }
- else if(op->operator == EVAL_OPERATOR_IF_THEN_ELSE && operators[op->operator].parameters == 3) {
- buffer_strcat(out, "(");
- print_parsed_as_value(out, &op->ops[0], error);
-
- if(operators[op->operator].print_as)
- buffer_sprintf(out, " %s ", operators[op->operator].print_as);
-
- print_parsed_as_value(out, &op->ops[1], error);
- buffer_strcat(out, " : ");
- print_parsed_as_value(out, &op->ops[2], error);
- buffer_strcat(out, ")");
- }
-
- if(operators[op->operator].isfunction)
- buffer_strcat(out, ")");
-}
-
-// ----------------------------------------------------------------------------
-// parsing expressions
-
-// skip spaces
-static inline void skip_spaces(const char **string) {
- const char *s = *string;
- while(isspace(*s)) s++;
- *string = s;
-}
-
-// what character can appear just after an operator keyword
-// like NOT AND OR ?
-static inline int isoperatorterm_word(const char s) {
- if(isspace(s) || s == '(' || s == '$' || s == '!' || s == '-' || s == '+' || isdigit(s) || !s)
- return 1;
-
- return 0;
-}
-
-// what character can appear just after an operator symbol?
-static inline int isoperatorterm_symbol(const char s) {
- if(isoperatorterm_word(s) || isalpha(s))
- return 1;
-
- return 0;
-}
-
-// return 1 if the character should never appear in a variable
-static inline int isvariableterm(const char s) {
- if(isalnum(s) || s == '.' || s == '_')
- return 0;
-
- return 1;
-}
-
-// ----------------------------------------------------------------------------
-// parse operators
-
-static inline int parse_and(const char **string) {
- const char *s = *string;
-
- // AND
- if((s[0] == 'A' || s[0] == 'a') && (s[1] == 'N' || s[1] == 'n') && (s[2] == 'D' || s[2] == 'd') && isoperatorterm_word(s[3])) {
- *string = &s[4];
- return 1;
- }
-
- // &&
- if(s[0] == '&' && s[1] == '&' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_or(const char **string) {
- const char *s = *string;
-
- // OR
- if((s[0] == 'O' || s[0] == 'o') && (s[1] == 'R' || s[1] == 'r') && isoperatorterm_word(s[2])) {
- *string = &s[3];
- return 1;
- }
-
- // ||
- if(s[0] == '|' && s[1] == '|' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_greater_than_or_equal(const char **string) {
- const char *s = *string;
-
- // >=
- if(s[0] == '>' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_less_than_or_equal(const char **string) {
- const char *s = *string;
-
- // <=
- if (s[0] == '<' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_greater(const char **string) {
- const char *s = *string;
-
- // >
- if(s[0] == '>' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_less(const char **string) {
- const char *s = *string;
-
- // <
- if(s[0] == '<' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_equal(const char **string) {
- const char *s = *string;
-
- // ==
- if(s[0] == '=' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- return 1;
- }
-
- // =
- if(s[0] == '=' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_not_equal(const char **string) {
- const char *s = *string;
-
- // !=
- if(s[0] == '!' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- return 1;
- }
-
- // <>
- if(s[0] == '<' && s[1] == '>' && isoperatorterm_symbol(s[2])) {
- *string = &s[2];
- }
-
- return 0;
-}
-
-static inline int parse_not(const char **string) {
- const char *s = *string;
-
- // NOT
- if((s[0] == 'N' || s[0] == 'n') && (s[1] == 'O' || s[1] == 'o') && (s[2] == 'T' || s[2] == 't') && isoperatorterm_word(s[3])) {
- *string = &s[3];
- return 1;
- }
-
- if(s[0] == '!') {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_multiply(const char **string) {
- const char *s = *string;
-
- // *
- if(s[0] == '*' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_divide(const char **string) {
- const char *s = *string;
-
- // /
- if(s[0] == '/' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_minus(const char **string) {
- const char *s = *string;
-
- // -
- if(s[0] == '-' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_plus(const char **string) {
- const char *s = *string;
-
- // +
- if(s[0] == '+' && isoperatorterm_symbol(s[1])) {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_open_subexpression(const char **string) {
- const char *s = *string;
-
- // (
- if(s[0] == '(') {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-#define parse_close_function(x) parse_close_subexpression(x)
-
-static inline int parse_close_subexpression(const char **string) {
- const char *s = *string;
-
- // )
- if(s[0] == ')') {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_variable(const char **string, char *buffer, size_t len) {
- const char *s = *string;
-
- // $
- if(*s == '$') {
- size_t i = 0;
- s++;
-
- if(*s == '{') {
- // ${variable_name}
-
- s++;
- while (*s && *s != '}' && i < len)
- buffer[i++] = *s++;
-
- if(*s == '}')
- s++;
- }
- else {
- // $variable_name
-
- while (*s && !isvariableterm(*s) && i < len)
- buffer[i++] = *s++;
- }
-
- buffer[i] = '\0';
-
- if (buffer[0]) {
- *string = s;
- return 1;
- }
- }
-
- return 0;
-}
-
-static inline int parse_constant(const char **string, calculated_number *number) {
- char *end = NULL;
- calculated_number n = str2ld(*string, &end);
- if(unlikely(!end || *string == end)) {
- *number = 0;
- return 0;
- }
- *number = n;
- *string = end;
- return 1;
-}
-
-static inline int parse_abs(const char **string) {
- const char *s = *string;
-
- // ABS
- if((s[0] == 'A' || s[0] == 'a') && (s[1] == 'B' || s[1] == 'b') && (s[2] == 'S' || s[2] == 's') && s[3] == '(') {
- *string = &s[3];
- return 1;
- }
-
- return 0;
-}
-
-static inline int parse_if_then_else(const char **string) {
- const char *s = *string;
-
- // ?
- if(s[0] == '?') {
- *string = &s[1];
- return 1;
- }
-
- return 0;
-}
-
-static struct operator_parser {
- unsigned char id;
- int (*parse)(const char **);
-} operator_parsers[] = {
- // the order in this list is important!
- // the first matching will be used
- // so place the longer of overlapping ones
- // at the top
-
- { EVAL_OPERATOR_AND, parse_and },
- { EVAL_OPERATOR_OR, parse_or },
- { EVAL_OPERATOR_GREATER_THAN_OR_EQUAL, parse_greater_than_or_equal },
- { EVAL_OPERATOR_LESS_THAN_OR_EQUAL, parse_less_than_or_equal },
- { EVAL_OPERATOR_NOT_EQUAL, parse_not_equal },
- { EVAL_OPERATOR_EQUAL, parse_equal },
- { EVAL_OPERATOR_LESS, parse_less },
- { EVAL_OPERATOR_GREATER, parse_greater },
- { EVAL_OPERATOR_PLUS, parse_plus },
- { EVAL_OPERATOR_MINUS, parse_minus },
- { EVAL_OPERATOR_MULTIPLY, parse_multiply },
- { EVAL_OPERATOR_DIVIDE, parse_divide },
- { EVAL_OPERATOR_IF_THEN_ELSE, parse_if_then_else },
-
- /* we should not put in this list the following:
- *
- * - NOT
- * - (
- * - )
- *
- * these are handled in code
- */
-
- // termination
- { EVAL_OPERATOR_NOP, NULL }
-};
-
-static inline unsigned char parse_operator(const char **string, int *precedence) {
- skip_spaces(string);
-
- int i;
- for(i = 0 ; operator_parsers[i].parse != NULL ; i++)
- if(operator_parsers[i].parse(string)) {
- if(precedence) *precedence = eval_precedence(operator_parsers[i].id);
- return operator_parsers[i].id;
- }
-
- return EVAL_OPERATOR_NOP;
-}
-
-// ----------------------------------------------------------------------------
-// memory management
-
-static inline EVAL_NODE *eval_node_alloc(int count) {
- static int id = 1;
-
- EVAL_NODE *op = callocz(1, sizeof(EVAL_NODE) + (sizeof(EVAL_VALUE) * count));
-
- op->id = id++;
- op->operator = EVAL_OPERATOR_NOP;
- op->precedence = eval_precedence(EVAL_OPERATOR_NOP);
- op->count = count;
- return op;
-}
-
-static inline void eval_node_set_value_to_node(EVAL_NODE *op, int pos, EVAL_NODE *value) {
- if(pos >= op->count)
- fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
-
- op->ops[pos].type = EVAL_VALUE_EXPRESSION;
- op->ops[pos].expression = value;
-}
-
-static inline void eval_node_set_value_to_constant(EVAL_NODE *op, int pos, calculated_number value) {
- if(pos >= op->count)
- fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
-
- op->ops[pos].type = EVAL_VALUE_NUMBER;
- op->ops[pos].number = value;
-}
-
-static inline void eval_node_set_value_to_variable(EVAL_NODE *op, int pos, const char *variable) {
- if(pos >= op->count)
- fatal("Invalid request to set position %d of OPERAND that has only %d values", pos + 1, op->count + 1);
-
- op->ops[pos].type = EVAL_VALUE_VARIABLE;
- op->ops[pos].variable = callocz(1, sizeof(EVAL_VARIABLE));
- op->ops[pos].variable->name = strdupz(variable);
- op->ops[pos].variable->hash = simple_hash(op->ops[pos].variable->name);
-}
-
-static inline void eval_variable_free(EVAL_VARIABLE *v) {
- freez(v->name);
- freez(v);
-}
-
-static inline void eval_value_free(EVAL_VALUE *v) {
- switch(v->type) {
- case EVAL_VALUE_EXPRESSION:
- eval_node_free(v->expression);
- break;
-
- case EVAL_VALUE_VARIABLE:
- eval_variable_free(v->variable);
- break;
-
- default:
- break;
- }
-}
-
-static inline void eval_node_free(EVAL_NODE *op) {
- if(op->count) {
- int i;
- for(i = op->count - 1; i >= 0 ;i--)
- eval_value_free(&op->ops[i]);
- }
-
- freez(op);
-}
-
-// ----------------------------------------------------------------------------
-// the parsing logic
-
-// helper function to avoid allocations all over the place
-static inline EVAL_NODE *parse_next_operand_given_its_operator(const char **string, unsigned char operator_type, int *error) {
- EVAL_NODE *sub = parse_one_full_operand(string, error);
- if(!sub) return NULL;
-
- EVAL_NODE *op = eval_node_alloc(1);
- op->operator = operator_type;
- eval_node_set_value_to_node(op, 0, sub);
- return op;
-}
-
-// parse a full operand, including its sign or other associative operator (e.g. NOT)
-static inline EVAL_NODE *parse_one_full_operand(const char **string, int *error) {
- char variable_buffer[EVAL_MAX_VARIABLE_NAME_LENGTH + 1];
- EVAL_NODE *op1 = NULL;
- calculated_number number;
-
- *error = EVAL_ERROR_OK;
-
- skip_spaces(string);
- if(!(**string)) {
- *error = EVAL_ERROR_MISSING_OPERAND;
- return NULL;
- }
-
- if(parse_not(string)) {
- op1 = parse_next_operand_given_its_operator(string, EVAL_OPERATOR_NOT, error);
- op1->precedence = eval_precedence(EVAL_OPERATOR_NOT);
- }
- else if(parse_plus(string)) {
- op1 = parse_next_operand_given_its_operator(string, EVAL_OPERATOR_SIGN_PLUS, error);
- op1->precedence = eval_precedence(EVAL_OPERATOR_SIGN_PLUS);
- }
- else if(parse_minus(string)) {
- op1 = parse_next_operand_given_its_operator(string, EVAL_OPERATOR_SIGN_MINUS, error);
- op1->precedence = eval_precedence(EVAL_OPERATOR_SIGN_MINUS);
- }
- else if(parse_abs(string)) {
- op1 = parse_next_operand_given_its_operator(string, EVAL_OPERATOR_ABS, error);
- op1->precedence = eval_precedence(EVAL_OPERATOR_ABS);
- }
- else if(parse_open_subexpression(string)) {
- EVAL_NODE *sub = parse_full_expression(string, error);
- if(sub) {
- op1 = eval_node_alloc(1);
- op1->operator = EVAL_OPERATOR_EXPRESSION_OPEN;
- op1->precedence = eval_precedence(EVAL_OPERATOR_EXPRESSION_OPEN);
- eval_node_set_value_to_node(op1, 0, sub);
- if(!parse_close_subexpression(string)) {
- *error = EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION;
- eval_node_free(op1);
- return NULL;
- }
- }
- }
- else if(parse_variable(string, variable_buffer, EVAL_MAX_VARIABLE_NAME_LENGTH)) {
- op1 = eval_node_alloc(1);
- op1->operator = EVAL_OPERATOR_NOP;
- eval_node_set_value_to_variable(op1, 0, variable_buffer);
- }
- else if(parse_constant(string, &number)) {
- op1 = eval_node_alloc(1);
- op1->operator = EVAL_OPERATOR_NOP;
- eval_node_set_value_to_constant(op1, 0, number);
- }
- else if(**string)
- *error = EVAL_ERROR_UNKNOWN_OPERAND;
- else
- *error = EVAL_ERROR_MISSING_OPERAND;
-
- return op1;
-}
-
-// parse an operator and the rest of the expression
-// precedence processing is handled here
-static inline EVAL_NODE *parse_rest_of_expression(const char **string, int *error, EVAL_NODE *op1) {
- EVAL_NODE *op2 = NULL;
- unsigned char operator;
- int precedence;
-
- operator = parse_operator(string, &precedence);
- skip_spaces(string);
-
- if(operator != EVAL_OPERATOR_NOP) {
- op2 = parse_one_full_operand(string, error);
- if(!op2) {
- // error is already reported
- eval_node_free(op1);
- return NULL;
- }
-
- EVAL_NODE *op = eval_node_alloc(operators[operator].parameters);
- op->operator = operator;
- op->precedence = precedence;
-
- if(operator == EVAL_OPERATOR_IF_THEN_ELSE && op->count == 3) {
- skip_spaces(string);
-
- if(**string != ':') {
- eval_node_free(op);
- eval_node_free(op1);
- eval_node_free(op2);
- *error = EVAL_ERROR_IF_THEN_ELSE_MISSING_ELSE;
- return NULL;
- }
- (*string)++;
-
- skip_spaces(string);
-
- EVAL_NODE *op3 = parse_one_full_operand(string, error);
- if(!op3) {
- eval_node_free(op);
- eval_node_free(op1);
- eval_node_free(op2);
- // error is already reported
- return NULL;
- }
-
- eval_node_set_value_to_node(op, 2, op3);
- }
-
- eval_node_set_value_to_node(op, 1, op2);
-
- // precedence processing
- // if this operator has a higher precedence compared to its next
- // put the next operator on top of us (top = evaluated later)
- // function recursion does the rest...
- if(op->precedence > op1->precedence && op1->count == 2 && op1->operator != '(' && op1->ops[1].type == EVAL_VALUE_EXPRESSION) {
- eval_node_set_value_to_node(op, 0, op1->ops[1].expression);
- op1->ops[1].expression = op;
- op = op1;
- }
- else
- eval_node_set_value_to_node(op, 0, op1);
-
- return parse_rest_of_expression(string, error, op);
- }
- else if(**string == ')') {
- ;
- }
- else if(**string) {
- eval_node_free(op1);
- op1 = NULL;
- *error = EVAL_ERROR_MISSING_OPERATOR;
- }
-
- return op1;
-}
-
-// high level function to parse an expression or a sub-expression
-static inline EVAL_NODE *parse_full_expression(const char **string, int *error) {
- EVAL_NODE *op1 = parse_one_full_operand(string, error);
- if(!op1) {
- *error = EVAL_ERROR_MISSING_OPERAND;
- return NULL;
- }
-
- return parse_rest_of_expression(string, error, op1);
-}
-
-// ----------------------------------------------------------------------------
-// public API
-
-int expression_evaluate(EVAL_EXPRESSION *exp) {
- exp->error = EVAL_ERROR_OK;
-
- buffer_reset(exp->error_msg);
- exp->result = eval_node(exp, (EVAL_NODE *)exp->nodes, &exp->error);
-
- if(unlikely(isnan(exp->result))) {
- if(exp->error == EVAL_ERROR_OK)
- exp->error = EVAL_ERROR_VALUE_IS_NAN;
- }
- else if(unlikely(isinf(exp->result))) {
- if(exp->error == EVAL_ERROR_OK)
- exp->error = EVAL_ERROR_VALUE_IS_INFINITE;
- }
- else if(unlikely(exp->error == EVAL_ERROR_UNKNOWN_VARIABLE)) {
- // although there is an unknown variable
- // the expression was evaluated successfully
- exp->error = EVAL_ERROR_OK;
- }
-
- if(exp->error != EVAL_ERROR_OK) {
- exp->result = NAN;
-
- if(buffer_strlen(exp->error_msg))
- buffer_strcat(exp->error_msg, "; ");
-
- buffer_sprintf(exp->error_msg, "failed to evaluate expression with error %d (%s)", exp->error, expression_strerror(exp->error));
- return 0;
- }
-
- return 1;
-}
-
-EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, int *error) {
- const char *s = string;
- int err = EVAL_ERROR_OK;
-
- EVAL_NODE *op = parse_full_expression(&s, &err);
-
- if(*s) {
- if(op) {
- eval_node_free(op);
- op = NULL;
- }
- err = EVAL_ERROR_REMAINING_GARBAGE;
- }
-
- if (failed_at) *failed_at = s;
- if (error) *error = err;
-
- if(!op) {
- unsigned long pos = s - string + 1;
- error("failed to parse expression '%s': %s at character %lu (i.e.: '%s').", string, expression_strerror(err), pos, s);
- return NULL;
- }
-
- BUFFER *out = buffer_create(1024);
- print_parsed_as_node(out, op, &err);
- if(err != EVAL_ERROR_OK) {
- error("failed to re-generate expression '%s' with reason: %s", string, expression_strerror(err));
- eval_node_free(op);
- buffer_free(out);
- return NULL;
- }
-
- EVAL_EXPRESSION *exp = callocz(1, sizeof(EVAL_EXPRESSION));
-
- exp->source = strdupz(string);
- exp->parsed_as = strdupz(buffer_tostring(out));
- buffer_free(out);
-
- exp->error_msg = buffer_create(100);
- exp->nodes = (void *)op;
-
- return exp;
-}
-
-void expression_free(EVAL_EXPRESSION *exp) {
- if(!exp) return;
-
- if(exp->nodes) eval_node_free((EVAL_NODE *)exp->nodes);
- freez((void *)exp->source);
- freez((void *)exp->parsed_as);
- buffer_free(exp->error_msg);
- freez(exp);
-}
-
-const char *expression_strerror(int error) {
- switch(error) {
- case EVAL_ERROR_OK:
- return "success";
-
- case EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION:
- return "missing closing parenthesis";
-
- case EVAL_ERROR_UNKNOWN_OPERAND:
- return "unknown operand";
-
- case EVAL_ERROR_MISSING_OPERAND:
- return "expected operand";
-
- case EVAL_ERROR_MISSING_OPERATOR:
- return "expected operator";
-
- case EVAL_ERROR_REMAINING_GARBAGE:
- return "remaining characters after expression";
-
- case EVAL_ERROR_INVALID_VALUE:
- return "invalid value structure - internal error";
-
- case EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS:
- return "wrong number of operands for operation - internal error";
-
- case EVAL_ERROR_VALUE_IS_NAN:
- return "value is unset";
-
- case EVAL_ERROR_VALUE_IS_INFINITE:
- return "computed value is infinite";
-
- case EVAL_ERROR_UNKNOWN_VARIABLE:
- return "undefined variable";
-
- case EVAL_ERROR_IF_THEN_ELSE_MISSING_ELSE:
- return "missing second sub-expression of inline conditional";
-
- default:
- return "unknown error";
- }
-}
diff --git a/src/eval.h b/src/eval.h
deleted file mode 100644
index 6a5562fd4..000000000
--- a/src/eval.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef NETDATA_EVAL_H
-#define NETDATA_EVAL_H
-
-#define EVAL_MAX_VARIABLE_NAME_LENGTH 300
-
-typedef struct eval_variable {
- char *name;
- uint32_t hash;
- struct eval_variable *next;
-} EVAL_VARIABLE;
-
-typedef struct eval_expression {
- const char *source;
- const char *parsed_as;
-
- RRDCALC_STATUS *status;
- calculated_number *this;
- time_t *after;
- time_t *before;
-
- calculated_number result;
-
- int error;
- BUFFER *error_msg;
-
- // hidden EVAL_NODE *
- void *nodes;
-
- // custom data to be used for looking up variables
- struct rrdcalc *rrdcalc;
-} EVAL_EXPRESSION;
-
-#define EVAL_VALUE_INVALID 0
-#define EVAL_VALUE_NUMBER 1
-#define EVAL_VALUE_VARIABLE 2
-#define EVAL_VALUE_EXPRESSION 3
-
-// parsing and evaluation
-#define EVAL_ERROR_OK 0
-
-// parsing errors
-#define EVAL_ERROR_MISSING_CLOSE_SUBEXPRESSION 1
-#define EVAL_ERROR_UNKNOWN_OPERAND 2
-#define EVAL_ERROR_MISSING_OPERAND 3
-#define EVAL_ERROR_MISSING_OPERATOR 4
-#define EVAL_ERROR_REMAINING_GARBAGE 5
-#define EVAL_ERROR_IF_THEN_ELSE_MISSING_ELSE 6
-
-// evaluation errors
-#define EVAL_ERROR_INVALID_VALUE 101
-#define EVAL_ERROR_INVALID_NUMBER_OF_OPERANDS 102
-#define EVAL_ERROR_VALUE_IS_NAN 103
-#define EVAL_ERROR_VALUE_IS_INFINITE 104
-#define EVAL_ERROR_UNKNOWN_VARIABLE 105
-
-// parse the given string as an expression and return:
-// a pointer to an expression if it parsed OK
-// NULL in which case the pointer to error has the error code
-extern EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, int *error);
-
-// free all resources allocated for an expression
-extern void expression_free(EVAL_EXPRESSION *op);
-
-// convert an error code to a message
-extern const char *expression_strerror(int error);
-
-// evaluate an expression and return
-// 1 = OK, the result is in: expression->result
-// 2 = FAILED, the error message is in: buffer_tostring(expression->error_msg)
-extern int expression_evaluate(EVAL_EXPRESSION *expression);
-
-#endif //NETDATA_EVAL_H
diff --git a/src/freebsd_devstat.c b/src/freebsd_devstat.c
deleted file mode 100644
index ed7466ead..000000000
--- a/src/freebsd_devstat.c
+++ /dev/null
@@ -1,778 +0,0 @@
-#include "common.h"
-
-#include <sys/devicestat.h>
-
-struct disk {
- char *name;
- uint32_t hash;
- size_t len;
-
- // flags
- int configured;
- int enabled;
- int updated;
-
- int do_io;
- int do_ops;
- int do_qops;
- int do_util;
- int do_iotime;
- int do_await;
- int do_avagsz;
- int do_svctm;
-
-
- // data for differential charts
-
- struct prev_dstat {
- collected_number bytes_read;
- collected_number bytes_write;
- collected_number bytes_free;
- collected_number operations_read;
- collected_number operations_write;
- collected_number operations_other;
- collected_number operations_free;
- collected_number duration_read_ms;
- collected_number duration_write_ms;
- collected_number duration_other_ms;
- collected_number duration_free_ms;
- collected_number busy_time_ms;
- } prev_dstat;
-
- // charts and dimensions
-
- RRDSET *st_io;
- RRDDIM *rd_io_in;
- RRDDIM *rd_io_out;
- RRDDIM *rd_io_free;
-
- RRDSET *st_ops;
- RRDDIM *rd_ops_in;
- RRDDIM *rd_ops_out;
- RRDDIM *rd_ops_other;
- RRDDIM *rd_ops_free;
-
- RRDSET *st_qops;
- RRDDIM *rd_qops;
-
- RRDSET *st_util;
- RRDDIM *rd_util;
-
- RRDSET *st_iotime;
- RRDDIM *rd_iotime_in;
- RRDDIM *rd_iotime_out;
- RRDDIM *rd_iotime_other;
- RRDDIM *rd_iotime_free;
-
- RRDSET *st_await;
- RRDDIM *rd_await_in;
- RRDDIM *rd_await_out;
- RRDDIM *rd_await_other;
- RRDDIM *rd_await_free;
-
- RRDSET *st_avagsz;
- RRDDIM *rd_avagsz_in;
- RRDDIM *rd_avagsz_out;
- RRDDIM *rd_avagsz_free;
-
- RRDSET *st_svctm;
- RRDDIM *rd_svctm;
-
- struct disk *next;
-};
-
-static struct disk *disks_root = NULL, *disks_last_used = NULL;
-
-static size_t disks_added = 0, disks_found = 0;
-
-static void disk_free(struct disk *dm) {
- if (likely(dm->st_io))
- rrdset_is_obsolete(dm->st_io);
- if (likely(dm->st_ops))
- rrdset_is_obsolete(dm->st_ops);
- if (likely(dm->st_qops))
- rrdset_is_obsolete(dm->st_qops);
- if (likely(dm->st_util))
- rrdset_is_obsolete(dm->st_util);
- if (likely(dm->st_iotime))
- rrdset_is_obsolete(dm->st_iotime);
- if (likely(dm->st_await))
- rrdset_is_obsolete(dm->st_await);
- if (likely(dm->st_avagsz))
- rrdset_is_obsolete(dm->st_avagsz);
- if (likely(dm->st_svctm))
- rrdset_is_obsolete(dm->st_svctm);
-
- disks_added--;
- freez(dm->name);
- freez(dm);
-}
-
-static void disks_cleanup() {
- if (likely(disks_found == disks_added)) return;
-
- struct disk *dm = disks_root, *last = NULL;
- while(dm) {
- if (unlikely(!dm->updated)) {
- // info("Removing disk '%s', linked after '%s'", dm->name, last?last->name:"ROOT");
-
- if (disks_last_used == dm)
- disks_last_used = last;
-
- struct disk *t = dm;
-
- if (dm == disks_root || !last)
- disks_root = dm = dm->next;
-
- else
- last->next = dm = dm->next;
-
- t->next = NULL;
- disk_free(t);
- }
- else {
- last = dm;
- dm->updated = 0;
- dm = dm->next;
- }
- }
-}
-
-static struct disk *get_disk(const char *name) {
- struct disk *dm;
-
- uint32_t hash = simple_hash(name);
-
- // search it, from the last position to the end
- for(dm = disks_last_used ; dm ; dm = dm->next) {
- if (unlikely(hash == dm->hash && !strcmp(name, dm->name))) {
- disks_last_used = dm->next;
- return dm;
- }
- }
-
- // search it from the beginning to the last position we used
- for(dm = disks_root ; dm != disks_last_used ; dm = dm->next) {
- if (unlikely(hash == dm->hash && !strcmp(name, dm->name))) {
- disks_last_used = dm->next;
- return dm;
- }
- }
-
- // create a new one
- dm = callocz(1, sizeof(struct disk));
- dm->name = strdupz(name);
- dm->hash = simple_hash(dm->name);
- dm->len = strlen(dm->name);
- disks_added++;
-
- // link it to the end
- if (disks_root) {
- struct disk *e;
- for(e = disks_root; e->next ; e = e->next) ;
- e->next = dm;
- }
- else
- disks_root = dm;
-
- return dm;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kern.devstat
-
-int do_kern_devstat(int update_every, usec_t dt) {
-
-#define DELAULT_EXLUDED_DISKS ""
-#define CONFIG_SECTION_KERN_DEVSTAT "plugin:freebsd:kern.devstat"
-#define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
-
- static int enable_new_disks = -1;
- static int enable_pass_devices = -1, do_system_io = -1, do_io = -1, do_ops = -1, do_qops = -1, do_util = -1,
- do_iotime = -1, do_await = -1, do_avagsz = -1, do_svctm = -1;
- static SIMPLE_PATTERN *excluded_disks = NULL;
-
- if (unlikely(enable_new_disks == -1)) {
- enable_new_disks = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT,
- "enable new disks detected at runtime", CONFIG_BOOLEAN_AUTO);
-
- enable_pass_devices = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT,
- "performance metrics for pass devices", CONFIG_BOOLEAN_AUTO);
-
- do_system_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "total bandwidth for all disks",
- CONFIG_BOOLEAN_YES);
-
- do_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "bandwidth for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_ops = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "operations for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_qops = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "queued operations for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_util = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "utilization percentage for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "i/o time for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_await = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o time for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_avagsz = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o bandwidth for all disks",
- CONFIG_BOOLEAN_AUTO);
- do_svctm = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average service time for all disks",
- CONFIG_BOOLEAN_AUTO);
-
- excluded_disks = simple_pattern_create(
- config_get(CONFIG_SECTION_KERN_DEVSTAT, "disable by default disks matching", DELAULT_EXLUDED_DISKS)
- , NULL
- , SIMPLE_PATTERN_EXACT
- );
- }
-
- if (likely(do_system_io || do_io || do_ops || do_qops || do_util || do_iotime || do_await || do_avagsz || do_svctm)) {
- static int mib_numdevs[3] = {0, 0, 0};
- int numdevs;
- int common_error = 0;
-
- if (unlikely(GETSYSCTL_SIMPLE("kern.devstat.numdevs", mib_numdevs, numdevs))) {
- common_error = 1;
- } else {
- static int mib_devstat[3] = {0, 0, 0};
- static void *devstat_data = NULL;
- static int old_numdevs = 0;
-
- if (unlikely(numdevs != old_numdevs)) {
- devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) *
- numdevs); // there is generation number before devstat structures
- old_numdevs = numdevs;
- }
- if (unlikely(GETSYSCTL_WSIZE("kern.devstat.all", mib_devstat, devstat_data,
- sizeof(long) + sizeof(struct devstat) * numdevs))) {
- common_error = 1;
- } else {
- struct devstat *dstat;
- int i;
- collected_number total_disk_kbytes_read = 0;
- collected_number total_disk_kbytes_write = 0;
-
- disks_found = 0;
-
- dstat = devstat_data + sizeof(long); // skip generation number
-
- for (i = 0; i < numdevs; i++) {
- if (likely(do_system_io)) {
- if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) ||
- ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
- total_disk_kbytes_read += dstat[i].bytes[DEVSTAT_READ] / KILO_FACTOR;
- total_disk_kbytes_write += dstat[i].bytes[DEVSTAT_WRITE] / KILO_FACTOR;
- }
- }
-
- if (unlikely(!enable_pass_devices))
- if ((dstat[i].device_type & DEVSTAT_TYPE_PASS) == DEVSTAT_TYPE_PASS)
- continue;
-
- if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) ||
- ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
- char disk[DEVSTAT_NAME_LEN + MAX_INT_DIGITS + 1];
- struct cur_dstat {
- collected_number duration_read_ms;
- collected_number duration_write_ms;
- collected_number duration_other_ms;
- collected_number duration_free_ms;
- collected_number busy_time_ms;
- } cur_dstat;
-
- sprintf(disk, "%s%d", dstat[i].device_name, dstat[i].unit_number);
-
- struct disk *dm = get_disk(disk);
- dm->updated = 1;
- disks_found++;
-
- if(unlikely(!dm->configured)) {
- char var_name[4096 + 1];
-
- // this is the first time we see this disk
-
- // remember we configured it
- dm->configured = 1;
-
- dm->enabled = enable_new_disks;
-
- if (likely(dm->enabled))
- dm->enabled = !simple_pattern_matches(excluded_disks, disk);
-
- snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_KERN_DEVSTAT, disk);
- dm->enabled = config_get_boolean_ondemand(var_name, "enabled", dm->enabled);
-
- dm->do_io = config_get_boolean_ondemand(var_name, "bandwidth", do_io);
- dm->do_ops = config_get_boolean_ondemand(var_name, "operations", do_ops);
- dm->do_qops = config_get_boolean_ondemand(var_name, "queued operations", do_qops);
- dm->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", do_util);
- dm->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", do_iotime);
- dm->do_await = config_get_boolean_ondemand(var_name, "average completed i/o time",
- do_await);
- dm->do_avagsz = config_get_boolean_ondemand(var_name, "average completed i/o bandwidth",
- do_avagsz);
- dm->do_svctm = config_get_boolean_ondemand(var_name, "average service time", do_svctm);
-
- // initialise data for differential charts
-
- dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ];
- dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE];
- dm->prev_dstat.bytes_free = dstat[i].bytes[DEVSTAT_FREE];
- dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ];
- dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE];
- dm->prev_dstat.operations_other = dstat[i].operations[DEVSTAT_NO_DATA];
- dm->prev_dstat.operations_free = dstat[i].operations[DEVSTAT_FREE];
- dm->prev_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000
- + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
- dm->prev_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
- + dstat[i].duration[DEVSTAT_WRITE].frac * BINTIME_SCALE;
- dm->prev_dstat.duration_other_ms = dstat[i].duration[DEVSTAT_NO_DATA].sec * 1000
- + dstat[i].duration[DEVSTAT_NO_DATA].frac * BINTIME_SCALE;
- dm->prev_dstat.duration_free_ms = dstat[i].duration[DEVSTAT_FREE].sec * 1000
- + dstat[i].duration[DEVSTAT_FREE].frac * BINTIME_SCALE;
- dm->prev_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000
- + dstat[i].busy_time.frac * BINTIME_SCALE;
- }
-
- cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000
- + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
- cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
- + dstat[i].duration[DEVSTAT_WRITE].frac * BINTIME_SCALE;
- cur_dstat.duration_other_ms = dstat[i].duration[DEVSTAT_NO_DATA].sec * 1000
- + dstat[i].duration[DEVSTAT_NO_DATA].frac * BINTIME_SCALE;
- cur_dstat.duration_free_ms = dstat[i].duration[DEVSTAT_FREE].sec * 1000
- + dstat[i].duration[DEVSTAT_FREE].frac * BINTIME_SCALE;
-
- cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
-
- // --------------------------------------------------------------------
-
- if(dm->do_io == CONFIG_BOOLEAN_YES || (dm->do_io == CONFIG_BOOLEAN_AUTO &&
- (dstat[i].bytes[DEVSTAT_READ] ||
- dstat[i].bytes[DEVSTAT_WRITE] ||
- dstat[i].bytes[DEVSTAT_FREE]))) {
- if (unlikely(!dm->st_io)) {
- dm->st_io = rrdset_create_localhost("disk",
- disk,
- NULL,
- disk,
- "disk.io",
- "Disk I/O Bandwidth",
- "kilobytes/s",
- "freebsd",
- "devstat",
- 2000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- dm->rd_io_in = rrddim_add(dm->st_io, "reads", NULL, 1, KILO_FACTOR,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_io_out = rrddim_add(dm->st_io, "writes", NULL, -1, KILO_FACTOR,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_io_free = rrddim_add(dm->st_io, "frees", NULL, -1, KILO_FACTOR,
- RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(dm->st_io);
-
- rrddim_set_by_pointer(dm->st_io, dm->rd_io_in, dstat[i].bytes[DEVSTAT_READ]);
- rrddim_set_by_pointer(dm->st_io, dm->rd_io_out, dstat[i].bytes[DEVSTAT_WRITE]);
- rrddim_set_by_pointer(dm->st_io, dm->rd_io_free, dstat[i].bytes[DEVSTAT_FREE]);
- rrdset_done(dm->st_io);
- }
-
- // --------------------------------------------------------------------
-
- if(dm->do_ops == CONFIG_BOOLEAN_YES || (dm->do_ops == CONFIG_BOOLEAN_AUTO &&
- (dstat[i].operations[DEVSTAT_READ] ||
- dstat[i].operations[DEVSTAT_WRITE] ||
- dstat[i].operations[DEVSTAT_NO_DATA] ||
- dstat[i].operations[DEVSTAT_FREE]))) {
- if (unlikely(!dm->st_ops)) {
- dm->st_ops = rrdset_create_localhost("disk_ops",
- disk,
- NULL,
- disk,
- "disk.ops",
- "Disk Completed I/O Operations",
- "operations/s",
- "freebsd",
- "devstat",
- 2001,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(dm->st_ops, RRDSET_FLAG_DETAIL);
-
- dm->rd_ops_in = rrddim_add(dm->st_ops, "reads", NULL, 1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_ops_out = rrddim_add(dm->st_ops, "writes", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_ops_other = rrddim_add(dm->st_ops, "other", NULL, 1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_ops_free = rrddim_add(dm->st_ops, "frees", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(dm->st_ops);
-
- rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_in, dstat[i].operations[DEVSTAT_READ]);
- rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_out, dstat[i].operations[DEVSTAT_WRITE]);
- rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_other, dstat[i].operations[DEVSTAT_NO_DATA]);
- rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_free, dstat[i].operations[DEVSTAT_FREE]);
- rrdset_done(dm->st_ops);
- }
-
- // --------------------------------------------------------------------
-
- if(dm->do_qops == CONFIG_BOOLEAN_YES || (dm->do_qops == CONFIG_BOOLEAN_AUTO &&
- (dstat[i].start_count || dstat[i].end_count))) {
- if (unlikely(!dm->st_qops)) {
- dm->st_qops = rrdset_create_localhost("disk_qops",
- disk,
- NULL,
- disk,
- "disk.qops",
- "Disk Current I/O Operations",
- "operations",
- "freebsd",
- "devstat",
- 2002,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(dm->st_qops, RRDSET_FLAG_DETAIL);
-
- dm->rd_qops = rrddim_add(dm->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(dm->st_qops);
-
- rrddim_set_by_pointer(dm->st_qops, dm->rd_qops, dstat[i].start_count - dstat[i].end_count);
- rrdset_done(dm->st_qops);
- }
-
- // --------------------------------------------------------------------
-
- if(dm->do_util == CONFIG_BOOLEAN_YES || (dm->do_util == CONFIG_BOOLEAN_AUTO &&
- cur_dstat.busy_time_ms)) {
- if (unlikely(!dm->st_util)) {
- dm->st_util = rrdset_create_localhost("disk_util",
- disk,
- NULL,
- disk,
- "disk.util",
- "Disk Utilization Time",
- "% of time working",
- "freebsd",
- "devstat",
- 2004,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(dm->st_util, RRDSET_FLAG_DETAIL);
-
- dm->rd_util = rrddim_add(dm->st_util, "utilization", NULL, 1, 10,
- RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(dm->st_util);
-
- rrddim_set_by_pointer(dm->st_util, dm->rd_util, cur_dstat.busy_time_ms);
- rrdset_done(dm->st_util);
- }
-
- // --------------------------------------------------------------------
-
- if(dm->do_iotime == CONFIG_BOOLEAN_YES || (dm->do_iotime == CONFIG_BOOLEAN_AUTO &&
- (cur_dstat.duration_read_ms ||
- cur_dstat.duration_write_ms ||
- cur_dstat.duration_other_ms ||
- cur_dstat.duration_free_ms))) {
- if (unlikely(!dm->st_iotime)) {
- dm->st_iotime = rrdset_create_localhost("disk_iotime",
- disk,
- NULL,
- disk,
- "disk.iotime",
- "Disk Total I/O Time",
- "milliseconds/s",
- "freebsd",
- "devstat",
- 2022,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(dm->st_iotime, RRDSET_FLAG_DETAIL);
-
- dm->rd_iotime_in = rrddim_add(dm->st_iotime, "reads", NULL, 1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_iotime_out = rrddim_add(dm->st_iotime, "writes", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_iotime_other = rrddim_add(dm->st_iotime, "other", NULL, 1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- dm->rd_iotime_free = rrddim_add(dm->st_iotime, "frees", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(dm->st_iotime);
-
- rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_in, cur_dstat.duration_read_ms);
- rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_out, cur_dstat.duration_write_ms);
- rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_other, cur_dstat.duration_other_ms);
- rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_free, cur_dstat.duration_free_ms);
- rrdset_done(dm->st_iotime);
- }
-
- // --------------------------------------------------------------------
- // calculate differential charts
- // only if this is not the first time we run
-
- if (likely(dt)) {
-
- // --------------------------------------------------------------------
-
- if(dm->do_await == CONFIG_BOOLEAN_YES || (dm->do_await == CONFIG_BOOLEAN_AUTO &&
- (dstat[i].operations[DEVSTAT_READ] ||
- dstat[i].operations[DEVSTAT_WRITE] ||
- dstat[i].operations[DEVSTAT_NO_DATA] ||
- dstat[i].operations[DEVSTAT_FREE]))) {
- if (unlikely(!dm->st_await)) {
- dm->st_await = rrdset_create_localhost("disk_await",
- disk,
- NULL,
- disk,
- "disk.await",
- "Average Completed I/O Operation Time",
- "ms per operation",
- "freebsd",
- "devstat",
- 2005,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(dm->st_await, RRDSET_FLAG_DETAIL);
-
- dm->rd_await_in = rrddim_add(dm->st_await, "reads", NULL, 1, 1,
- RRD_ALGORITHM_ABSOLUTE);
- dm->rd_await_out = rrddim_add(dm->st_await, "writes", NULL, -1, 1,
- RRD_ALGORITHM_ABSOLUTE);
- dm->rd_await_other = rrddim_add(dm->st_await, "other", NULL, 1, 1,
- RRD_ALGORITHM_ABSOLUTE);
- dm->rd_await_free = rrddim_add(dm->st_await, "frees", NULL, -1, 1,
- RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(dm->st_await);
-
- rrddim_set_by_pointer(dm->st_await, dm->rd_await_in,
- (dstat[i].operations[DEVSTAT_READ] -
- dm->prev_dstat.operations_read) ?
- (cur_dstat.duration_read_ms - dm->prev_dstat.duration_read_ms) /
- (dstat[i].operations[DEVSTAT_READ] -
- dm->prev_dstat.operations_read) :
- 0);
- rrddim_set_by_pointer(dm->st_await, dm->rd_await_out,
- (dstat[i].operations[DEVSTAT_WRITE] -
- dm->prev_dstat.operations_write) ?
- (cur_dstat.duration_write_ms - dm->prev_dstat.duration_write_ms) /
- (dstat[i].operations[DEVSTAT_WRITE] -
- dm->prev_dstat.operations_write) :
- 0);
- rrddim_set_by_pointer(dm->st_await, dm->rd_await_other,
- (dstat[i].operations[DEVSTAT_NO_DATA] -
- dm->prev_dstat.operations_other) ?
- (cur_dstat.duration_other_ms - dm->prev_dstat.duration_other_ms) /
- (dstat[i].operations[DEVSTAT_NO_DATA] -
- dm->prev_dstat.operations_other) :
- 0);
- rrddim_set_by_pointer(dm->st_await, dm->rd_await_free,
- (dstat[i].operations[DEVSTAT_FREE] -
- dm->prev_dstat.operations_free) ?
- (cur_dstat.duration_free_ms - dm->prev_dstat.duration_free_ms) /
- (dstat[i].operations[DEVSTAT_FREE] -
- dm->prev_dstat.operations_free) :
- 0);
- rrdset_done(dm->st_await);
- }
-
- // --------------------------------------------------------------------
-
- if(dm->do_avagsz == CONFIG_BOOLEAN_YES || (dm->do_avagsz == CONFIG_BOOLEAN_AUTO &&
- (dstat[i].operations[DEVSTAT_READ] ||
- dstat[i].operations[DEVSTAT_WRITE] ||
- dstat[i].operations[DEVSTAT_FREE]))) {
- if (unlikely(!dm->st_avagsz)) {
- dm->st_avagsz = rrdset_create_localhost("disk_avgsz",
- disk,
- NULL,
- disk,
- "disk.avgsz",
- "Average Completed I/O Operation Bandwidth",
- "kilobytes per operation",
- "freebsd",
- "devstat",
- 2006,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(dm->st_avagsz, RRDSET_FLAG_DETAIL);
-
- dm->rd_avagsz_in = rrddim_add(dm->st_avagsz, "reads", NULL, 1, KILO_FACTOR,
- RRD_ALGORITHM_ABSOLUTE);
- dm->rd_avagsz_out = rrddim_add(dm->st_avagsz, "writes", NULL, -1, KILO_FACTOR,
- RRD_ALGORITHM_ABSOLUTE);
- dm->rd_avagsz_free = rrddim_add(dm->st_avagsz, "frees", NULL, -1, KILO_FACTOR,
- RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(dm->st_avagsz);
-
- rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_in,
- (dstat[i].operations[DEVSTAT_READ] -
- dm->prev_dstat.operations_read) ?
- (dstat[i].bytes[DEVSTAT_READ] - dm->prev_dstat.bytes_read) /
- (dstat[i].operations[DEVSTAT_READ] -
- dm->prev_dstat.operations_read) :
- 0);
- rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_out,
- (dstat[i].operations[DEVSTAT_WRITE] -
- dm->prev_dstat.operations_write) ?
- (dstat[i].bytes[DEVSTAT_WRITE] - dm->prev_dstat.bytes_write) /
- (dstat[i].operations[DEVSTAT_WRITE] -
- dm->prev_dstat.operations_write) :
- 0);
- rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_free,
- (dstat[i].operations[DEVSTAT_FREE] -
- dm->prev_dstat.operations_free) ?
- (dstat[i].bytes[DEVSTAT_FREE] - dm->prev_dstat.bytes_free) /
- (dstat[i].operations[DEVSTAT_FREE] -
- dm->prev_dstat.operations_free) :
- 0);
- rrdset_done(dm->st_avagsz);
- }
-
- // --------------------------------------------------------------------
-
- if(dm->do_svctm == CONFIG_BOOLEAN_YES || (dm->do_svctm == CONFIG_BOOLEAN_AUTO &&
- (dstat[i].operations[DEVSTAT_READ] ||
- dstat[i].operations[DEVSTAT_WRITE] ||
- dstat[i].operations[DEVSTAT_NO_DATA] ||
- dstat[i].operations[DEVSTAT_FREE]))) {
- if (unlikely(!dm->st_svctm)) {
- dm->st_svctm = rrdset_create_localhost("disk_svctm",
- disk,
- NULL,
- disk,
- "disk.svctm",
- "Average Service Time",
- "ms per operation",
- "freebsd",
- "devstat",
- 2007,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(dm->st_svctm, RRDSET_FLAG_DETAIL);
-
- dm->rd_svctm = rrddim_add(dm->st_svctm, "svctm", NULL, 1, 1,
- RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(dm->st_svctm);
-
- rrddim_set_by_pointer(dm->st_svctm, dm->rd_svctm,
- ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
- (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write) +
- (dstat[i].operations[DEVSTAT_NO_DATA] - dm->prev_dstat.operations_other) +
- (dstat[i].operations[DEVSTAT_FREE] - dm->prev_dstat.operations_free)) ?
- (cur_dstat.busy_time_ms - dm->prev_dstat.busy_time_ms) /
- ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
- (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write) +
- (dstat[i].operations[DEVSTAT_NO_DATA] - dm->prev_dstat.operations_other) +
- (dstat[i].operations[DEVSTAT_FREE] - dm->prev_dstat.operations_free)) :
- 0);
- rrdset_done(dm->st_svctm);
- }
-
- // --------------------------------------------------------------------
-
- dm->prev_dstat.bytes_read = dstat[i].bytes[DEVSTAT_READ];
- dm->prev_dstat.bytes_write = dstat[i].bytes[DEVSTAT_WRITE];
- dm->prev_dstat.bytes_free = dstat[i].bytes[DEVSTAT_FREE];
- dm->prev_dstat.operations_read = dstat[i].operations[DEVSTAT_READ];
- dm->prev_dstat.operations_write = dstat[i].operations[DEVSTAT_WRITE];
- dm->prev_dstat.operations_other = dstat[i].operations[DEVSTAT_NO_DATA];
- dm->prev_dstat.operations_free = dstat[i].operations[DEVSTAT_FREE];
- dm->prev_dstat.duration_read_ms = cur_dstat.duration_read_ms;
- dm->prev_dstat.duration_write_ms = cur_dstat.duration_write_ms;
- dm->prev_dstat.duration_other_ms = cur_dstat.duration_other_ms;
- dm->prev_dstat.duration_free_ms = cur_dstat.duration_free_ms;
- dm->prev_dstat.busy_time_ms = cur_dstat.busy_time_ms;
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_system_io)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost("system",
- "io",
- NULL,
- "disk",
- NULL,
- "Disk I/O",
- "kilobytes/s",
- "freebsd",
- "devstat",
- 150,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, total_disk_kbytes_read);
- rrddim_set_by_pointer(st, rd_out, total_disk_kbytes_write);
- rrdset_done(st);
- }
- }
- }
- if (unlikely(common_error)) {
- do_system_io = 0;
- error("DISABLED: system.io chart");
- do_io = 0;
- error("DISABLED: disk.* charts");
- do_ops = 0;
- error("DISABLED: disk_ops.* charts");
- do_qops = 0;
- error("DISABLED: disk_qops.* charts");
- do_util = 0;
- error("DISABLED: disk_util.* charts");
- do_iotime = 0;
- error("DISABLED: disk_iotime.* charts");
- do_await = 0;
- error("DISABLED: disk_await.* charts");
- do_avagsz = 0;
- error("DISABLED: disk_avgsz.* charts");
- do_svctm = 0;
- error("DISABLED: disk_svctm.* charts");
- error("DISABLED: kern.devstat module");
- return 1;
- }
- } else {
- error("DISABLED: kern.devstat module");
- return 1;
- }
-
- disks_cleanup();
-
- return 0;
-}
diff --git a/src/freebsd_getifaddrs.c b/src/freebsd_getifaddrs.c
deleted file mode 100644
index 73f8f1824..000000000
--- a/src/freebsd_getifaddrs.c
+++ /dev/null
@@ -1,506 +0,0 @@
-#include "common.h"
-
-#include <ifaddrs.h>
-
-struct cgroup_network_interface {
- char *name;
- uint32_t hash;
- size_t len;
-
- // flags
- int configured;
- int enabled;
- int updated;
-
- int do_bandwidth;
- int do_packets;
- int do_errors;
- int do_drops;
- int do_events;
-
- // charts and dimensions
-
- RRDSET *st_bandwidth;
- RRDDIM *rd_bandwidth_in;
- RRDDIM *rd_bandwidth_out;
-
- RRDSET *st_packets;
- RRDDIM *rd_packets_in;
- RRDDIM *rd_packets_out;
- RRDDIM *rd_packets_m_in;
- RRDDIM *rd_packets_m_out;
-
- RRDSET *st_errors;
- RRDDIM *rd_errors_in;
- RRDDIM *rd_errors_out;
-
- RRDSET *st_drops;
- RRDDIM *rd_drops_in;
- RRDDIM *rd_drops_out;
-
- RRDSET *st_events;
- RRDDIM *rd_events_coll;
-
- struct cgroup_network_interface *next;
-};
-
-static struct cgroup_network_interface *network_interfaces_root = NULL, *network_interfaces_last_used = NULL;
-
-static size_t network_interfaces_added = 0, network_interfaces_found = 0;
-
-static void network_interface_free(struct cgroup_network_interface *ifm) {
- if (likely(ifm->st_bandwidth))
- rrdset_is_obsolete(ifm->st_bandwidth);
- if (likely(ifm->st_packets))
- rrdset_is_obsolete(ifm->st_packets);
- if (likely(ifm->st_errors))
- rrdset_is_obsolete(ifm->st_errors);
- if (likely(ifm->st_drops))
- rrdset_is_obsolete(ifm->st_drops);
- if (likely(ifm->st_events))
- rrdset_is_obsolete(ifm->st_events);
-
- network_interfaces_added--;
- freez(ifm->name);
- freez(ifm);
-}
-
-static void network_interfaces_cleanup() {
- if (likely(network_interfaces_found == network_interfaces_added)) return;
-
- struct cgroup_network_interface *ifm = network_interfaces_root, *last = NULL;
- while(ifm) {
- if (unlikely(!ifm->updated)) {
- // info("Removing network interface '%s', linked after '%s'", ifm->name, last?last->name:"ROOT");
-
- if (network_interfaces_last_used == ifm)
- network_interfaces_last_used = last;
-
- struct cgroup_network_interface *t = ifm;
-
- if (ifm == network_interfaces_root || !last)
- network_interfaces_root = ifm = ifm->next;
-
- else
- last->next = ifm = ifm->next;
-
- t->next = NULL;
- network_interface_free(t);
- }
- else {
- last = ifm;
- ifm->updated = 0;
- ifm = ifm->next;
- }
- }
-}
-
-static struct cgroup_network_interface *get_network_interface(const char *name) {
- struct cgroup_network_interface *ifm;
-
- uint32_t hash = simple_hash(name);
-
- // search it, from the last position to the end
- for(ifm = network_interfaces_last_used ; ifm ; ifm = ifm->next) {
- if (unlikely(hash == ifm->hash && !strcmp(name, ifm->name))) {
- network_interfaces_last_used = ifm->next;
- return ifm;
- }
- }
-
- // search it from the beginning to the last position we used
- for(ifm = network_interfaces_root ; ifm != network_interfaces_last_used ; ifm = ifm->next) {
- if (unlikely(hash == ifm->hash && !strcmp(name, ifm->name))) {
- network_interfaces_last_used = ifm->next;
- return ifm;
- }
- }
-
- // create a new one
- ifm = callocz(1, sizeof(struct cgroup_network_interface));
- ifm->name = strdupz(name);
- ifm->hash = simple_hash(ifm->name);
- ifm->len = strlen(ifm->name);
- network_interfaces_added++;
-
- // link it to the end
- if (network_interfaces_root) {
- struct cgroup_network_interface *e;
- for(e = network_interfaces_root; e->next ; e = e->next) ;
- e->next = ifm;
- }
- else
- network_interfaces_root = ifm;
-
- return ifm;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// getifaddrs
-
-int do_getifaddrs(int update_every, usec_t dt) {
- (void)dt;
-
-#define DELAULT_EXLUDED_INTERFACES "lo*"
-#define CONFIG_SECTION_GETIFADDRS "plugin:freebsd:getifaddrs"
-
- static int enable_new_interfaces = -1;
- static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1,
- do_errors = -1, do_drops = -1, do_events = -1;
- static SIMPLE_PATTERN *excluded_interfaces = NULL;
-
- if (unlikely(enable_new_interfaces == -1)) {
- enable_new_interfaces = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS,
- "enable new interfaces detected at runtime",
- CONFIG_BOOLEAN_AUTO);
-
- do_bandwidth_ipv4 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv4 interfaces",
- CONFIG_BOOLEAN_AUTO);
- do_bandwidth_ipv6 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv6 interfaces",
- CONFIG_BOOLEAN_AUTO);
- do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "bandwidth for all interfaces",
- CONFIG_BOOLEAN_AUTO);
- do_packets = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "packets for all interfaces",
- CONFIG_BOOLEAN_AUTO);
- do_errors = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "errors for all interfaces",
- CONFIG_BOOLEAN_AUTO);
- do_drops = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "drops for all interfaces",
- CONFIG_BOOLEAN_AUTO);
- do_events = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "collisions for all interfaces",
- CONFIG_BOOLEAN_AUTO);
-
- excluded_interfaces = simple_pattern_create(
- config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching", DELAULT_EXLUDED_INTERFACES)
- , NULL
- , SIMPLE_PATTERN_EXACT
- );
- }
-
- if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors ||
- do_drops || do_events)) {
- struct ifaddrs *ifap;
-
- if (unlikely(getifaddrs(&ifap))) {
- error("FREEBSD: getifaddrs() failed");
- do_bandwidth_ipv4 = 0;
- error("DISABLED: system.ipv4 chart");
- do_bandwidth_ipv6 = 0;
- error("DISABLED: system.ipv6 chart");
- do_bandwidth = 0;
- error("DISABLED: net.* charts");
- do_packets = 0;
- error("DISABLED: net_packets.* charts");
- do_errors = 0;
- error("DISABLED: net_errors.* charts");
- do_drops = 0;
- error("DISABLED: net_drops.* charts");
- do_events = 0;
- error("DISABLED: net_events.* charts");
- error("DISABLED: getifaddrs module");
- return 1;
- } else {
-#define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
- struct ifaddrs *ifa;
- struct iftot {
- u_long ift_ibytes;
- u_long ift_obytes;
- } iftot = {0, 0};
-
- // --------------------------------------------------------------------
-
- if (likely(do_bandwidth_ipv4)) {
- iftot.ift_ibytes = iftot.ift_obytes = 0;
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != AF_INET)
- continue;
- iftot.ift_ibytes += IFA_DATA(ibytes);
- iftot.ift_obytes += IFA_DATA(obytes);
- }
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost("system",
- "ipv4",
- NULL,
- "network",
- NULL,
- "IPv4 Bandwidth",
- "kilobits/s",
- "freebsd",
- "getifaddrs",
- 500,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes);
- rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_bandwidth_ipv6)) {
- iftot.ift_ibytes = iftot.ift_obytes = 0;
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != AF_INET6)
- continue;
- iftot.ift_ibytes += IFA_DATA(ibytes);
- iftot.ift_obytes += IFA_DATA(obytes);
- }
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost("system",
- "ipv6",
- NULL,
- "network",
- NULL,
- "IPv6 Bandwidth",
- "kilobits/s",
- "freebsd",
- "getifaddrs",
- 500,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes);
- rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- network_interfaces_found = 0;
-
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
-
- struct cgroup_network_interface *ifm = get_network_interface(ifa->ifa_name);
- ifm->updated = 1;
- network_interfaces_found++;
-
- if (unlikely(!ifm->configured)) {
- char var_name[4096 + 1];
-
- // this is the first time we see this network interface
-
- // remember we configured it
- ifm->configured = 1;
-
- ifm->enabled = enable_new_interfaces;
-
- if (likely(ifm->enabled))
- ifm->enabled = !simple_pattern_matches(excluded_interfaces, ifa->ifa_name);
-
- snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETIFADDRS, ifa->ifa_name);
- ifm->enabled = config_get_boolean_ondemand(var_name, "enabled", ifm->enabled);
-
- if (unlikely(ifm->enabled == CONFIG_BOOLEAN_NO))
- continue;
-
- ifm->do_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", do_bandwidth);
- ifm->do_packets = config_get_boolean_ondemand(var_name, "packets", do_packets);
- ifm->do_errors = config_get_boolean_ondemand(var_name, "errors", do_errors);
- ifm->do_drops = config_get_boolean_ondemand(var_name, "drops", do_drops);
- ifm->do_events = config_get_boolean_ondemand(var_name, "events", do_events);
- }
-
- if (unlikely(!ifm->enabled))
- continue;
-
- // --------------------------------------------------------------------
-
- if (ifm->do_bandwidth == CONFIG_BOOLEAN_YES || (ifm->do_bandwidth == CONFIG_BOOLEAN_AUTO &&
- (IFA_DATA(ibytes) || IFA_DATA(obytes)))) {
- if (unlikely(!ifm->st_bandwidth)) {
- ifm->st_bandwidth = rrdset_create_localhost("net",
- ifa->ifa_name,
- NULL,
- ifa->ifa_name,
- "net.net",
- "Bandwidth",
- "kilobits/s",
- "freebsd",
- "getifaddrs",
- 7000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- ifm->rd_bandwidth_in = rrddim_add(ifm->st_bandwidth, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- ifm->rd_bandwidth_out = rrddim_add(ifm->st_bandwidth, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(ifm->st_bandwidth);
-
- rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_in, IFA_DATA(ibytes));
- rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_out, IFA_DATA(obytes));
- rrdset_done(ifm->st_bandwidth);
- }
-
- // --------------------------------------------------------------------
-
- if (ifm->do_packets == CONFIG_BOOLEAN_YES || (ifm->do_packets == CONFIG_BOOLEAN_AUTO &&
- (IFA_DATA(ipackets) || IFA_DATA(opackets) || IFA_DATA(imcasts) || IFA_DATA(omcasts)))) {
- if (unlikely(!ifm->st_packets)) {
- ifm->st_packets = rrdset_create_localhost("net_packets",
- ifa->ifa_name,
- NULL,
- ifa->ifa_name,
- "net.packets",
- "Packets",
- "packets/s",
- "freebsd",
- "getifaddrs",
- 7001,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(ifm->st_packets, RRDSET_FLAG_DETAIL);
-
- ifm->rd_packets_in = rrddim_add(ifm->st_packets, "received", NULL, 1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- ifm->rd_packets_out = rrddim_add(ifm->st_packets, "sent", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- ifm->rd_packets_m_in = rrddim_add(ifm->st_packets, "multicast_received", NULL, 1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- ifm->rd_packets_m_out = rrddim_add(ifm->st_packets, "multicast_sent", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(ifm->st_packets);
-
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_in, IFA_DATA(ipackets));
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_out, IFA_DATA(opackets));
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_in, IFA_DATA(imcasts));
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_out, IFA_DATA(omcasts));
- rrdset_done(ifm->st_packets);
- }
-
- // --------------------------------------------------------------------
-
- if (ifm->do_errors == CONFIG_BOOLEAN_YES || (ifm->do_errors == CONFIG_BOOLEAN_AUTO &&
- (IFA_DATA(ierrors) || IFA_DATA(oerrors)))) {
- if (unlikely(!ifm->st_errors)) {
- ifm->st_errors = rrdset_create_localhost("net_errors",
- ifa->ifa_name,
- NULL,
- ifa->ifa_name,
- "net.errors",
- "Interface Errors",
- "errors/s",
- "freebsd",
- "getifaddrs",
- 7002,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(ifm->st_errors, RRDSET_FLAG_DETAIL);
-
- ifm->rd_errors_in = rrddim_add(ifm->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- ifm->rd_errors_out = rrddim_add(ifm->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(ifm->st_errors);
-
- rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_in, IFA_DATA(ierrors));
- rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_out, IFA_DATA(oerrors));
- rrdset_done(ifm->st_errors);
- }
- // --------------------------------------------------------------------
-
- if (ifm->do_drops == CONFIG_BOOLEAN_YES || (ifm->do_drops == CONFIG_BOOLEAN_AUTO &&
- (IFA_DATA(iqdrops)
- #if __FreeBSD__ >= 11
- || IFA_DATA(oqdrops)
-#endif
- ))) {
- if (unlikely(!ifm->st_drops)) {
- ifm->st_drops = rrdset_create_localhost("net_drops",
- ifa->ifa_name,
- NULL,
- ifa->ifa_name,
- "net.drops",
- "Interface Drops",
- "drops/s",
- "freebsd",
- "getifaddrs",
- 7003,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(ifm->st_drops, RRDSET_FLAG_DETAIL);
-
- ifm->rd_drops_in = rrddim_add(ifm->st_drops, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#if __FreeBSD__ >= 11
- ifm->rd_drops_out = rrddim_add(ifm->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-#endif
- } else
- rrdset_next(ifm->st_drops);
-
- rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_in, IFA_DATA(iqdrops));
-#if __FreeBSD__ >= 11
- rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_out, IFA_DATA(oqdrops));
-#endif
- rrdset_done(ifm->st_drops);
- }
-
- // --------------------------------------------------------------------
-
- if (ifm->do_events == CONFIG_BOOLEAN_YES || (ifm->do_events == CONFIG_BOOLEAN_AUTO &&
- IFA_DATA(collisions))) {
- if (unlikely(!ifm->st_events)) {
- ifm->st_events = rrdset_create_localhost("net_events",
- ifa->ifa_name,
- NULL,
- ifa->ifa_name,
- "net.events",
- "Network Interface Events",
- "events/s",
- "freebsd",
- "getifaddrs",
- 7006,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(ifm->st_events, RRDSET_FLAG_DETAIL);
-
- ifm->rd_events_coll = rrddim_add(ifm->st_events, "collisions", NULL, -1, 1,
- RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(ifm->st_events);
-
- rrddim_set_by_pointer(ifm->st_events, ifm->rd_events_coll, IFA_DATA(collisions));
- rrdset_done(ifm->st_events);
- }
- }
-
- freeifaddrs(ifap);
- }
- } else {
- error("DISABLED: getifaddrs module");
- return 1;
- }
-
- network_interfaces_cleanup();
-
- return 0;
-}
diff --git a/src/freebsd_getmntinfo.c b/src/freebsd_getmntinfo.c
deleted file mode 100644
index ea82b9fd1..000000000
--- a/src/freebsd_getmntinfo.c
+++ /dev/null
@@ -1,299 +0,0 @@
-#include "common.h"
-
-#include <sys/mount.h>
-
-struct mount_point {
- char *name;
- uint32_t hash;
- size_t len;
-
- // flags
- int configured;
- int enabled;
- int updated;
-
- int do_space;
- int do_inodes;
-
- size_t collected; // the number of times this has been collected
-
- // charts and dimensions
-
- RRDSET *st_space;
- RRDDIM *rd_space_used;
- RRDDIM *rd_space_avail;
- RRDDIM *rd_space_reserved;
-
- RRDSET *st_inodes;
- RRDDIM *rd_inodes_used;
- RRDDIM *rd_inodes_avail;
-
- struct mount_point *next;
-};
-
-static struct mount_point *mount_points_root = NULL, *mount_points_last_used = NULL;
-
-static size_t mount_points_added = 0, mount_points_found = 0;
-
-static void mount_point_free(struct mount_point *m) {
- if (likely(m->st_space))
- rrdset_is_obsolete(m->st_space);
- if (likely(m->st_inodes))
- rrdset_is_obsolete(m->st_inodes);
-
- mount_points_added--;
- freez(m->name);
- freez(m);
-}
-
-static void mount_points_cleanup() {
- if (likely(mount_points_found == mount_points_added)) return;
-
- struct mount_point *m = mount_points_root, *last = NULL;
- while(m) {
- if (unlikely(!m->updated)) {
- // info("Removing mount point '%s', linked after '%s'", m->name, last?last->name:"ROOT");
-
- if (mount_points_last_used == m)
- mount_points_last_used = last;
-
- struct mount_point *t = m;
-
- if (m == mount_points_root || !last)
- mount_points_root = m = m->next;
-
- else
- last->next = m = m->next;
-
- t->next = NULL;
- mount_point_free(t);
- }
- else {
- last = m;
- m->updated = 0;
- m = m->next;
- }
- }
-}
-
-static struct mount_point *get_mount_point(const char *name) {
- struct mount_point *m;
-
- uint32_t hash = simple_hash(name);
-
- // search it, from the last position to the end
- for(m = mount_points_last_used ; m ; m = m->next) {
- if (unlikely(hash == m->hash && !strcmp(name, m->name))) {
- mount_points_last_used = m->next;
- return m;
- }
- }
-
- // search it from the beginning to the last position we used
- for(m = mount_points_root ; m != mount_points_last_used ; m = m->next) {
- if (unlikely(hash == m->hash && !strcmp(name, m->name))) {
- mount_points_last_used = m->next;
- return m;
- }
- }
-
- // create a new one
- m = callocz(1, sizeof(struct mount_point));
- m->name = strdupz(name);
- m->hash = simple_hash(m->name);
- m->len = strlen(m->name);
- mount_points_added++;
-
- // link it to the end
- if (mount_points_root) {
- struct mount_point *e;
- for(e = mount_points_root; e->next ; e = e->next) ;
- e->next = m;
- }
- else
- mount_points_root = m;
-
- return m;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// getmntinfo
-
-int do_getmntinfo(int update_every, usec_t dt) {
- (void)dt;
-
-#define DELAULT_EXCLUDED_PATHS "/proc/*"
-// taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
-#define DEFAULT_EXCLUDED_FILESYSTEMS "autofs procfs subfs devfs none"
-#define CONFIG_SECTION_GETMNTINFO "plugin:freebsd:getmntinfo"
-
- static int enable_new_mount_points = -1;
- static int do_space = -1, do_inodes = -1;
- static SIMPLE_PATTERN *excluded_mountpoints = NULL;
- static SIMPLE_PATTERN *excluded_filesystems = NULL;
-
- if (unlikely(enable_new_mount_points == -1)) {
- enable_new_mount_points = config_get_boolean_ondemand(CONFIG_SECTION_GETMNTINFO,
- "enable new mount points detected at runtime",
- CONFIG_BOOLEAN_AUTO);
-
- do_space = config_get_boolean_ondemand(CONFIG_SECTION_GETMNTINFO, "space usage for all disks", CONFIG_BOOLEAN_AUTO);
- do_inodes = config_get_boolean_ondemand(CONFIG_SECTION_GETMNTINFO, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO);
-
- excluded_mountpoints = simple_pattern_create(
- config_get(CONFIG_SECTION_GETMNTINFO, "exclude space metrics on paths",
- DELAULT_EXCLUDED_PATHS)
- , NULL
- , SIMPLE_PATTERN_EXACT
- );
-
- excluded_filesystems = simple_pattern_create(
- config_get(CONFIG_SECTION_GETMNTINFO, "exclude space metrics on filesystems",
- DEFAULT_EXCLUDED_FILESYSTEMS)
- , NULL
- , SIMPLE_PATTERN_EXACT
- );
- }
-
- if (likely(do_space || do_inodes)) {
- struct statfs *mntbuf;
- int mntsize;
-
- // there is no mount info in sysctl MIBs
- if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
- error("FREEBSD: getmntinfo() failed");
- do_space = 0;
- error("DISABLED: disk_space.* charts");
- do_inodes = 0;
- error("DISABLED: disk_inodes.* charts");
- error("DISABLED: getmntinfo module");
- return 1;
- } else {
- int i;
-
- mount_points_found = 0;
-
- for (i = 0; i < mntsize; i++) {
- char title[4096 + 1];
-
- struct mount_point *m = get_mount_point(mntbuf[i].f_mntonname);
- m->updated = 1;
- mount_points_found++;
-
- if (unlikely(!m->configured)) {
- char var_name[4096 + 1];
-
- // this is the first time we see this filesystem
-
- // remember we configured it
- m->configured = 1;
-
- m->enabled = enable_new_mount_points;
-
- if (likely(m->enabled))
- m->enabled = !(simple_pattern_matches(excluded_mountpoints, mntbuf[i].f_mntonname)
- || simple_pattern_matches(excluded_filesystems, mntbuf[i].f_fstypename));
-
- snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETMNTINFO, mntbuf[i].f_mntonname);
- m->enabled = config_get_boolean_ondemand(var_name, "enabled", m->enabled);
-
- if (unlikely(m->enabled == CONFIG_BOOLEAN_NO))
- continue;
-
- m->do_space = config_get_boolean_ondemand(var_name, "space usage", do_space);
- m->do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", do_inodes);
- }
-
- if (unlikely(!m->enabled))
- continue;
-
- if (unlikely(mntbuf[i].f_flags & MNT_RDONLY && !m->collected))
- continue;
-
- // --------------------------------------------------------------------------
-
- int rendered = 0;
-
- if (m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_blocks > 2))) {
- if (unlikely(!m->st_space)) {
- snprintfz(title, 4096, "Disk Space Usage for %s [%s]",
- mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
- m->st_space = rrdset_create_localhost("disk_space",
- mntbuf[i].f_mntonname,
- NULL,
- mntbuf[i].f_mntonname,
- "disk.space",
- title,
- "GB",
- "freebsd",
- "getmntinfo",
- 2023,
- update_every,
- RRDSET_TYPE_STACKED
- );
-
- m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL,
- mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- m->rd_space_used = rrddim_add(m->st_space, "used", NULL,
- mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root",
- mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(m->st_space);
-
- rrddim_set_by_pointer(m->st_space, m->rd_space_avail, (collected_number) mntbuf[i].f_bavail);
- rrddim_set_by_pointer(m->st_space, m->rd_space_used, (collected_number) (mntbuf[i].f_blocks -
- mntbuf[i].f_bfree));
- rrddim_set_by_pointer(m->st_space, m->rd_space_reserved, (collected_number) (mntbuf[i].f_bfree -
- mntbuf[i].f_bavail));
- rrdset_done(m->st_space);
-
- rendered++;
- }
-
- // --------------------------------------------------------------------------
-
- if (m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_files > 1))) {
- if (unlikely(!m->st_inodes)) {
- snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]",
- mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
- m->st_inodes = rrdset_create_localhost("disk_inodes",
- mntbuf[i].f_mntonname,
- NULL,
- mntbuf[i].f_mntonname,
- "disk.inodes",
- title,
- "Inodes",
- "freebsd",
- "getmntinfo",
- 2024,
- update_every,
- RRDSET_TYPE_STACKED
- );
-
- m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(m->st_inodes);
-
- rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number) mntbuf[i].f_ffree);
- rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used, (collected_number) (mntbuf[i].f_files -
- mntbuf[i].f_ffree));
- rrdset_done(m->st_inodes);
-
- rendered++;
- }
-
- if (likely(rendered))
- m->collected++;
- }
- }
- } else {
- error("DISABLED: getmntinfo module");
- return 1;
- }
-
- mount_points_cleanup();
-
- return 0;
-}
diff --git a/src/freebsd_ipfw.c b/src/freebsd_ipfw.c
deleted file mode 100644
index 81264b3f3..000000000
--- a/src/freebsd_ipfw.c
+++ /dev/null
@@ -1,370 +0,0 @@
-#include "common.h"
-
-#include <netinet/ip_fw.h>
-
-#define FREE_MEM_THRESHOLD 10000 // number of unused chunks that trigger memory freeing
-
-#define COMMON_IPFW_ERROR() error("DISABLED: ipfw.packets chart"); \
- error("DISABLED: ipfw.bytes chart"); \
- error("DISABLED: ipfw.dyn_active chart"); \
- error("DISABLED: ipfw.dyn_expired chart"); \
- error("DISABLED: ipfw.mem chart");
-
-// --------------------------------------------------------------------------------------------------------------------
-// ipfw
-
-int do_ipfw(int update_every, usec_t dt) {
- (void)dt;
-#if __FreeBSD__ >= 11
-
- static int do_static = -1, do_dynamic = -1, do_mem = -1;
-
- if (unlikely(do_static == -1)) {
- do_static = config_get_boolean("plugin:freebsd:ipfw", "counters for static rules", 1);
- do_dynamic = config_get_boolean("plugin:freebsd:ipfw", "number of dynamic rules", 1);
- do_mem = config_get_boolean("plugin:freebsd:ipfw", "allocated memory", 1);
- }
-
- // variables for getting ipfw configuration
-
- int error;
- static int ipfw_socket = -1;
- static ipfw_cfg_lheader *cfg = NULL;
- ip_fw3_opheader *op3 = NULL;
- static socklen_t *optlen = NULL, cfg_size = 0;
-
- // variables for static rules handling
-
- ipfw_obj_ctlv *ctlv = NULL;
- ipfw_obj_tlv *rbase = NULL;
- int rcnt = 0;
-
- int n, seen;
- struct ip_fw_rule *rule;
- struct ip_fw_bcounter *cntr;
- int c = 0;
-
- char rule_num_str[12];
-
- // variables for dynamic rules handling
-
- caddr_t dynbase = NULL;
- size_t dynsz = 0;
- size_t readsz = sizeof(*cfg);;
- int ttype = 0;
- ipfw_obj_tlv *tlv;
- ipfw_dyn_rule *dyn_rule;
- uint16_t rulenum, prev_rulenum = IPFW_DEFAULT_RULE;
- unsigned srn, static_rules_num = 0;
- static size_t dyn_rules_num_size = 0;
-
- static struct dyn_rule_num {
- uint16_t rule_num;
- uint32_t active_rules;
- uint32_t expired_rules;
- } *dyn_rules_num = NULL;
-
- uint32_t *dyn_rules_counter;
-
- if (likely(do_static | do_dynamic | do_mem)) {
-
- // initialize the smallest ipfw_cfg_lheader possible
-
- if (unlikely((optlen == NULL) || (cfg == NULL))) {
- optlen = reallocz(optlen, sizeof(socklen_t));
- *optlen = cfg_size = 32;
- cfg = reallocz(cfg, *optlen);
- }
-
- // get socket descriptor and initialize ipfw_cfg_lheader structure
-
- if (unlikely(ipfw_socket == -1))
- ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
- if (unlikely(ipfw_socket == -1)) {
- error("FREEBSD: can't get socket for ipfw configuration");
- error("FREEBSD: run netdata as root to get access to ipfw data");
- COMMON_IPFW_ERROR();
- return 1;
- }
-
- bzero(cfg, 32);
- cfg->flags = IPFW_CFG_GET_STATIC | IPFW_CFG_GET_COUNTERS | IPFW_CFG_GET_STATES;
- op3 = &cfg->opheader;
- op3->opcode = IP_FW_XGET;
-
- // get ifpw configuration size than get configuration
-
- *optlen = cfg_size;
- error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, optlen);
- if (error)
- if (errno != ENOMEM) {
- error("FREEBSD: ipfw socket reading error");
- COMMON_IPFW_ERROR();
- return 1;
- }
- if ((cfg->size > cfg_size) || ((cfg_size - cfg->size) > sizeof(struct dyn_rule_num) * FREE_MEM_THRESHOLD)) {
- *optlen = cfg_size = cfg->size;
- cfg = reallocz(cfg, *optlen);
- bzero(cfg, 32);
- cfg->flags = IPFW_CFG_GET_STATIC | IPFW_CFG_GET_COUNTERS | IPFW_CFG_GET_STATES;
- op3 = &cfg->opheader;
- op3->opcode = IP_FW_XGET;
- error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, optlen);
- if (error) {
- error("FREEBSD: ipfw socket reading error");
- COMMON_IPFW_ERROR();
- return 1;
- }
- }
-
- // go through static rules configuration structures
-
- ctlv = (ipfw_obj_ctlv *) (cfg + 1);
-
- if (cfg->flags & IPFW_CFG_GET_STATIC) {
- /* We've requested static rules */
- if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
- readsz += ctlv->head.length;
- ctlv = (ipfw_obj_ctlv *) ((caddr_t) ctlv +
- ctlv->head.length);
- }
-
- if (ctlv->head.type == IPFW_TLV_RULE_LIST) {
- rbase = (ipfw_obj_tlv *) (ctlv + 1);
- rcnt = ctlv->count;
- readsz += ctlv->head.length;
- ctlv = (ipfw_obj_ctlv *) ((caddr_t) ctlv + ctlv->head.length);
- }
- }
-
- if ((cfg->flags & IPFW_CFG_GET_STATES) && (readsz != *optlen)) {
- /* We may have some dynamic states */
- dynsz = *optlen - readsz;
- /* Skip empty header */
- if (dynsz != sizeof(ipfw_obj_ctlv))
- dynbase = (caddr_t) ctlv;
- else
- dynsz = 0;
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_mem)) {
- static RRDSET *st_mem = NULL;
- static RRDDIM *rd_dyn_mem = NULL;
- static RRDDIM *rd_stat_mem = NULL;
-
- if (unlikely(!st_mem)) {
- st_mem = rrdset_create_localhost("ipfw",
- "mem",
- NULL,
- "memory allocated",
- NULL,
- "Memory allocated by rules",
- "bytes",
- "freebsd",
- "ipfw",
- 3005,
- update_every,
- RRDSET_TYPE_STACKED
- );
- rrdset_flag_set(st_mem, RRDSET_FLAG_DETAIL);
-
- rd_dyn_mem = rrddim_add(st_mem, "dynamic", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_stat_mem = rrddim_add(st_mem, "static", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(st_mem);
-
- rrddim_set_by_pointer(st_mem, rd_dyn_mem, dynsz);
- rrddim_set_by_pointer(st_mem, rd_stat_mem, *optlen - dynsz);
- rrdset_done(st_mem);
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_packets = NULL, *st_bytes = NULL;
- RRDDIM *rd_packets = NULL, *rd_bytes = NULL;
-
- if (likely(do_static || do_dynamic)) {
- if (likely(do_static)) {
- if (unlikely(!st_packets))
- st_packets = rrdset_create_localhost("ipfw",
- "packets",
- NULL,
- "static rules",
- NULL,
- "Packets",
- "packets/s",
- "freebsd",
- "ipfw",
- 3001,
- update_every,
- RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_packets);
-
- if (unlikely(!st_bytes))
- st_bytes = rrdset_create_localhost("ipfw",
- "bytes",
- NULL,
- "static rules",
- NULL,
- "Bytes",
- "bytes/s",
- "freebsd",
- "ipfw",
- 3002,
- update_every,
- RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_bytes);
- }
-
- for (n = seen = 0; n < rcnt; n++, rbase = (ipfw_obj_tlv *) ((caddr_t) rbase + rbase->length)) {
- cntr = (struct ip_fw_bcounter *) (rbase + 1);
- rule = (struct ip_fw_rule *) ((caddr_t) cntr + cntr->size);
- if (rule->rulenum != prev_rulenum)
- static_rules_num++;
- if (rule->rulenum > IPFW_DEFAULT_RULE)
- break;
-
- if (likely(do_static)) {
- sprintf(rule_num_str, "%d_%d", rule->rulenum, rule->id);
-
- rd_packets = rrddim_find(st_packets, rule_num_str);
- if (unlikely(!rd_packets))
- rd_packets = rrddim_add(st_packets, rule_num_str, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_set_by_pointer(st_packets, rd_packets, cntr->pcnt);
-
- rd_bytes = rrddim_find(st_bytes, rule_num_str);
- if (unlikely(!rd_bytes))
- rd_bytes = rrddim_add(st_bytes, rule_num_str, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_set_by_pointer(st_bytes, rd_bytes, cntr->bcnt);
- }
-
- c += rbase->length;
- seen++;
- }
-
- if (likely(do_static)) {
- rrdset_done(st_packets);
- rrdset_done(st_bytes);
- }
- }
-
- // --------------------------------------------------------------------
-
- // go through dynamic rules configuration structures
-
- if (likely(do_dynamic && (dynsz > 0))) {
- if ((dyn_rules_num_size < sizeof(struct dyn_rule_num) * static_rules_num) ||
- ((dyn_rules_num_size - sizeof(struct dyn_rule_num) * static_rules_num) >
- sizeof(struct dyn_rule_num) * FREE_MEM_THRESHOLD)) {
- dyn_rules_num_size = sizeof(struct dyn_rule_num) * static_rules_num;
- dyn_rules_num = reallocz(dyn_rules_num, dyn_rules_num_size);
- }
- bzero(dyn_rules_num, sizeof(struct dyn_rule_num) * static_rules_num);
- dyn_rules_num->rule_num = IPFW_DEFAULT_RULE;
-
- if (dynsz > 0 && ctlv->head.type == IPFW_TLV_DYNSTATE_LIST) {
- dynbase += sizeof(*ctlv);
- dynsz -= sizeof(*ctlv);
- ttype = IPFW_TLV_DYN_ENT;
- }
-
- while (dynsz > 0) {
- tlv = (ipfw_obj_tlv *) dynbase;
- if (tlv->type != ttype)
- break;
-
- dyn_rule = (ipfw_dyn_rule *) (tlv + 1);
- bcopy(&dyn_rule->rule, &rulenum, sizeof(rulenum));
-
- for (srn = 0; srn < (static_rules_num - 1); srn++) {
- if (dyn_rule->expire > 0)
- dyn_rules_counter = &dyn_rules_num[srn].active_rules;
- else
- dyn_rules_counter = &dyn_rules_num[srn].expired_rules;
- if (dyn_rules_num[srn].rule_num == rulenum) {
- (*dyn_rules_counter)++;
- break;
- }
- if (dyn_rules_num[srn].rule_num == IPFW_DEFAULT_RULE) {
- dyn_rules_num[srn].rule_num = rulenum;
- dyn_rules_num[srn + 1].rule_num = IPFW_DEFAULT_RULE;
- (*dyn_rules_counter)++;
- break;
- }
- }
-
- dynsz -= tlv->length;
- dynbase += tlv->length;
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_active = NULL, *st_expired = NULL;
- RRDDIM *rd_active = NULL, *rd_expired = NULL;
-
- if (unlikely(!st_active))
- st_active = rrdset_create_localhost("ipfw",
- "active",
- NULL,
- "dynamic_rules",
- NULL,
- "Active rules",
- "rules",
- "freebsd",
- "ipfw",
- 3003,
- update_every,
- RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_active);
-
- if (unlikely(!st_expired))
- st_expired = rrdset_create_localhost("ipfw",
- "expired",
- NULL,
- "dynamic_rules",
- NULL,
- "Expired rules",
- "rules",
- "freebsd",
- "ipfw",
- 3004,
- update_every,
- RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_expired);
-
- for (srn = 0; (srn < (static_rules_num - 1)) && (dyn_rules_num[srn].rule_num != IPFW_DEFAULT_RULE); srn++) {
- sprintf(rule_num_str, "%d", dyn_rules_num[srn].rule_num);
-
- rd_active = rrddim_find(st_active, rule_num_str);
- if (unlikely(!rd_active))
- rd_active = rrddim_add(st_active, rule_num_str, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_set_by_pointer(st_active, rd_active, dyn_rules_num[srn].active_rules);
-
- rd_expired = rrddim_find(st_expired, rule_num_str);
- if (unlikely(!rd_expired))
- rd_expired = rrddim_add(st_expired, rule_num_str, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_set_by_pointer(st_expired, rd_expired, dyn_rules_num[srn].expired_rules);
- }
-
- rrdset_done(st_active);
- rrdset_done(st_expired);
- }
- }
-
- return 0;
-#else
- error("FREEBSD: ipfw charts supported for FreeBSD 11.0 and newer releases only");
- COMMON_IPFW_ERROR();
- return 1;
-#endif
-}
diff --git a/src/freebsd_kstat_zfs.c b/src/freebsd_kstat_zfs.c
deleted file mode 100644
index 1bd48d4bf..000000000
--- a/src/freebsd_kstat_zfs.c
+++ /dev/null
@@ -1,298 +0,0 @@
-#include "common.h"
-#include "zfs_common.h"
-
-extern struct arcstats arcstats;
-
-// --------------------------------------------------------------------------------------------------------------------
-// kstat.zfs.misc.arcstats
-
-int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt) {
- (void)dt;
-
- unsigned long long l2_size;
- size_t uint64_t_size = sizeof(uint64_t);
- static struct mibs {
- int hits[5];
- int misses[5];
- int demand_data_hits[5];
- int demand_data_misses[5];
- int demand_metadata_hits[5];
- int demand_metadata_misses[5];
- int prefetch_data_hits[5];
- int prefetch_data_misses[5];
- int prefetch_metadata_hits[5];
- int prefetch_metadata_misses[5];
- int mru_hits[5];
- int mru_ghost_hits[5];
- int mfu_hits[5];
- int mfu_ghost_hits[5];
- int deleted[5];
- int mutex_miss[5];
- int evict_skip[5];
- int evict_not_enough[5];
- int evict_l2_cached[5];
- int evict_l2_eligible[5];
- int evict_l2_ineligible[5];
- int evict_l2_skip[5];
- int hash_elements[5];
- int hash_elements_max[5];
- int hash_collisions[5];
- int hash_chains[5];
- int hash_chain_max[5];
- int p[5];
- int c[5];
- int c_min[5];
- int c_max[5];
- int size[5];
- int hdr_size[5];
- int data_size[5];
- int metadata_size[5];
- int other_size[5];
- int anon_size[5];
- int anon_evictable_data[5];
- int anon_evictable_metadata[5];
- int mru_size[5];
- int mru_evictable_data[5];
- int mru_evictable_metadata[5];
- int mru_ghost_size[5];
- int mru_ghost_evictable_data[5];
- int mru_ghost_evictable_metadata[5];
- int mfu_size[5];
- int mfu_evictable_data[5];
- int mfu_evictable_metadata[5];
- int mfu_ghost_size[5];
- int mfu_ghost_evictable_data[5];
- int mfu_ghost_evictable_metadata[5];
- int l2_hits[5];
- int l2_misses[5];
- int l2_feeds[5];
- int l2_rw_clash[5];
- int l2_read_bytes[5];
- int l2_write_bytes[5];
- int l2_writes_sent[5];
- int l2_writes_done[5];
- int l2_writes_error[5];
- int l2_writes_lock_retry[5];
- int l2_evict_lock_retry[5];
- int l2_evict_reading[5];
- int l2_evict_l1cached[5];
- int l2_free_on_write[5];
- int l2_cdata_free_on_write[5];
- int l2_abort_lowmem[5];
- int l2_cksum_bad[5];
- int l2_io_error[5];
- int l2_size[5];
- int l2_asize[5];
- int l2_hdr_size[5];
- int l2_compress_successes[5];
- int l2_compress_zeros[5];
- int l2_compress_failures[5];
- int memory_throttle_count[5];
- int duplicate_buffers[5];
- int duplicate_buffers_size[5];
- int duplicate_reads[5];
- int memory_direct_count[5];
- int memory_indirect_count[5];
- int arc_no_grow[5];
- int arc_tempreserve[5];
- int arc_loaned_bytes[5];
- int arc_prune[5];
- int arc_meta_used[5];
- int arc_meta_limit[5];
- int arc_meta_max[5];
- int arc_meta_min[5];
- int arc_need_free[5];
- int arc_sys_free[5];
- } mibs;
-
- arcstats.l2exist = -1;
-
- if(unlikely(sysctlbyname("kstat.zfs.misc.arcstats.l2_size", &l2_size, &uint64_t_size, NULL, 0)))
- return 0;
-
- if(likely(l2_size))
- arcstats.l2exist = 1;
- else
- arcstats.l2exist = 0;
-
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hits", mibs.hits, arcstats.hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.misses", mibs.misses, arcstats.misses);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.demand_data_hits", mibs.demand_data_hits, arcstats.demand_data_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.demand_data_misses", mibs.demand_data_misses, arcstats.demand_data_misses);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.demand_metadata_hits", mibs.demand_metadata_hits, arcstats.demand_metadata_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.demand_metadata_misses", mibs.demand_metadata_misses, arcstats.demand_metadata_misses);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.prefetch_data_hits", mibs.prefetch_data_hits, arcstats.prefetch_data_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.prefetch_data_misses", mibs.prefetch_data_misses, arcstats.prefetch_data_misses);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.prefetch_metadata_hits", mibs.prefetch_metadata_hits, arcstats.prefetch_metadata_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.prefetch_metadata_misses", mibs.prefetch_metadata_misses, arcstats.prefetch_metadata_misses);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_hits", mibs.mru_hits, arcstats.mru_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_ghost_hits", mibs.mru_ghost_hits, arcstats.mru_ghost_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_hits", mibs.mfu_hits, arcstats.mfu_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_ghost_hits", mibs.mfu_ghost_hits, arcstats.mfu_ghost_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.deleted", mibs.deleted, arcstats.deleted);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mutex_miss", mibs.mutex_miss, arcstats.mutex_miss);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.evict_skip", mibs.evict_skip, arcstats.evict_skip);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.evict_not_enough", mibs.evict_not_enough, arcstats.evict_not_enough);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.evict_l2_cached", mibs.evict_l2_cached, arcstats.evict_l2_cached);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.evict_l2_eligible", mibs.evict_l2_eligible, arcstats.evict_l2_eligible);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.evict_l2_ineligible", mibs.evict_l2_ineligible, arcstats.evict_l2_ineligible);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.evict_l2_skip", mibs.evict_l2_skip, arcstats.evict_l2_skip);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hash_elements", mibs.hash_elements, arcstats.hash_elements);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hash_elements_max", mibs.hash_elements_max, arcstats.hash_elements_max);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hash_collisions", mibs.hash_collisions, arcstats.hash_collisions);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hash_chains", mibs.hash_chains, arcstats.hash_chains);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hash_chain_max", mibs.hash_chain_max, arcstats.hash_chain_max);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.p", mibs.p, arcstats.p);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.c", mibs.c, arcstats.c);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.c_min", mibs.c_min, arcstats.c_min);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.c_max", mibs.c_max, arcstats.c_max);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.size", mibs.size, arcstats.size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.hdr_size", mibs.hdr_size, arcstats.hdr_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.data_size", mibs.data_size, arcstats.data_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.metadata_size", mibs.metadata_size, arcstats.metadata_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.other_size", mibs.other_size, arcstats.other_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.anon_size", mibs.anon_size, arcstats.anon_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.anon_evictable_data", mibs.anon_evictable_data, arcstats.anon_evictable_data);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.anon_evictable_metadata", mibs.anon_evictable_metadata, arcstats.anon_evictable_metadata);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_size", mibs.mru_size, arcstats.mru_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_evictable_data", mibs.mru_evictable_data, arcstats.mru_evictable_data);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_evictable_metadata", mibs.mru_evictable_metadata, arcstats.mru_evictable_metadata);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_ghost_size", mibs.mru_ghost_size, arcstats.mru_ghost_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_ghost_evictable_data", mibs.mru_ghost_evictable_data, arcstats.mru_ghost_evictable_data);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mru_ghost_evictable_metadata", mibs.mru_ghost_evictable_metadata, arcstats.mru_ghost_evictable_metadata);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_size", mibs.mfu_size, arcstats.mfu_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_evictable_data", mibs.mfu_evictable_data, arcstats.mfu_evictable_data);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_evictable_metadata", mibs.mfu_evictable_metadata, arcstats.mfu_evictable_metadata);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_ghost_size", mibs.mfu_ghost_size, arcstats.mfu_ghost_size);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_ghost_evictable_data", mibs.mfu_ghost_evictable_data, arcstats.mfu_ghost_evictable_data);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.mfu_ghost_evictable_metadata", mibs.mfu_ghost_evictable_metadata, arcstats.mfu_ghost_evictable_metadata);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_hits", mibs.l2_hits, arcstats.l2_hits);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_misses", mibs.l2_misses, arcstats.l2_misses);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_feeds", mibs.l2_feeds, arcstats.l2_feeds);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_rw_clash", mibs.l2_rw_clash, arcstats.l2_rw_clash);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_read_bytes", mibs.l2_read_bytes, arcstats.l2_read_bytes);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_write_bytes", mibs.l2_write_bytes, arcstats.l2_write_bytes);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_writes_sent", mibs.l2_writes_sent, arcstats.l2_writes_sent);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_writes_done", mibs.l2_writes_done, arcstats.l2_writes_done);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_writes_error", mibs.l2_writes_error, arcstats.l2_writes_error);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_writes_lock_retry", mibs.l2_writes_lock_retry, arcstats.l2_writes_lock_retry);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_evict_lock_retry", mibs.l2_evict_lock_retry, arcstats.l2_evict_lock_retry);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_evict_reading", mibs.l2_evict_reading, arcstats.l2_evict_reading);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_evict_l1cached", mibs.l2_evict_l1cached, arcstats.l2_evict_l1cached);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_free_on_write", mibs.l2_free_on_write, arcstats.l2_free_on_write);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_cdata_free_on_write", mibs.l2_cdata_free_on_write, arcstats.l2_cdata_free_on_write);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_abort_lowmem", mibs.l2_abort_lowmem, arcstats.l2_abort_lowmem);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_cksum_bad", mibs.l2_cksum_bad, arcstats.l2_cksum_bad);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_io_error", mibs.l2_io_error, arcstats.l2_io_error);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_size", mibs.l2_size, arcstats.l2_size);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_asize", mibs.l2_asize, arcstats.l2_asize);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_hdr_size", mibs.l2_hdr_size, arcstats.l2_hdr_size);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_compress_successes", mibs.l2_compress_successes, arcstats.l2_compress_successes);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_compress_zeros", mibs.l2_compress_zeros, arcstats.l2_compress_zeros);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.l2_compress_failures", mibs.l2_compress_failures, arcstats.l2_compress_failures);
- GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.memory_throttle_count", mibs.memory_throttle_count, arcstats.memory_throttle_count);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.duplicate_buffers", mibs.duplicate_buffers, arcstats.duplicate_buffers);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.duplicate_buffers_size", mibs.duplicate_buffers_size, arcstats.duplicate_buffers_size);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.duplicate_reads", mibs.duplicate_reads, arcstats.duplicate_reads);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.memory_direct_count", mibs.memory_direct_count, arcstats.memory_direct_count);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.memory_indirect_count", mibs.memory_indirect_count, arcstats.memory_indirect_count);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_no_grow", mibs.arc_no_grow, arcstats.arc_no_grow);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_tempreserve", mibs.arc_tempreserve, arcstats.arc_tempreserve);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_loaned_bytes", mibs.arc_loaned_bytes, arcstats.arc_loaned_bytes);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_prune", mibs.arc_prune, arcstats.arc_prune);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_meta_used", mibs.arc_meta_used, arcstats.arc_meta_used);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_meta_limit", mibs.arc_meta_limit, arcstats.arc_meta_limit);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_meta_max", mibs.arc_meta_max, arcstats.arc_meta_max);
- // not used: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_meta_min", mibs.arc_meta_min, arcstats.arc_meta_min);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_need_free", mibs.arc_need_free, arcstats.arc_need_free);
- // missing mib: GETSYSCTL_SIMPLE("kstat.zfs.misc.arcstats.arc_sys_free", mibs.arc_sys_free, arcstats.arc_sys_free);
-
- generate_charts_arcstats("freebsd", update_every);
- generate_charts_arc_summary("freebsd", update_every);
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kstat.zfs.misc.zio_trim
-
-int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt) {
- (void)dt;
- static int mib_bytes[5] = {0, 0, 0, 0, 0}, mib_success[5] = {0, 0, 0, 0, 0},
- mib_failed[5] = {0, 0, 0, 0, 0}, mib_unsupported[5] = {0, 0, 0, 0, 0};
- uint64_t bytes, success, failed, unsupported;
-
- if (unlikely(GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.bytes", mib_bytes, bytes) ||
- GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.success", mib_success, success) ||
- GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.failed", mib_failed, failed) ||
- GETSYSCTL_SIMPLE("kstat.zfs.misc.zio_trim.unsupported", mib_unsupported, unsupported))) {
- error("DISABLED: zfs.trim_bytes chart");
- error("DISABLED: zfs.trim_success chart");
- error("DISABLED: kstat.zfs.misc.zio_trim module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_bytes = NULL;
- static RRDDIM *rd_bytes = NULL;
-
- if (unlikely(!st_bytes)) {
- st_bytes = rrdset_create_localhost(
- "zfs",
- "trim_bytes",
- NULL,
- "trim",
- NULL,
- "Successfully TRIMmed bytes",
- "bytes",
- "freebsd",
- "zfs",
- 2320,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_bytes = rrddim_add(st_bytes, "TRIMmed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_bytes);
-
- rrddim_set_by_pointer(st_bytes, rd_bytes, bytes);
- rrdset_done(st_bytes);
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_requests = NULL;
- static RRDDIM *rd_successful = NULL, *rd_failed = NULL, *rd_unsupported = NULL;
-
- if (unlikely(!st_requests)) {
- st_requests = rrdset_create_localhost(
- "zfs",
- "trim_requests",
- NULL,
- "trim",
- NULL,
- "TRIM requests",
- "requests",
- "freebsd",
- "zfs",
- 2321,
- update_every,
- RRDSET_TYPE_STACKED
- );
-
- rd_successful = rrddim_add(st_requests, "successful", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st_requests, "failed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_unsupported = rrddim_add(st_requests, "unsupported", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_requests);
-
- rrddim_set_by_pointer(st_requests, rd_successful, success);
- rrddim_set_by_pointer(st_requests, rd_failed, failed);
- rrddim_set_by_pointer(st_requests, rd_unsupported, unsupported);
- rrdset_done(st_requests);
-
- }
-
- return 0;
-} \ No newline at end of file
diff --git a/src/freebsd_sysctl.c b/src/freebsd_sysctl.c
deleted file mode 100644
index 1e11255aa..000000000
--- a/src/freebsd_sysctl.c
+++ /dev/null
@@ -1,3171 +0,0 @@
-#include "common.h"
-
-#include <sys/vmmeter.h>
-#include <vm/vm_param.h>
-
-#define _KERNEL
-#include <sys/sem.h>
-#include <sys/shm.h>
-#include <sys/msg.h>
-#undef _KERNEL
-
-#include <net/netisr.h>
-
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/icmp_var.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/icmp6.h>
-#include <netinet/tcp_var.h>
-#include <netinet/tcp_fsm.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-
-// --------------------------------------------------------------------------------------------------------------------
-// common definitions and variables
-
-int system_pagesize = PAGE_SIZE;
-int number_of_cpus = 1;
-#if __FreeBSD_version >= 1200029
-struct __vmmeter {
- uint64_t v_swtch;
- uint64_t v_trap;
- uint64_t v_syscall;
- uint64_t v_intr;
- uint64_t v_soft;
- uint64_t v_vm_faults;
- uint64_t v_io_faults;
- uint64_t v_cow_faults;
- uint64_t v_cow_optim;
- uint64_t v_zfod;
- uint64_t v_ozfod;
- uint64_t v_swapin;
- uint64_t v_swapout;
- uint64_t v_swappgsin;
- uint64_t v_swappgsout;
- uint64_t v_vnodein;
- uint64_t v_vnodeout;
- uint64_t v_vnodepgsin;
- uint64_t v_vnodepgsout;
- uint64_t v_intrans;
- uint64_t v_reactivated;
- uint64_t v_pdwakeups;
- uint64_t v_pdpages;
- uint64_t v_pdshortfalls;
- uint64_t v_dfree;
- uint64_t v_pfree;
- uint64_t v_tfree;
- uint64_t v_forks;
- uint64_t v_vforks;
- uint64_t v_rforks;
- uint64_t v_kthreads;
- uint64_t v_forkpages;
- uint64_t v_vforkpages;
- uint64_t v_rforkpages;
- uint64_t v_kthreadpages;
- u_int v_page_size;
- u_int v_page_count;
- u_int v_free_reserved;
- u_int v_free_target;
- u_int v_free_min;
- u_int v_free_count;
- u_int v_wire_count;
- u_int v_active_count;
- u_int v_inactive_target;
- u_int v_inactive_count;
- u_int v_laundry_count;
- u_int v_pageout_free_min;
- u_int v_interrupt_free_min;
- u_int v_free_severe;
-};
-typedef struct __vmmeter vmmeter_t;
-#else
-typedef struct vmmeter vmmeter_t;
-#endif
-
-// --------------------------------------------------------------------------------------------------------------------
-// FreeBSD plugin initialization
-
-int freebsd_plugin_init()
-{
- system_pagesize = getpagesize();
- if (system_pagesize <= 0) {
- error("FREEBSD: can't get system page size");
- return 1;
- }
-
- if (unlikely(GETSYSCTL_BY_NAME("kern.smp.cpus", number_of_cpus))) {
- error("FREEBSD: can't get number of cpus");
- return 1;
- }
-
- if (unlikely(!number_of_cpus)) {
- error("FREEBSD: wrong number of cpus");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.loadavg
-
-// FreeBSD calculates load averages once every 5 seconds
-#define MIN_LOADAVG_UPDATE_EVERY 5
-
-int do_vm_loadavg(int update_every, usec_t dt){
- static usec_t next_loadavg_dt = 0;
-
- if (next_loadavg_dt <= dt) {
- static int mib[2] = {0, 0};
- struct loadavg sysload;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.loadavg", mib, sysload))) {
- error("DISABLED: system.load chart");
- error("DISABLED: vm.loadavg module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_load1 = NULL, *rd_load2 = NULL, *rd_load3 = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "load",
- NULL,
- "load",
- NULL,
- "System Load Average",
- "load",
- "freebsd",
- "vm.loadavg",
- 100,
- (update_every < MIN_LOADAVG_UPDATE_EVERY) ?
- MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE
- );
- rd_load1 = rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_load2 = rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_load3 = rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_load1, (collected_number) ((double) sysload.ldavg[0] / sysload.fscale * 1000));
- rrddim_set_by_pointer(st, rd_load2, (collected_number) ((double) sysload.ldavg[1] / sysload.fscale * 1000));
- rrddim_set_by_pointer(st, rd_load3, (collected_number) ((double) sysload.ldavg[2] / sysload.fscale * 1000));
- rrdset_done(st);
-
- next_loadavg_dt = st->update_every * USEC_PER_SEC;
- }
- }
- else
- next_loadavg_dt -= dt;
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.vmtotal
-
-int do_vm_vmtotal(int update_every, usec_t dt) {
- (void)dt;
- static int do_all_processes = -1, do_processes = -1, do_committed = -1;
-
- if (unlikely(do_all_processes == -1)) {
- do_all_processes = config_get_boolean("plugin:freebsd:vm.vmtotal", "enable total processes", 1);
- do_processes = config_get_boolean("plugin:freebsd:vm.vmtotal", "processes running", 1);
- do_committed = config_get_boolean("plugin:freebsd:vm.vmtotal", "committed memory", 1);
- }
-
- if (likely(do_all_processes | do_processes | do_committed)) {
- static int mib[2] = {0, 0};
- struct vmtotal vmtotal_data;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.vmtotal", mib, vmtotal_data))) {
- do_all_processes = 0;
- error("DISABLED: system.active_processes chart");
- do_processes = 0;
- error("DISABLED: system.processes chart");
- do_committed = 0;
- error("DISABLED: mem.committed chart");
- error("DISABLED: vm.vmtotal module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- if (likely(do_all_processes)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "active_processes",
- NULL,
- "processes",
- NULL,
- "System Active Processes",
- "processes",
- "freebsd",
- "vm.vmtotal",
- 750,
- update_every,
- RRDSET_TYPE_LINE
- );
- rd = rrddim_add(st, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw));
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_processes)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_running = NULL, *rd_blocked = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "processes",
- NULL,
- "processes",
- NULL,
- "System Processes",
- "processes",
- "freebsd",
- "vm.vmtotal",
- 600,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_running = rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_blocked = rrddim_add(st, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_running, vmtotal_data.t_rq);
- rrddim_set_by_pointer(st, rd_blocked, (vmtotal_data.t_dw + vmtotal_data.t_pw));
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_committed)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "mem",
- "committed",
- NULL,
- "system",
- NULL,
- "Committed (Allocated) Memory",
- "MB",
- "freebsd",
- "vm.vmtotal",
- NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED,
- update_every,
- RRDSET_TYPE_AREA
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd = rrddim_add(st, "Committed_AS", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, vmtotal_data.t_rm);
- rrdset_done(st);
- }
- }
- } else {
- error("DISABLED: vm.vmtotal module");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kern.cp_time
-
-int do_kern_cp_time(int update_every, usec_t dt) {
- (void)dt;
-
- if (unlikely(CPUSTATES != 5)) {
- error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
- error("DISABLED: system.cpu chart");
- error("DISABLED: kern.cp_time module");
- return 1;
- } else {
- static int mib[2] = {0, 0};
- long cp_time[CPUSTATES];
-
- if (unlikely(GETSYSCTL_SIMPLE("kern.cp_time", mib, cp_time))) {
- error("DISABLED: system.cpu chart");
- error("DISABLED: kern.cp_time module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_nice = NULL, *rd_system = NULL, *rd_user = NULL, *rd_interrupt = NULL, *rd_idle = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "cpu",
- NULL,
- "cpu",
- "system.cpu",
- "Total CPU utilization",
- "percentage",
- "freebsd",
- "kern.cp_time",
- 100, update_every,
- RRDSET_TYPE_STACKED
- );
-
- rd_nice = rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_system = rrddim_add(st, "system", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_user = rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_interrupt = rrddim_add(st, "interrupt", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_idle = rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_hide(st, "idle");
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_nice, cp_time[1]);
- rrddim_set_by_pointer(st, rd_system, cp_time[2]);
- rrddim_set_by_pointer(st, rd_user, cp_time[0]);
- rrddim_set_by_pointer(st, rd_interrupt, cp_time[3]);
- rrddim_set_by_pointer(st, rd_idle, cp_time[4]);
- rrdset_done(st);
- }
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kern.cp_times
-
-int do_kern_cp_times(int update_every, usec_t dt) {
- (void)dt;
-
- if (unlikely(CPUSTATES != 5)) {
- error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
- error("DISABLED: cpu.cpuXX charts");
- error("DISABLED: kern.cp_times module");
- return 1;
- } else {
- static int mib[2] = {0, 0};
- long cp_time[CPUSTATES];
- static long *pcpu_cp_time = NULL;
- static int old_number_of_cpus = 0;
-
- if(unlikely(number_of_cpus != old_number_of_cpus))
- pcpu_cp_time = reallocz(pcpu_cp_time, sizeof(cp_time) * number_of_cpus);
- if (unlikely(GETSYSCTL_WSIZE("kern.cp_times", mib, pcpu_cp_time, sizeof(cp_time) * number_of_cpus))) {
- error("DISABLED: cpu.cpuXX charts");
- error("DISABLED: kern.cp_times module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- int i;
- static struct cpu_chart {
- char cpuid[MAX_INT_DIGITS + 4];
- RRDSET *st;
- RRDDIM *rd_user;
- RRDDIM *rd_nice;
- RRDDIM *rd_system;
- RRDDIM *rd_interrupt;
- RRDDIM *rd_idle;
- } *all_cpu_charts = NULL;
-
- if(unlikely(number_of_cpus > old_number_of_cpus)) {
- all_cpu_charts = reallocz(all_cpu_charts, sizeof(struct cpu_chart) * number_of_cpus);
- memset(&all_cpu_charts[old_number_of_cpus], 0, sizeof(struct cpu_chart) * (number_of_cpus - old_number_of_cpus));
- }
-
- for (i = 0; i < number_of_cpus; i++) {
- if (unlikely(!all_cpu_charts[i].st)) {
- snprintfz(all_cpu_charts[i].cpuid, MAX_INT_DIGITS, "cpu%d", i);
- all_cpu_charts[i].st = rrdset_create_localhost(
- "cpu",
- all_cpu_charts[i].cpuid,
- NULL,
- "utilization",
- "cpu.cpu",
- "Core utilization",
- "percentage",
- "freebsd",
- "kern.cp_times",
- 1000,
- update_every,
- RRDSET_TYPE_STACKED
- );
-
- all_cpu_charts[i].rd_nice = rrddim_add(all_cpu_charts[i].st, "nice", NULL, 1, 1,
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- all_cpu_charts[i].rd_system = rrddim_add(all_cpu_charts[i].st, "system", NULL, 1, 1,
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- all_cpu_charts[i].rd_user = rrddim_add(all_cpu_charts[i].st, "user", NULL, 1, 1,
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- all_cpu_charts[i].rd_interrupt = rrddim_add(all_cpu_charts[i].st, "interrupt", NULL, 1, 1,
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- all_cpu_charts[i].rd_idle = rrddim_add(all_cpu_charts[i].st, "idle", NULL, 1, 1,
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_hide(all_cpu_charts[i].st, "idle");
- } else rrdset_next(all_cpu_charts[i].st);
-
- rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_nice, pcpu_cp_time[i * 5 + 1]);
- rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_system, pcpu_cp_time[i * 5 + 2]);
- rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_user, pcpu_cp_time[i * 5 + 0]);
- rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_interrupt, pcpu_cp_time[i * 5 + 3]);
- rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_idle, pcpu_cp_time[i * 5 + 4]);
- rrdset_done(all_cpu_charts[i].st);
- }
- }
-
- old_number_of_cpus = number_of_cpus;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// dev.cpu.temperature
-
-int do_dev_cpu_temperature(int update_every, usec_t dt) {
- (void)dt;
-
- int i;
- static int *mib = NULL;
- static int *pcpu_temperature = NULL;
- static int old_number_of_cpus = 0;
- char char_mib[MAX_INT_DIGITS + 21];
- char char_rd[MAX_INT_DIGITS + 9];
-
- if (unlikely(number_of_cpus != old_number_of_cpus)) {
- pcpu_temperature = reallocz(pcpu_temperature, sizeof(int) * number_of_cpus);
- mib = reallocz(mib, sizeof(int) * number_of_cpus * 4);
- if (unlikely(number_of_cpus > old_number_of_cpus))
- memset(&mib[old_number_of_cpus * 4], 0, sizeof(RRDDIM) * (number_of_cpus - old_number_of_cpus));
- }
- for (i = 0; i < number_of_cpus; i++) {
- if (unlikely(!(mib[i * 4])))
- sprintf(char_mib, "dev.cpu.%d.temperature", i);
- if (unlikely(getsysctl_simple(char_mib, &mib[i * 4], 4, &pcpu_temperature[i], sizeof(int)))) {
- error("DISABLED: cpu.temperature chart");
- error("DISABLED: dev.cpu.temperature module");
- return 1;
- }
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st;
- static RRDDIM **rd_pcpu_temperature;
-
- if (unlikely(number_of_cpus != old_number_of_cpus)) {
- rd_pcpu_temperature = reallocz(rd_pcpu_temperature, sizeof(RRDDIM) * number_of_cpus);
- if (unlikely(number_of_cpus > old_number_of_cpus))
- memset(&rd_pcpu_temperature[old_number_of_cpus], 0, sizeof(RRDDIM) * (number_of_cpus - old_number_of_cpus));
- }
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "cpu",
- "temperature",
- NULL,
- "temperature",
- "cpu.temperatute",
- "Core temperature",
- "Celsius",
- "freebsd",
- "dev.cpu.temperature",
- 1050,
- update_every,
- RRDSET_TYPE_LINE
- );
- }
- else rrdset_next(st);
-
- for (i = 0; i < number_of_cpus; i++) {
- if (unlikely(!rd_pcpu_temperature[i])) {
- sprintf(char_rd, "cpu%d.temp", i);
- rd_pcpu_temperature[i] = rrddim_add(st, char_rd, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
-
- rrddim_set_by_pointer(st, rd_pcpu_temperature[i], (collected_number) ((double)pcpu_temperature[i] / 10 - 273.15));
- }
-
- rrdset_done(st);
-
- old_number_of_cpus = number_of_cpus;
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// dev.cpu.0.freq
-
-int do_dev_cpu_0_freq(int update_every, usec_t dt) {
- (void)dt;
- static int mib[4] = {0, 0, 0, 0};
- int cpufreq;
-
- if (unlikely(GETSYSCTL_SIMPLE("dev.cpu.0.freq", mib, cpufreq))) {
- error("DISABLED: cpu.scaling_cur_freq chart");
- error("DISABLED: dev.cpu.0.freq module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "cpu",
- "scaling_cur_freq",
- NULL,
- "cpufreq",
- NULL,
- "Current CPU Scaling Frequency",
- "MHz",
- "freebsd",
- "dev.cpu.0.freq",
- 5003,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "frequency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, cpufreq);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// hw.intrcnt
-
-int do_hw_intcnt(int update_every, usec_t dt) {
- (void)dt;
- static int mib_hw_intrcnt[2] = {0, 0};
- size_t intrcnt_size = 0;
- unsigned long i;
-
- if (unlikely(GETSYSCTL_SIZE("hw.intrcnt", mib_hw_intrcnt, intrcnt_size))) {
- error("DISABLED: system.intr chart");
- error("DISABLED: system.interrupts chart");
- error("DISABLED: hw.intrcnt module");
- return 1;
- } else {
- unsigned long nintr = 0;
- static unsigned long old_nintr = 0;
- static unsigned long *intrcnt = NULL;
- unsigned long long totalintr = 0;
-
- nintr = intrcnt_size / sizeof(u_long);
- if (unlikely(nintr != old_nintr))
- intrcnt = reallocz(intrcnt, nintr * sizeof(u_long));
- if (unlikely(GETSYSCTL_WSIZE("hw.intrcnt", mib_hw_intrcnt, intrcnt, nintr * sizeof(u_long)))) {
- error("DISABLED: system.intr chart");
- error("DISABLED: system.interrupts chart");
- error("DISABLED: hw.intrcnt module");
- return 1;
- } else {
- for (i = 0; i < nintr; i++)
- totalintr += intrcnt[i];
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_intr = NULL;
- static RRDDIM *rd_intr = NULL;
-
- if (unlikely(!st_intr)) {
- st_intr = rrdset_create_localhost(
- "system",
- "intr",
- NULL,
- "interrupts",
- NULL,
- "Total Hardware Interrupts",
- "interrupts/s",
- "freebsd",
- "hw.intrcnt",
- 900,
- update_every,
- RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL);
-
- rd_intr = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st_intr);
-
- rrddim_set_by_pointer(st_intr, rd_intr, totalintr);
- rrdset_done(st_intr);
-
- // --------------------------------------------------------------------
-
- size_t size;
- static int mib_hw_intrnames[2] = {0, 0};
- static char *intrnames = NULL;
-
- size = nintr * (MAXCOMLEN + 1);
- if (unlikely(nintr != old_nintr))
- intrnames = reallocz(intrnames, size);
- if (unlikely(GETSYSCTL_WSIZE("hw.intrnames", mib_hw_intrnames, intrnames, size))) {
- error("DISABLED: system.intr chart");
- error("DISABLED: system.interrupts chart");
- error("DISABLED: hw.intrcnt module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_interrupts = NULL;
- void *p;
-
- if (unlikely(!st_interrupts))
- st_interrupts = rrdset_create_localhost(
- "system",
- "interrupts",
- NULL,
- "interrupts",
- NULL,
- "System interrupts",
- "interrupts/s",
- "freebsd",
- "hw.intrcnt",
- 1000,
- update_every,
- RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_interrupts);
-
- for (i = 0; i < nintr; i++) {
- p = intrnames + i * (MAXCOMLEN + 1);
- if (unlikely((intrcnt[i] != 0) && (*(char *) p != 0))) {
- RRDDIM *rd_interrupts = rrddim_find(st_interrupts, p);
-
- if (unlikely(!rd_interrupts))
- rd_interrupts = rrddim_add(st_interrupts, p, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_interrupts, rd_interrupts, intrcnt[i]);
- }
- }
- rrdset_done(st_interrupts);
- }
- }
-
- old_nintr = nintr;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.stats.sys.v_intr
-
-int do_vm_stats_sys_v_intr(int update_every, usec_t dt) {
- (void)dt;
- static int mib[4] = {0, 0, 0, 0};
- u_int int_number;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.sys.v_intr", mib, int_number))) {
- error("DISABLED: system.dev_intr chart");
- error("DISABLED: vm.stats.sys.v_intr module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "dev_intr",
- NULL,
- "interrupts",
- NULL,
- "Device Interrupts",
- "interrupts/s",
- "freebsd",
- "vm.stats.sys.v_intr",
- 1000,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, int_number);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.stats.sys.v_soft
-
-int do_vm_stats_sys_v_soft(int update_every, usec_t dt) {
- (void)dt;
- static int mib[4] = {0, 0, 0, 0};
- u_int soft_intr_number;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.sys.v_soft", mib, soft_intr_number))) {
- error("DISABLED: system.dev_intr chart");
- error("DISABLED: vm.stats.sys.v_soft module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "soft_intr",
- NULL,
- "interrupts",
- NULL,
- "Software Interrupts",
- "interrupts/s",
- "freebsd",
- "vm.stats.sys.v_soft",
- 1100,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, soft_intr_number);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.stats.sys.v_swtch
-
-int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) {
- (void)dt;
- static int mib[4] = {0, 0, 0, 0};
- u_int ctxt_number;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.sys.v_swtch", mib, ctxt_number))) {
- error("DISABLED: system.ctxt chart");
- error("DISABLED: vm.stats.sys.v_swtch module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "ctxt",
- NULL,
- "processes",
- NULL,
- "CPU Context Switches",
- "context switches/s",
- "freebsd",
- "vm.stats.sys.v_swtch",
- 800,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, ctxt_number);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.stats.vm.v_forks
-
-int do_vm_stats_sys_v_forks(int update_every, usec_t dt) {
- (void)dt;
- static int mib[4] = {0, 0, 0, 0};
- u_int forks_number;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_forks", mib, forks_number))) {
- error("DISABLED: system.forks chart");
- error("DISABLED: vm.stats.sys.v_swtch module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "forks",
- NULL,
- "processes",
- NULL,
- "Started Processes",
- "processes/s",
- "freebsd",
- "vm.stats.sys.v_swtch",
- 700,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd = rrddim_add(st, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, forks_number);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.swap_info
-
-int do_vm_swap_info(int update_every, usec_t dt) {
- (void)dt;
- static int mib[3] = {0, 0, 0};
-
- if (unlikely(getsysctl_mib("vm.swap_info", mib, 2))) {
- error("DISABLED: system.swap chart");
- error("DISABLED: vm.swap_info module");
- return 1;
- } else {
- int i;
- struct xswdev xsw;
- struct total_xsw {
- collected_number bytes_used;
- collected_number bytes_total;
- } total_xsw = {0, 0};
-
- for (i = 0; ; i++) {
- size_t size;
-
- mib[2] = i;
- size = sizeof(xsw);
- if (unlikely(sysctl(mib, 3, &xsw, &size, NULL, 0) == -1 )) {
- if (unlikely(errno != ENOENT)) {
- error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
- error("DISABLED: system.swap chart");
- error("DISABLED: vm.swap_info module");
- return 1;
- } else {
- if (unlikely(size != sizeof(xsw))) {
- error("FREEBSD: sysctl(%s...) expected %lu, got %lu", "vm.swap_info", (unsigned long)sizeof(xsw), (unsigned long)size);
- error("DISABLED: system.swap chart");
- error("DISABLED: vm.swap_info module");
- return 1;
- } else break;
- }
- }
- total_xsw.bytes_used += xsw.xsw_used;
- total_xsw.bytes_total += xsw.xsw_nblks;
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_free = NULL, *rd_used = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "swap",
- NULL,
- "swap",
- NULL,
- "System Swap",
- "MB",
- "freebsd",
- "vm.swap_info",
- 201,
- update_every,
- RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_free = rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- rd_used = rrddim_add(st, "used", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_free, total_xsw.bytes_total - total_xsw.bytes_used);
- rrddim_set_by_pointer(st, rd_used, total_xsw.bytes_used);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// system.ram
-
-int do_system_ram(int update_every, usec_t dt) {
- (void)dt;
- static int mib_active_count[4] = {0, 0, 0, 0}, mib_inactive_count[4] = {0, 0, 0, 0}, mib_wire_count[4] = {0, 0, 0, 0},
- mib_cache_count[4] = {0, 0, 0, 0}, mib_vfs_bufspace[2] = {0, 0}, mib_free_count[4] = {0, 0, 0, 0};
- vmmeter_t vmmeter_data;
- int vfs_bufspace_count;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_active_count", mib_active_count, vmmeter_data.v_active_count) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_inactive_count", mib_inactive_count, vmmeter_data.v_inactive_count) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_wire_count", mib_wire_count, vmmeter_data.v_wire_count) ||
-#if __FreeBSD_version < 1200016
- GETSYSCTL_SIMPLE("vm.stats.vm.v_cache_count", mib_cache_count, vmmeter_data.v_cache_count) ||
-#endif
- GETSYSCTL_SIMPLE("vfs.bufspace", mib_vfs_bufspace, vfs_bufspace_count) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_free_count", mib_free_count, vmmeter_data.v_free_count))) {
- error("DISABLED: system.ram chart");
- error("DISABLED: system.ram module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_free = NULL, *rd_active = NULL, *rd_inactive = NULL,
- *rd_wired = NULL, *rd_cache = NULL, *rd_buffers = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "ram",
- NULL,
- "ram",
- NULL,
- "System RAM",
- "MB",
- "freebsd",
- "system.ram",
- 200,
- update_every,
- RRDSET_TYPE_STACKED
- );
-
- rd_free = rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- rd_active = rrddim_add(st, "active", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- rd_inactive = rrddim_add(st, "inactive", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- rd_wired = rrddim_add(st, "wired", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
-#if __FreeBSD_version < 1200016
- rd_cache = rrddim_add(st, "cache", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
-#endif
- rd_buffers = rrddim_add(st, "buffers", NULL, 1, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_free, vmmeter_data.v_free_count);
- rrddim_set_by_pointer(st, rd_active, vmmeter_data.v_active_count);
- rrddim_set_by_pointer(st, rd_inactive, vmmeter_data.v_inactive_count);
- rrddim_set_by_pointer(st, rd_wired, vmmeter_data.v_wire_count);
-#if __FreeBSD_version < 1200016
- rrddim_set_by_pointer(st, rd_cache, vmmeter_data.v_cache_count);
-#endif
- rrddim_set_by_pointer(st, rd_buffers, vfs_bufspace_count);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.stats.vm.v_swappgs
-
-int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) {
- (void)dt;
- static int mib_swappgsin[4] = {0, 0, 0, 0}, mib_swappgsout[4] = {0, 0, 0, 0};
- vmmeter_t vmmeter_data;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_swappgsin", mib_swappgsin, vmmeter_data.v_swappgsin) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_swappgsout", mib_swappgsout, vmmeter_data.v_swappgsout))) {
- error("DISABLED: system.swapio chart");
- error("DISABLED: vm.stats.vm.v_swappgs module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "swapio",
- NULL,
- "swap",
- NULL,
- "Swap I/O",
- "kilobytes/s",
- "freebsd",
- "vm.stats.vm.v_swappgs",
- 250,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st, "in", NULL, system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "out", NULL, -system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, vmmeter_data.v_swappgsin);
- rrddim_set_by_pointer(st, rd_out, vmmeter_data.v_swappgsout);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// vm.stats.vm.v_pgfaults
-
-int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) {
- (void)dt;
- static int mib_vm_faults[4] = {0, 0, 0, 0}, mib_io_faults[4] = {0, 0, 0, 0}, mib_cow_faults[4] = {0, 0, 0, 0},
- mib_cow_optim[4] = {0, 0, 0, 0}, mib_intrans[4] = {0, 0, 0, 0};
- vmmeter_t vmmeter_data;
-
- if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_vm_faults", mib_vm_faults, vmmeter_data.v_vm_faults) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_io_faults", mib_io_faults, vmmeter_data.v_io_faults) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_cow_faults", mib_cow_faults, vmmeter_data.v_cow_faults) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_cow_optim", mib_cow_optim, vmmeter_data.v_cow_optim) ||
- GETSYSCTL_SIMPLE("vm.stats.vm.v_intrans", mib_intrans, vmmeter_data.v_intrans))) {
- error("DISABLED: mem.pgfaults chart");
- error("DISABLED: vm.stats.vm.v_pgfaults module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_memory = NULL, *rd_io_requiring = NULL, *rd_cow = NULL,
- *rd_cow_optimized = NULL, *rd_in_transit = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "mem",
- "pgfaults",
- NULL,
- "system",
- NULL,
- "Memory Page Faults",
- "page faults/s",
- "freebsd",
- "vm.stats.vm.v_pgfaults",
- NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_memory = rrddim_add(st, "memory", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_io_requiring = rrddim_add(st, "io_requiring", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_cow = rrddim_add(st, "cow", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_cow_optimized = rrddim_add(st, "cow_optimized", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_transit = rrddim_add(st, "in_transit", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_memory, vmmeter_data.v_vm_faults);
- rrddim_set_by_pointer(st, rd_io_requiring, vmmeter_data.v_io_faults);
- rrddim_set_by_pointer(st, rd_cow, vmmeter_data.v_cow_faults);
- rrddim_set_by_pointer(st, rd_cow_optimized, vmmeter_data.v_cow_optim);
- rrddim_set_by_pointer(st, rd_in_transit, vmmeter_data.v_intrans);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kern.ipc.sem
-
-int do_kern_ipc_sem(int update_every, usec_t dt) {
- (void)dt;
- static int mib_semmni[3] = {0, 0, 0}, mib_sema[3] = {0, 0, 0};
- struct ipc_sem {
- int semmni;
- collected_number sets;
- collected_number semaphores;
- } ipc_sem = {0, 0, 0};
-
- if (unlikely(GETSYSCTL_SIMPLE("kern.ipc.semmni", mib_semmni, ipc_sem.semmni))) {
- error("DISABLED: system.ipc_semaphores chart");
- error("DISABLED: system.ipc_semaphore_arrays chart");
- error("DISABLED: kern.ipc.sem module");
- return 1;
- } else {
- static struct semid_kernel *ipc_sem_data = NULL;
- static int old_semmni = 0;
-
- if (unlikely(ipc_sem.semmni != old_semmni)) {
- ipc_sem_data = reallocz(ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni);
- old_semmni = ipc_sem.semmni;
- }
- if (unlikely(GETSYSCTL_WSIZE("kern.ipc.sema", mib_sema, ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni))) {
- error("DISABLED: system.ipc_semaphores chart");
- error("DISABLED: system.ipc_semaphore_arrays chart");
- error("DISABLED: kern.ipc.sem module");
- return 1;
- } else {
- int i;
-
- for (i = 0; i < ipc_sem.semmni; i++) {
- if (unlikely(ipc_sem_data[i].u.sem_perm.mode & SEM_ALLOC)) {
- ipc_sem.sets += 1;
- ipc_sem.semaphores += ipc_sem_data[i].u.sem_nsems;
- }
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_semaphores = NULL, *st_semaphore_arrays = NULL;
- static RRDDIM *rd_semaphores = NULL, *rd_semaphore_arrays = NULL;
-
- if (unlikely(!st_semaphores)) {
- st_semaphores = rrdset_create_localhost(
- "system",
- "ipc_semaphores",
- NULL,
- "ipc semaphores",
- NULL,
- "IPC Semaphores",
- "semaphores",
- "freebsd",
- "kern.ipc.sem",
- 1000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_semaphores = rrddim_add(st_semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_semaphores);
-
- rrddim_set_by_pointer(st_semaphores, rd_semaphores, ipc_sem.semaphores);
- rrdset_done(st_semaphores);
-
- // --------------------------------------------------------------------
-
- if (unlikely(!st_semaphore_arrays)) {
- st_semaphore_arrays = rrdset_create_localhost(
- "system",
- "ipc_semaphore_arrays",
- NULL,
- "ipc semaphores",
- NULL,
- "IPC Semaphore Arrays",
- "arrays",
- "freebsd",
- "kern.ipc.sem",
- 1000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_semaphore_arrays = rrddim_add(st_semaphore_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_semaphore_arrays);
-
- rrddim_set_by_pointer(st_semaphore_arrays, rd_semaphore_arrays, ipc_sem.sets);
- rrdset_done(st_semaphore_arrays);
- }
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kern.ipc.shm
-
-int do_kern_ipc_shm(int update_every, usec_t dt) {
- (void)dt;
- static int mib_shmmni[3] = {0, 0, 0}, mib_shmsegs[3] = {0, 0, 0};
- struct ipc_shm {
- u_long shmmni;
- collected_number segs;
- collected_number segsize;
- } ipc_shm = {0, 0, 0};
-
- if (unlikely(GETSYSCTL_SIMPLE("kern.ipc.shmmni", mib_shmmni, ipc_shm.shmmni))) {
- error("DISABLED: system.ipc_shared_mem_segs chart");
- error("DISABLED: system.ipc_shared_mem_size chart");
- error("DISABLED: kern.ipc.shmmodule");
- return 1;
- } else {
- static struct shmid_kernel *ipc_shm_data = NULL;
- static u_long old_shmmni = 0;
-
- if (unlikely(ipc_shm.shmmni != old_shmmni)) {
- ipc_shm_data = reallocz(ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni);
- old_shmmni = ipc_shm.shmmni;
- }
- if (unlikely(
- GETSYSCTL_WSIZE("kern.ipc.shmsegs", mib_shmsegs, ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni))) {
- error("DISABLED: system.ipc_shared_mem_segs chart");
- error("DISABLED: system.ipc_shared_mem_size chart");
- error("DISABLED: kern.ipc.shmmodule");
- return 1;
- } else {
- unsigned long i;
-
- for (i = 0; i < ipc_shm.shmmni; i++) {
- if (unlikely(ipc_shm_data[i].u.shm_perm.mode & 0x0800)) {
- ipc_shm.segs += 1;
- ipc_shm.segsize += ipc_shm_data[i].u.shm_segsz;
- }
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_segs = NULL, *st_size = NULL;
- static RRDDIM *rd_segments = NULL, *rd_allocated = NULL;
-
- if (unlikely(!st_segs)) {
- st_segs = rrdset_create_localhost(
- "system",
- "ipc_shared_mem_segs",
- NULL,
- "ipc shared memory",
- NULL,
- "IPC Shared Memory Segments",
- "segments",
- "freebsd",
- "kern.ipc.shm",
- 1000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_segments = rrddim_add(st_segs, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_segs);
-
- rrddim_set_by_pointer(st_segs, rd_segments, ipc_shm.segs);
- rrdset_done(st_segs);
-
- // --------------------------------------------------------------------
-
- if (unlikely(!st_size)) {
- st_size = rrdset_create_localhost(
- "system",
- "ipc_shared_mem_size",
- NULL,
- "ipc shared memory",
- NULL,
- "IPC Shared Memory Segments Size",
- "kilobytes",
- "freebsd",
- "kern.ipc.shm",
- 1000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, KILO_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_size);
-
- rrddim_set_by_pointer(st_size, rd_allocated, ipc_shm.segsize);
- rrdset_done(st_size);
- }
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// kern.ipc.msq
-
-int do_kern_ipc_msq(int update_every, usec_t dt) {
- (void)dt;
- static int mib_msgmni[3] = {0, 0, 0}, mib_msqids[3] = {0, 0, 0};
- struct ipc_msq {
- int msgmni;
- collected_number queues;
- collected_number messages;
- collected_number usedsize;
- collected_number allocsize;
- } ipc_msq = {0, 0, 0, 0, 0};
-
- if (unlikely(GETSYSCTL_SIMPLE("kern.ipc.msgmni", mib_msgmni, ipc_msq.msgmni))) {
- error("DISABLED: system.ipc_msq_queues chart");
- error("DISABLED: system.ipc_msq_messages chart");
- error("DISABLED: system.ipc_msq_size chart");
- error("DISABLED: kern.ipc.msg module");
- return 1;
- } else {
- static struct msqid_kernel *ipc_msq_data = NULL;
- static int old_msgmni = 0;
-
- if (unlikely(ipc_msq.msgmni != old_msgmni)) {
- ipc_msq_data = reallocz(ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni);
- old_msgmni = ipc_msq.msgmni;
- }
- if (unlikely(
- GETSYSCTL_WSIZE("kern.ipc.msqids", mib_msqids, ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni))) {
- error("DISABLED: system.ipc_msq_queues chart");
- error("DISABLED: system.ipc_msq_messages chart");
- error("DISABLED: system.ipc_msq_size chart");
- error("DISABLED: kern.ipc.msg module");
- return 1;
- } else {
- int i;
-
- for (i = 0; i < ipc_msq.msgmni; i++) {
- if (unlikely(ipc_msq_data[i].u.msg_qbytes != 0)) {
- ipc_msq.queues += 1;
- ipc_msq.messages += ipc_msq_data[i].u.msg_qnum;
- ipc_msq.usedsize += ipc_msq_data[i].u.msg_cbytes;
- ipc_msq.allocsize += ipc_msq_data[i].u.msg_qbytes;
- }
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_queues = NULL, *st_messages = NULL, *st_size = NULL;
- static RRDDIM *rd_queues = NULL, *rd_messages = NULL, *rd_allocated = NULL, *rd_used = NULL;
-
- if (unlikely(!st_queues)) {
- st_queues = rrdset_create_localhost(
- "system",
- "ipc_msq_queues",
- NULL,
- "ipc message queues",
- NULL,
- "Number of IPC Message Queues",
- "queues",
- "freebsd",
- "kern.ipc.msq",
- 990,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_queues = rrddim_add(st_queues, "queues", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_queues);
-
- rrddim_set_by_pointer(st_queues, rd_queues, ipc_msq.queues);
- rrdset_done(st_queues);
-
- // --------------------------------------------------------------------
-
- if (unlikely(!st_messages)) {
- st_messages = rrdset_create_localhost(
- "system",
- "ipc_msq_messages",
- NULL,
- "ipc message queues",
- NULL,
- "Number of Messages in IPC Message Queues",
- "messages",
- "freebsd",
- "kern.ipc.msq",
- 1000,
- update_every,
- RRDSET_TYPE_AREA
- );
-
- rd_messages = rrddim_add(st_messages, "messages", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_messages);
-
- rrddim_set_by_pointer(st_messages, rd_messages, ipc_msq.messages);
- rrdset_done(st_messages);
-
- // --------------------------------------------------------------------
-
- if (unlikely(!st_size)) {
- st_size = rrdset_create_localhost(
- "system",
- "ipc_msq_size",
- NULL,
- "ipc message queues",
- NULL,
- "Size of IPC Message Queues",
- "bytes",
- "freebsd",
- "kern.ipc.msq",
- 1100,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_used = rrddim_add(st_size, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_size);
-
- rrddim_set_by_pointer(st_size, rd_allocated, ipc_msq.allocsize);
- rrddim_set_by_pointer(st_size, rd_used, ipc_msq.usedsize);
- rrdset_done(st_size);
- }
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// uptime
-
-int do_uptime(int update_every, usec_t dt) {
- (void)dt;
- struct timespec up_time;
-
- clock_gettime(CLOCK_UPTIME, &up_time);
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "uptime",
- NULL,
- "uptime",
- NULL,
- "System Uptime",
- "seconds",
- "freebsd",
- "uptime",
- 1000,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, up_time.tv_sec);
- rrdset_done(st);
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.isr
-
-int do_net_isr(int update_every, usec_t dt) {
- (void)dt;
- static int do_netisr = -1, do_netisr_per_core = -1;
-
- if (unlikely(do_netisr == -1)) {
- do_netisr = config_get_boolean("plugin:freebsd:net.isr", "netisr", 1);
- do_netisr_per_core = config_get_boolean("plugin:freebsd:net.isr", "netisr per core", 1);
- }
-
- static int mib_workstream[3] = {0, 0, 0}, mib_work[3] = {0, 0, 0};
- int common_error = 0;
- size_t netisr_workstream_size = 0, netisr_work_size = 0;
- unsigned long num_netisr_workstreams = 0, num_netisr_works = 0;
- static struct sysctl_netisr_workstream *netisr_workstream = NULL;
- static struct sysctl_netisr_work *netisr_work = NULL;
- static struct netisr_stats {
- collected_number dispatched;
- collected_number hybrid_dispatched;
- collected_number qdrops;
- collected_number queued;
- } *netisr_stats = NULL;
-
- if (likely(do_netisr || do_netisr_per_core)) {
- if (unlikely(GETSYSCTL_SIZE("net.isr.workstream", mib_workstream, netisr_workstream_size))) {
- common_error = 1;
- } else if (unlikely(GETSYSCTL_SIZE("net.isr.work", mib_work, netisr_work_size))) {
- common_error = 1;
- } else {
- static size_t old_netisr_workstream_size = 0;
-
- num_netisr_workstreams = netisr_workstream_size / sizeof(struct sysctl_netisr_workstream);
- if (unlikely(netisr_workstream_size != old_netisr_workstream_size)) {
- netisr_workstream = reallocz(netisr_workstream,
- num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream));
- old_netisr_workstream_size = netisr_workstream_size;
- }
- if (unlikely(GETSYSCTL_WSIZE("net.isr.workstream", mib_workstream, netisr_workstream,
- num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream)))){
- common_error = 1;
- } else {
- static size_t old_netisr_work_size = 0;
-
- num_netisr_works = netisr_work_size / sizeof(struct sysctl_netisr_work);
- if (unlikely(netisr_work_size != old_netisr_work_size)) {
- netisr_work = reallocz(netisr_work, num_netisr_works * sizeof(struct sysctl_netisr_work));
- old_netisr_work_size = netisr_work_size;
- }
- if (unlikely(GETSYSCTL_WSIZE("net.isr.work", mib_work, netisr_work,
- num_netisr_works * sizeof(struct sysctl_netisr_work)))){
- common_error = 1;
- }
- }
- }
- if (unlikely(common_error)) {
- do_netisr = 0;
- error("DISABLED: system.softnet_stat chart");
- do_netisr_per_core = 0;
- error("DISABLED: system.cpuX_softnet_stat chart");
- common_error = 0;
- error("DISABLED: net.isr module");
- return 1;
- } else {
- unsigned long i, n;
- int j;
- static int old_number_of_cpus = 0;
-
- if (unlikely(number_of_cpus != old_number_of_cpus)) {
- netisr_stats = reallocz(netisr_stats, (number_of_cpus + 1) * sizeof(struct netisr_stats));
- old_number_of_cpus = number_of_cpus;
- }
- memset(netisr_stats, 0, (number_of_cpus + 1) * sizeof(struct netisr_stats));
- for (i = 0; i < num_netisr_workstreams; i++) {
- for (n = 0; n < num_netisr_works; n++) {
- if (netisr_workstream[i].snws_wsid == netisr_work[n].snw_wsid) {
- netisr_stats[netisr_workstream[i].snws_cpu].dispatched += netisr_work[n].snw_dispatched;
- netisr_stats[netisr_workstream[i].snws_cpu].hybrid_dispatched += netisr_work[n].snw_hybrid_dispatched;
- netisr_stats[netisr_workstream[i].snws_cpu].qdrops += netisr_work[n].snw_qdrops;
- netisr_stats[netisr_workstream[i].snws_cpu].queued += netisr_work[n].snw_queued;
- }
- }
- }
- for (j = 0; j < number_of_cpus; j++) {
- netisr_stats[number_of_cpus].dispatched += netisr_stats[j].dispatched;
- netisr_stats[number_of_cpus].hybrid_dispatched += netisr_stats[j].hybrid_dispatched;
- netisr_stats[number_of_cpus].qdrops += netisr_stats[j].qdrops;
- netisr_stats[number_of_cpus].queued += netisr_stats[j].queued;
- }
- }
- } else {
- error("DISABLED: net.isr module");
- return 1;
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_netisr)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_dispatched = NULL, *rd_hybrid_dispatched = NULL, *rd_qdrops = NULL, *rd_queued = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system",
- "softnet_stat",
- NULL,
- "softnet_stat",
- NULL,
- "System softnet_stat",
- "events/s",
- "freebsd",
- "net.isr",
- 955,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_dispatched = rrddim_add(st, "dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_hybrid_dispatched = rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_qdrops = rrddim_add(st, "qdrops", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_queued = rrddim_add(st, "queued", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_dispatched, netisr_stats[number_of_cpus].dispatched);
- rrddim_set_by_pointer(st, rd_hybrid_dispatched, netisr_stats[number_of_cpus].hybrid_dispatched);
- rrddim_set_by_pointer(st, rd_qdrops, netisr_stats[number_of_cpus].qdrops);
- rrddim_set_by_pointer(st, rd_queued, netisr_stats[number_of_cpus].queued);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_netisr_per_core)) {
- static struct softnet_chart {
- char netisr_cpuid[MAX_INT_DIGITS + 17];
- RRDSET *st;
- RRDDIM *rd_dispatched;
- RRDDIM *rd_hybrid_dispatched;
- RRDDIM *rd_qdrops;
- RRDDIM *rd_queued;
- } *all_softnet_charts = NULL;
- static int old_number_of_cpus = 0;
- int i;
-
- if(unlikely(number_of_cpus > old_number_of_cpus)) {
- all_softnet_charts = reallocz(all_softnet_charts, sizeof(struct softnet_chart) * number_of_cpus);
- memset(&all_softnet_charts[old_number_of_cpus], 0, sizeof(struct softnet_chart) * (number_of_cpus - old_number_of_cpus));
- old_number_of_cpus = number_of_cpus;
- }
-
- for (i = 0; i < number_of_cpus ;i++) {
- snprintfz(all_softnet_charts[i].netisr_cpuid, MAX_INT_DIGITS + 17, "cpu%d_softnet_stat", i);
-
- if (unlikely(!all_softnet_charts[i].st)) {
- all_softnet_charts[i].st = rrdset_create_localhost(
- "cpu",
- all_softnet_charts[i].netisr_cpuid,
- NULL,
- "softnet_stat",
- NULL,
- "Per CPU netisr statistics",
- "events/s",
- "freebsd",
- "net.isr",
- 1101 + i,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- all_softnet_charts[i].rd_dispatched = rrddim_add(all_softnet_charts[i].st, "dispatched",
- NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- all_softnet_charts[i].rd_hybrid_dispatched = rrddim_add(all_softnet_charts[i].st, "hybrid_dispatched",
- NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- all_softnet_charts[i].rd_qdrops = rrddim_add(all_softnet_charts[i].st, "qdrops",
- NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- all_softnet_charts[i].rd_queued = rrddim_add(all_softnet_charts[i].st, "queued",
- NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(all_softnet_charts[i].st);
-
- rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_dispatched,
- netisr_stats[i].dispatched);
- rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_hybrid_dispatched,
- netisr_stats[i].hybrid_dispatched);
- rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_qdrops,
- netisr_stats[i].qdrops);
- rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_queued,
- netisr_stats[i].queued);
- rrdset_done(all_softnet_charts[i].st);
- }
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet.tcp.states
-
-int do_net_inet_tcp_states(int update_every, usec_t dt) {
- (void)dt;
- static int mib[4] = {0, 0, 0, 0};
- uint64_t tcps_states[TCP_NSTATES];
-
- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
- if (unlikely(GETSYSCTL_SIMPLE("net.inet.tcp.states", mib, tcps_states))) {
- error("DISABLED: ipv4.tcpsock chart");
- error("DISABLED: net.inet.tcp.states module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcpsock",
- NULL,
- "tcp",
- NULL,
- "IPv4 TCP Connections",
- "active connections",
- "freebsd",
- "net.inet.tcp.states",
- 2500,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, tcps_states[TCPS_ESTABLISHED]);
- rrdset_done(st);
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet.tcp.stats
-
-int do_net_inet_tcp_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcpext_connaborts = -1, do_tcpext_ofo = -1,
- do_tcpext_syncookies = -1, do_tcpext_listen = -1, do_ecn = -1;
-
- if (unlikely(do_tcp_packets == -1)) {
- do_tcp_packets = config_get_boolean("plugin:freebsd:net.inet.tcp.stats", "ipv4 TCP packets", 1);
- do_tcp_errors = config_get_boolean("plugin:freebsd:net.inet.tcp.stats", "ipv4 TCP errors", 1);
- do_tcp_handshake = config_get_boolean("plugin:freebsd:net.inet.tcp.stats", "ipv4 TCP handshake issues", 1);
- do_tcpext_connaborts = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP connection aborts",
- CONFIG_BOOLEAN_AUTO);
- do_tcpext_ofo = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP out-of-order queue",
- CONFIG_BOOLEAN_AUTO);
- do_tcpext_syncookies = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP SYN cookies",
- CONFIG_BOOLEAN_AUTO);
- do_tcpext_listen = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP listen issues",
- CONFIG_BOOLEAN_AUTO);
- do_ecn = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "ECN packets",
- CONFIG_BOOLEAN_AUTO);
- }
-
- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
- if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo ||
- do_tcpext_syncookies || do_tcpext_listen || do_ecn)) {
- static int mib[4] = {0, 0, 0, 0};
- struct tcpstat tcpstat;
-
- if (unlikely(GETSYSCTL_SIMPLE("net.inet.tcp.stats", mib, tcpstat))) {
- do_tcp_packets = 0;
- error("DISABLED: ipv4.tcppackets chart");
- do_tcp_errors = 0;
- error("DISABLED: ipv4.tcperrors chart");
- do_tcp_handshake = 0;
- error("DISABLED: ipv4.tcphandshake chart");
- do_tcpext_connaborts = 0;
- error("DISABLED: ipv4.tcpconnaborts chart");
- do_tcpext_ofo = 0;
- error("DISABLED: ipv4.tcpofo chart");
- do_tcpext_syncookies = 0;
- error("DISABLED: ipv4.tcpsyncookies chart");
- do_tcpext_listen = 0;
- error("DISABLED: ipv4.tcplistenissues chart");
- do_ecn = 0;
- error("DISABLED: ipv4.ecnpkts chart");
- error("DISABLED: net.inet.tcp.stats module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- if (likely(do_tcp_packets)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_segs = NULL, *rd_out_segs = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcppackets",
- NULL,
- "tcp",
- NULL,
- "IPv4 TCP Packets",
- "packets/s",
- "freebsd",
- "net.inet.tcp.stats",
- 2600,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in_segs = rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_segs = rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_segs, tcpstat.tcps_rcvtotal);
- rrddim_set_by_pointer(st, rd_out_segs, tcpstat.tcps_sndtotal);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_tcp_errors)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_errs = NULL, *rd_in_csum_errs = NULL, *rd_retrans_segs = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcperrors",
- NULL,
- "tcp",
- NULL,
- "IPv4 TCP Errors",
- "packets/s",
- "freebsd",
- "net.inet.tcp.stats",
- 2700,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_in_errs = rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_csum_errs = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_retrans_segs = rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
-#if __FreeBSD__ >= 11
- rrddim_set_by_pointer(st, rd_in_errs, tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvreassfull +
- tcpstat.tcps_rcvshort);
-#else
- rrddim_set_by_pointer(st, rd_in_errs, tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
-#endif
- rrddim_set_by_pointer(st, rd_in_csum_errs, tcpstat.tcps_rcvbadsum);
- rrddim_set_by_pointer(st, rd_retrans_segs, tcpstat.tcps_sndrexmitpack);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_tcp_handshake)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_estab_resets = NULL, *rd_active_opens = NULL, *rd_passive_opens = NULL,
- *rd_attempt_fails = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcphandshake",
- NULL,
- "tcp",
- NULL,
- "IPv4 TCP Handshake Issues",
- "events/s",
- "freebsd",
- "net.inet.tcp.stats",
- 2900,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_estab_resets = rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_active_opens = rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_passive_opens = rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_attempt_fails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_estab_resets, tcpstat.tcps_drops);
- rrddim_set_by_pointer(st, rd_active_opens, tcpstat.tcps_connattempt);
- rrddim_set_by_pointer(st, rd_passive_opens, tcpstat.tcps_accepts);
- rrddim_set_by_pointer(st, rd_attempt_fails, tcpstat.tcps_conndrops);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop || tcpstat.tcps_finwait2_drops))) {
- do_tcpext_connaborts = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_on_data = NULL, *rd_on_close = NULL, *rd_on_memory = NULL,
- *rd_on_timeout = NULL, *rd_on_linger = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcpconnaborts",
- NULL,
- "tcp",
- NULL,
- "TCP Connection Aborts",
- "connections/s",
- "freebsd",
- "net.inet.tcp.stats",
- 3010,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_on_data = rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_on_close = rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_on_memory = rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_on_timeout = rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_on_linger = rrddim_add(st, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_on_data, tcpstat.tcps_rcvpackafterwin);
- rrddim_set_by_pointer(st, rd_on_close, tcpstat.tcps_rcvafterclose);
- rrddim_set_by_pointer(st, rd_on_memory, tcpstat.tcps_rcvmemdrop);
- rrddim_set_by_pointer(st, rd_on_timeout, tcpstat.tcps_persistdrop);
- rrddim_set_by_pointer(st, rd_on_linger, tcpstat.tcps_finwait2_drops);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_rcvoopack)) {
- do_tcpext_ofo = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_ofo_queue = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcpofo",
- NULL,
- "tcp",
- NULL,
- "TCP Out-Of-Order Queue",
- "packets/s",
- "freebsd",
- "net.inet.tcp.stats",
- 3050,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_ofo_queue = rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ofo_queue, tcpstat.tcps_rcvoopack);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_tcpext_syncookies == CONFIG_BOOLEAN_YES || (do_tcpext_syncookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) {
- do_tcpext_syncookies = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_recv = NULL, *rd_send = NULL, *rd_failed = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "tcpsyncookies",
- NULL,
- "tcp",
- NULL,
- "TCP SYN Cookies",
- "packets/s",
- "freebsd",
- "net.inet.tcp.stats",
- 3100,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_recv = rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_send = rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_recv, tcpstat.tcps_sc_recvcookie);
- rrddim_set_by_pointer(st, rd_send, tcpstat.tcps_sc_sendcookie);
- rrddim_set_by_pointer(st, rd_failed, tcpstat.tcps_sc_zonefail);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_listendrop)) {
- do_tcpext_listen = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_listen = NULL;
- static RRDDIM *rd_overflows = NULL;
-
- if(unlikely(!st_listen)) {
-
- st_listen = rrdset_create_localhost(
- "ipv4",
- "tcplistenissues",
- NULL,
- "tcp",
- NULL,
- "TCP Listen Socket Issues",
- "packets/s",
- "freebsd",
- "net.inet.tcp.stats",
- 3015,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_listen);
-
- rrddim_set_by_pointer(st_listen, rd_overflows, tcpstat.tcps_listendrop);
-
- rrdset_done(st_listen);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_ce || tcpstat.tcps_ecn_ect0 || tcpstat.tcps_ecn_ect1))) {
- do_ecn = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_ce = NULL, *rd_no_ect = NULL, *rd_ect0 = NULL, *rd_ect1 = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "ecnpkts",
- NULL,
- "ecn",
- NULL,
- "IPv4 ECN Statistics",
- "packets/s",
- "freebsd",
- "net.inet.tcp.stats",
- 8700,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ce = rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_no_ect = rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ect0 = rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ect1 = rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ce, tcpstat.tcps_ecn_ce);
- rrddim_set_by_pointer(st, rd_no_ect, tcpstat.tcps_ecn_ce - (tcpstat.tcps_ecn_ect0 +
- tcpstat.tcps_ecn_ect1));
- rrddim_set_by_pointer(st, rd_ect0, tcpstat.tcps_ecn_ect0);
- rrddim_set_by_pointer(st, rd_ect1, tcpstat.tcps_ecn_ect1);
- rrdset_done(st);
- }
-
- }
- } else {
- error("DISABLED: net.inet.tcp.stats module");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet.udp.stats
-
-int do_net_inet_udp_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_udp_packets = -1, do_udp_errors = -1;
-
- if (unlikely(do_udp_packets == -1)) {
- do_udp_packets = config_get_boolean("plugin:freebsd:net.inet.udp.stats", "ipv4 UDP packets", 1);
- do_udp_errors = config_get_boolean("plugin:freebsd:net.inet.udp.stats", "ipv4 UDP errors", 1);
- }
-
- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
- if (likely(do_udp_packets || do_udp_errors)) {
- static int mib[4] = {0, 0, 0, 0};
- struct udpstat udpstat;
-
- if (unlikely(GETSYSCTL_SIMPLE("net.inet.udp.stats", mib, udpstat))) {
- do_udp_packets = 0;
- error("DISABLED: ipv4.udppackets chart");
- do_udp_errors = 0;
- error("DISABLED: ipv4.udperrors chart");
- error("DISABLED: net.inet.udp.stats module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- if (likely(do_udp_packets)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "udppackets",
- NULL,
- "udp",
- NULL,
- "IPv4 UDP Packets",
- "packets/s",
- "freebsd",
- "net.inet.udp.stats",
- 2601,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, udpstat.udps_ipackets);
- rrddim_set_by_pointer(st, rd_out, udpstat.udps_opackets);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_udp_errors)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_errors = NULL, *rd_no_ports = NULL, *rd_recv_buf_errors = NULL,
- *rd_in_csum_errors = NULL, *rd_ignored_multi = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "udperrors",
- NULL,
- "udp",
- NULL,
- "IPv4 UDP Errors",
- "events/s",
- "freebsd",
- "net.inet.udp.stats",
- 2701,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_in_errors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_no_ports = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_recv_buf_errors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_csum_errors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ignored_multi = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_errors, udpstat.udps_hdrops + udpstat.udps_badlen);
- rrddim_set_by_pointer(st, rd_no_ports, udpstat.udps_noport);
- rrddim_set_by_pointer(st, rd_recv_buf_errors, udpstat.udps_fullsock);
- rrddim_set_by_pointer(st, rd_in_csum_errors, udpstat.udps_badsum + udpstat.udps_nosum);
- rrddim_set_by_pointer(st, rd_ignored_multi, udpstat.udps_filtermcast);
- rrdset_done(st);
- }
- }
- } else {
- error("DISABLED: net.inet.udp.stats module");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet.icmp.stats
-
-int do_net_inet_icmp_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_icmp_packets = -1, do_icmp_errors = -1, do_icmpmsg = -1;
-
- if (unlikely(do_icmp_packets == -1)) {
- do_icmp_packets = config_get_boolean("plugin:freebsd:net.inet.icmp.stats", "ipv4 ICMP packets", 1);
- do_icmp_errors = config_get_boolean("plugin:freebsd:net.inet.icmp.stats", "ipv4 ICMP errors", 1);
- do_icmpmsg = config_get_boolean("plugin:freebsd:net.inet.icmp.stats", "ipv4 ICMP messages", 1);
- }
-
- if (likely(do_icmp_packets || do_icmp_errors || do_icmpmsg)) {
- static int mib[4] = {0, 0, 0, 0};
- struct icmpstat icmpstat;
- int i;
- struct icmp_total {
- u_long msgs_in;
- u_long msgs_out;
- } icmp_total = {0, 0};
-
- if (unlikely(GETSYSCTL_SIMPLE("net.inet.icmp.stats", mib, icmpstat))) {
- do_icmp_packets = 0;
- error("DISABLED: ipv4.icmp chart");
- do_icmp_errors = 0;
- error("DISABLED: ipv4.icmp_errors chart");
- do_icmpmsg = 0;
- error("DISABLED: ipv4.icmpmsg chart");
- error("DISABLED: net.inet.icmp.stats module");
- return 1;
- } else {
- for (i = 0; i <= ICMP_MAXTYPE; i++) {
- icmp_total.msgs_in += icmpstat.icps_inhist[i];
- icmp_total.msgs_out += icmpstat.icps_outhist[i];
- }
- icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmp_packets)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "icmp"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Packets"
- , "packets/s"
- , "freebsd"
- , "net.inet.icmp.stats"
- , 2602
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_in = rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, icmp_total.msgs_in);
- rrddim_set_by_pointer(st, rd_out, icmp_total.msgs_out);
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmp_errors)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_csum = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "icmp_errors"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Errors"
- , "packets/s"
- , "freebsd"
- , "net.inet.icmp.stats"
- , 2603
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_in = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_csum = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, icmpstat.icps_badcode + icmpstat.icps_badlen +
- icmpstat.icps_checksum + icmpstat.icps_tooshort);
- rrddim_set_by_pointer(st, rd_out, icmpstat.icps_error);
- rrddim_set_by_pointer(st, rd_in_csum, icmpstat.icps_checksum);
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmpmsg)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_reps = NULL, *rd_out_reps = NULL, *rd_in = NULL, *rd_out = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "icmpmsg"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Messages"
- , "packets/s"
- , "freebsd"
- , "net.inet.icmp.stats"
- , 2604
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_in_reps = rrddim_add(st, "InEchoReps", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_reps = rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in = rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_reps, icmpstat.icps_inhist[ICMP_ECHOREPLY]);
- rrddim_set_by_pointer(st, rd_out_reps, icmpstat.icps_outhist[ICMP_ECHOREPLY]);
- rrddim_set_by_pointer(st, rd_in, icmpstat.icps_inhist[ICMP_ECHO]);
- rrddim_set_by_pointer(st, rd_out, icmpstat.icps_outhist[ICMP_ECHO]);
-
- rrdset_done(st);
- }
- }
- } else {
- error("DISABLED: net.inet.icmp.stats module");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet.ip.stats
-
-int do_net_inet_ip_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1;
-
- if (unlikely(do_ip_packets == -1)) {
- do_ip_packets = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "ipv4 packets", 1);
- do_ip_fragsout = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "ipv4 fragments sent", 1);
- do_ip_fragsin = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "ipv4 fragments assembly", 1);
- do_ip_errors = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "ipv4 errors", 1);
- }
-
- // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
- if (likely(do_ip_packets || do_ip_fragsout || do_ip_fragsin || do_ip_errors)) {
- static int mib[4] = {0, 0, 0, 0};
- struct ipstat ipstat;
-
- if (unlikely(GETSYSCTL_SIMPLE("net.inet.ip.stats", mib, ipstat))) {
- do_ip_packets = 0;
- error("DISABLED: ipv4.packets chart");
- do_ip_fragsout = 0;
- error("DISABLED: ipv4.fragsout chart");
- do_ip_fragsin = 0;
- error("DISABLED: ipv4.fragsin chart");
- do_ip_errors = 0;
- error("DISABLED: ipv4.errors chart");
- error("DISABLED: net.inet.ip.stats module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_packets)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_receives = NULL, *rd_out_requests = NULL, *rd_forward_datagrams = NULL,
- *rd_in_delivers = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "packets",
- NULL,
- "packets",
- NULL,
- "IPv4 Packets",
- "packets/s",
- "freebsd",
- "net.inet.ip.stats",
- 3000,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in_receives = rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_requests = rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_forward_datagrams = rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_delivers = rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_receives, ipstat.ips_total);
- rrddim_set_by_pointer(st, rd_out_requests, ipstat.ips_localout);
- rrddim_set_by_pointer(st, rd_forward_datagrams, ipstat.ips_forward);
- rrddim_set_by_pointer(st, rd_in_delivers, ipstat.ips_delivered);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_fragsout)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_ok = NULL, *rd_fails = NULL, *rd_created = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "fragsout",
- NULL,
- "fragments",
- NULL,
- "IPv4 Fragments Sent",
- "packets/s",
- "freebsd",
- "net.inet.ip.stats",
- 3010,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ok = rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_fails = rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_created = rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ok, ipstat.ips_fragmented);
- rrddim_set_by_pointer(st, rd_fails, ipstat.ips_cantfrag);
- rrddim_set_by_pointer(st, rd_created, ipstat.ips_ofragments);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_fragsin)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "fragsin",
- NULL,
- "fragments",
- NULL,
- "IPv4 Fragments Reassembly",
- "packets/s",
- "freebsd",
- "net.inet.ip.stats",
- 3011,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ok = rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_all = rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ok, ipstat.ips_fragments);
- rrddim_set_by_pointer(st, rd_failed, ipstat.ips_fragdropped);
- rrddim_set_by_pointer(st, rd_all, ipstat.ips_reassembled);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_errors)) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_discards = NULL, *rd_out_discards = NULL,
- *rd_in_hdr_errors = NULL, *rd_out_no_routes = NULL,
- *rd_in_addr_errors = NULL, *rd_in_unknown_protos = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4",
- "errors",
- NULL,
- "errors",
- NULL,
- "IPv4 Errors",
- "packets/s",
- "freebsd",
- "net.inet.ip.stats",
- 3002,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_in_discards = rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_discards = rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_hdr_errors = rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_no_routes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_addr_errors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_unknown_protos = rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_discards, ipstat.ips_badsum + ipstat.ips_tooshort +
- ipstat.ips_toosmall + ipstat.ips_toolong);
- rrddim_set_by_pointer(st, rd_out_discards, ipstat.ips_odropped);
- rrddim_set_by_pointer(st, rd_in_hdr_errors, ipstat.ips_badhlen + ipstat.ips_badlen +
- ipstat.ips_badoptions + ipstat.ips_badvers);
- rrddim_set_by_pointer(st, rd_out_no_routes, ipstat.ips_noroute);
- rrddim_set_by_pointer(st, rd_in_addr_errors, ipstat.ips_badaddr);
- rrddim_set_by_pointer(st, rd_in_unknown_protos, ipstat.ips_noproto);
- rrdset_done(st);
- }
- }
- } else {
- error("DISABLED: net.inet.ip.stats module");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet6.ip6.stats
-
-int do_net_inet6_ip6_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1;
-
- if (unlikely(do_ip6_packets == -1)) {
- do_ip6_packets = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 packets",
- CONFIG_BOOLEAN_AUTO);
- do_ip6_fragsout = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 fragments sent",
- CONFIG_BOOLEAN_AUTO);
- do_ip6_fragsin = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 fragments assembly",
- CONFIG_BOOLEAN_AUTO);
- do_ip6_errors = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 errors",
- CONFIG_BOOLEAN_AUTO);
- }
-
- if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) {
- static int mib[4] = {0, 0, 0, 0};
- struct ip6stat ip6stat;
-
- if (unlikely(GETSYSCTL_SIMPLE("net.inet6.ip6.stats", mib, ip6stat))) {
- do_ip6_packets = 0;
- error("DISABLED: ipv6.packets chart");
- do_ip6_fragsout = 0;
- error("DISABLED: ipv6.fragsout chart");
- do_ip6_fragsin = 0;
- error("DISABLED: ipv6.fragsin chart");
- do_ip6_errors = 0;
- error("DISABLED: ipv6.errors chart");
- error("DISABLED: net.inet6.ip6.stats module");
- return 1;
- } else {
-
- // --------------------------------------------------------------------
-
- if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO &&
- (ip6stat.ip6s_localout || ip6stat.ip6s_total ||
- ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) {
- do_ip6_packets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_forwarded = NULL, *rd_delivers = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "packets",
- NULL,
- "packets",
- NULL,
- "IPv6 Packets",
- "packets/s",
- "freebsd",
- "net.inet6.ip6.stats",
- 3000,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_forwarded = rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_delivers = rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_sent, ip6stat.ip6s_localout);
- rrddim_set_by_pointer(st, rd_received, ip6stat.ip6s_total);
- rrddim_set_by_pointer(st, rd_forwarded, ip6stat.ip6s_forward);
- rrddim_set_by_pointer(st, rd_delivers, ip6stat.ip6s_delivered);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO &&
- (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag ||
- ip6stat.ip6s_ofragments))) {
- do_ip6_fragsout = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "fragsout",
- NULL,
- "fragments",
- NULL,
- "IPv6 Fragments Sent",
- "packets/s",
- "freebsd",
- "net.inet6.ip6.stats",
- 3010,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ok = rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_all = rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ok, ip6stat.ip6s_fragmented);
- rrddim_set_by_pointer(st, rd_failed, ip6stat.ip6s_cantfrag);
- rrddim_set_by_pointer(st, rd_all, ip6stat.ip6s_ofragments);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO &&
- (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped ||
- ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) {
- do_ip6_fragsin = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_timeout = NULL, *rd_all = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "fragsin",
- NULL,
- "fragments",
- NULL,
- "IPv6 Fragments Reassembly",
- "packets/s",
- "freebsd",
- "net.inet6.ip6.stats",
- 3011,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ok = rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_timeout = rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_all = rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ok, ip6stat.ip6s_reassembled);
- rrddim_set_by_pointer(st, rd_failed, ip6stat.ip6s_fragdropped);
- rrddim_set_by_pointer(st, rd_timeout, ip6stat.ip6s_fragtimeout);
- rrddim_set_by_pointer(st, rd_all, ip6stat.ip6s_fragments);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && (
- ip6stat.ip6s_toosmall ||
- ip6stat.ip6s_odropped ||
- ip6stat.ip6s_badoptions ||
- ip6stat.ip6s_badvers ||
- ip6stat.ip6s_exthdrtoolong ||
- ip6stat.ip6s_sources_none ||
- ip6stat.ip6s_tooshort ||
- ip6stat.ip6s_cantforward ||
- ip6stat.ip6s_noroute))) {
- do_ip6_errors = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_discards = NULL, *rd_out_discards = NULL,
- *rd_in_hdr_errors = NULL, *rd_in_addr_errors = NULL, *rd_in_truncated_pkts = NULL,
- *rd_in_no_routes = NULL, *rd_out_no_routes = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "errors",
- NULL,
- "errors",
- NULL,
- "IPv6 Errors",
- "packets/s",
- "freebsd",
- "net.inet6.ip6.stats",
- 3002,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_in_discards = rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_discards = rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_hdr_errors = rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_addr_errors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_truncated_pkts = rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_no_routes = rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_no_routes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_discards, ip6stat.ip6s_toosmall);
- rrddim_set_by_pointer(st, rd_out_discards, ip6stat.ip6s_odropped);
- rrddim_set_by_pointer(st, rd_in_hdr_errors, ip6stat.ip6s_badoptions + ip6stat.ip6s_badvers +
- ip6stat.ip6s_exthdrtoolong);
- rrddim_set_by_pointer(st, rd_in_addr_errors, ip6stat.ip6s_sources_none);
- rrddim_set_by_pointer(st, rd_in_truncated_pkts, ip6stat.ip6s_tooshort);
- rrddim_set_by_pointer(st, rd_in_no_routes, ip6stat.ip6s_cantforward);
- rrddim_set_by_pointer(st, rd_out_no_routes, ip6stat.ip6s_noroute);
- rrdset_done(st);
- }
- }
- } else {
- error("DISABLED: net.inet6.ip6.stats module");
- return 1;
- }
-
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// net.inet6.icmp6.stats
-
-int do_net_inet6_icmp6_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1, do_icmp6_router = -1,
- do_icmp6_neighbor = -1, do_icmp6_types = -1;
-
- if (unlikely(do_icmp6 == -1)) {
- do_icmp6 = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp",
- CONFIG_BOOLEAN_AUTO);
- do_icmp6_redir = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp redirects",
- CONFIG_BOOLEAN_AUTO);
- do_icmp6_errors = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp errors",
- CONFIG_BOOLEAN_AUTO);
- do_icmp6_echos = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp echos",
- CONFIG_BOOLEAN_AUTO);
- do_icmp6_router = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp router",
- CONFIG_BOOLEAN_AUTO);
- do_icmp6_neighbor = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp neighbor",
- CONFIG_BOOLEAN_AUTO);
- do_icmp6_types = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp types",
- CONFIG_BOOLEAN_AUTO);
- }
-
- if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) {
- static int mib[4] = {0, 0, 0, 0};
- struct icmp6stat icmp6stat;
-
- if (unlikely(GETSYSCTL_SIMPLE("net.inet6.icmp6.stats", mib, icmp6stat))) {
- do_icmp6 = 0;
- error("DISABLED: ipv6.icmp chart");
- do_icmp6_redir = 0;
- error("DISABLED: ipv6.icmpredir chart");
- do_icmp6_errors = 0;
- error("DISABLED: ipv6.icmperrors chart");
- do_icmp6_echos = 0;
- error("DISABLED: ipv6.icmpechos chart");
- do_icmp6_router = 0;
- error("DISABLED: ipv6.icmprouter chart");
- do_icmp6_neighbor = 0;
- error("DISABLED: ipv6.icmpneighbor chart");
- do_icmp6_types = 0;
- error("DISABLED: ipv6.icmptypes chart");
- error("DISABLED: net.inet6.icmp6.stats module");
- return 1;
- } else {
- int i;
- struct icmp6_total {
- u_long msgs_in;
- u_long msgs_out;
- } icmp6_total = {0, 0};
-
- for (i = 0; i <= ICMP6_MAXTYPE; i++) {
- icmp6_total.msgs_in += icmp6stat.icp6s_inhist[i];
- icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i];
- }
- icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort;
-
- // --------------------------------------------------------------------
-
- if (do_icmp6 == CONFIG_BOOLEAN_YES || (do_icmp6 == CONFIG_BOOLEAN_AUTO && (icmp6_total.msgs_in || icmp6_total.msgs_out))) {
- do_icmp6 = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL, *rd_sent = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmp",
- NULL,
- "icmp",
- NULL,
- "IPv6 ICMP Messages",
- "messages/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10000,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_received, icmp6_total.msgs_out);
- rrddim_set_by_pointer(st, rd_sent, icmp6_total.msgs_in);
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) {
- do_icmp6_redir = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL, *rd_sent = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmpredir",
- NULL,
- "icmp",
- NULL,
- "IPv6 ICMP Redirects",
- "redirects/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10050,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_received, icmp6stat.icp6s_outhist[ND_REDIRECT]);
- rrddim_set_by_pointer(st, rd_sent, icmp6stat.icp6s_inhist[ND_REDIRECT]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_badcode ||
- icmp6stat.icp6s_badlen ||
- icmp6stat.icp6s_checksum ||
- icmp6stat.icp6s_tooshort ||
- icmp6stat.icp6s_error ||
- icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH] ||
- icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED] ||
- icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB] ||
- icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] ||
- icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] ||
- icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) {
- do_icmp6_errors = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_errors = NULL, *rd_out_errors = NULL, *rd_in_csum_errors = NULL,
- *rd_in_dest_unreachs = NULL, *rd_in_pkt_too_bigs = NULL, *rd_in_time_excds = NULL,
- *rd_in_parm_problems = NULL, *rd_out_dest_unreachs = NULL, *rd_out_time_excds = NULL,
- *rd_out_parm_problems = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmperrors",
- NULL, "icmp",
- NULL,
- "IPv6 ICMP Errors",
- "errors/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10100,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in_errors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_errors = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_csum_errors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_dest_unreachs = rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_pkt_too_bigs = rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_time_excds = rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_parm_problems = rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_dest_unreachs = rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_time_excds = rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_parm_problems = rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_errors, icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen +
- icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort);
- rrddim_set_by_pointer(st, rd_out_errors, icmp6stat.icp6s_error);
- rrddim_set_by_pointer(st, rd_in_csum_errors, icmp6stat.icp6s_checksum);
- rrddim_set_by_pointer(st, rd_in_dest_unreachs, icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH]);
- rrddim_set_by_pointer(st, rd_in_pkt_too_bigs, icmp6stat.icp6s_badlen);
- rrddim_set_by_pointer(st, rd_in_time_excds, icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED]);
- rrddim_set_by_pointer(st, rd_in_parm_problems, icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB]);
- rrddim_set_by_pointer(st, rd_out_dest_unreachs, icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH]);
- rrddim_set_by_pointer(st, rd_out_time_excds, icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED]);
- rrddim_set_by_pointer(st, rd_out_parm_problems, icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] ||
- icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] ||
- icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] ||
- icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) {
- do_icmp6_echos = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_replies = NULL, *rd_out_replies = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmpechos",
- NULL,
- "icmp",
- NULL,
- "IPv6 ICMP Echo",
- "messages/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10200,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in = rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_replies = rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_replies = rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in, icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]);
- rrddim_set_by_pointer(st, rd_out, icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]);
- rrddim_set_by_pointer(st, rd_in_replies, icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY]);
- rrddim_set_by_pointer(st, rd_out_replies, icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] ||
- icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] ||
- icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] ||
- icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) {
- do_icmp6_router = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_solicits = NULL, *rd_out_solicits = NULL,
- *rd_in_advertisements = NULL, *rd_out_advertisements = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmprouter",
- NULL,
- "icmp",
- NULL,
- "IPv6 Router Messages",
- "messages/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10400,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in_solicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_solicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_advertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_solicits, icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]);
- rrddim_set_by_pointer(st, rd_out_solicits, icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]);
- rrddim_set_by_pointer(st, rd_in_advertisements, icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT]);
- rrddim_set_by_pointer(st, rd_out_advertisements, icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] ||
- icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] ||
- icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] ||
- icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) {
- do_icmp6_neighbor = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_solicits = NULL, *rd_out_solicits = NULL,
- *rd_in_advertisements = NULL, *rd_out_advertisements = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmpneighbor",
- NULL,
- "icmp",
- NULL,
- "IPv6 Neighbor Messages",
- "messages/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10500,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in_solicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_solicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_advertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_solicits, icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]);
- rrddim_set_by_pointer(st, rd_out_solicits, icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
- rrddim_set_by_pointer(st, rd_in_advertisements, icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]);
- rrddim_set_by_pointer(st, rd_out_advertisements, icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[1] ||
- icmp6stat.icp6s_inhist[128] ||
- icmp6stat.icp6s_inhist[129] ||
- icmp6stat.icp6s_inhist[136] ||
- icmp6stat.icp6s_outhist[1] ||
- icmp6stat.icp6s_outhist[128] ||
- icmp6stat.icp6s_outhist[129] ||
- icmp6stat.icp6s_outhist[133] ||
- icmp6stat.icp6s_outhist[135] ||
- icmp6stat.icp6s_outhist[136]))) {
- do_icmp6_types = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_in_1 = NULL, *rd_in_128 = NULL, *rd_in_129 = NULL, *rd_in_136 = NULL,
- *rd_out_1 = NULL, *rd_out_128 = NULL, *rd_out_129 = NULL, *rd_out_133 = NULL,
- *rd_out_135 = NULL, *rd_out_143 = NULL;
-
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6",
- "icmptypes",
- NULL,
- "icmp",
- NULL,
- "IPv6 ICMP Types",
- "messages/s",
- "freebsd",
- "net.inet6.icmp6.stats",
- 10700,
- update_every,
- RRDSET_TYPE_LINE
- );
-
- rd_in_1 = rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_128 = rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_129 = rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_in_136 = rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_1 = rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_128 = rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_129 = rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_133 = rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_135 = rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out_143 = rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_in_1, icmp6stat.icp6s_inhist[1]);
- rrddim_set_by_pointer(st, rd_in_128, icmp6stat.icp6s_inhist[128]);
- rrddim_set_by_pointer(st, rd_in_129, icmp6stat.icp6s_inhist[129]);
- rrddim_set_by_pointer(st, rd_in_136, icmp6stat.icp6s_inhist[136]);
- rrddim_set_by_pointer(st, rd_out_1, icmp6stat.icp6s_outhist[1]);
- rrddim_set_by_pointer(st, rd_out_128, icmp6stat.icp6s_outhist[128]);
- rrddim_set_by_pointer(st, rd_out_129, icmp6stat.icp6s_outhist[129]);
- rrddim_set_by_pointer(st, rd_out_133, icmp6stat.icp6s_outhist[133]);
- rrddim_set_by_pointer(st, rd_out_135, icmp6stat.icp6s_outhist[135]);
- rrddim_set_by_pointer(st, rd_out_143, icmp6stat.icp6s_outhist[143]);
- rrdset_done(st);
- }
- }
- } else {
- error("DISABLED: net.inet6.icmp6.stats module");
- return 1;
- }
-
- return 0;
-}
diff --git a/src/freeipmi_plugin.c b/src/freeipmi_plugin.c
deleted file mode 100644
index df4c019a4..000000000
--- a/src/freeipmi_plugin.c
+++ /dev/null
@@ -1,1680 +0,0 @@
-/*
- * netdata freeipmi.plugin
- * Copyright (C) 2017 Costa Tsaousis
- * GPL v3+
- *
- * Based on:
- * ipmimonitoring-sensors.c,v 1.51 2016/11/02 23:46:24 chu11 Exp
- * ipmimonitoring-sel.c,v 1.51 2016/11/02 23:46:24 chu11 Exp
- *
- * Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
- * Copyright (C) 2006-2007 The Regents of the University of California.
- * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
- * Written by Albert Chu <chu11@llnl.gov>
- * UCRL-CODE-222073
- */
-
-#include "common.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-#ifdef HAVE_FREEIPMI
-
-#include <ipmi_monitoring.h>
-#include <ipmi_monitoring_bitmasks.h>
-
-/* Communication Configuration - Initialize accordingly */
-
-/* Hostname, NULL for In-band communication, non-null for a hostname */
-char *hostname = NULL;
-
-/* In-band Communication Configuration */
-int driver_type = -1; // IPMI_MONITORING_DRIVER_TYPE_KCS; /* or -1 for default */
-int disable_auto_probe = 0; /* probe for in-band device */
-unsigned int driver_address = 0; /* not used if probing */
-unsigned int register_spacing = 0; /* not used if probing */
-char *driver_device = NULL; /* not used if probing */
-
-/* Out-of-band Communication Configuration */
-int protocol_version = -1; //IPMI_MONITORING_PROTOCOL_VERSION_1_5; /* or -1 for default */
-char *username = "foousername";
-char *password = "foopassword";
-unsigned char *k_g = NULL;
-unsigned int k_g_len = 0;
-int privilege_level = -1; // IPMI_MONITORING_PRIVILEGE_LEVEL_USER; /* or -1 for default */
-int authentication_type = -1; // IPMI_MONITORING_AUTHENTICATION_TYPE_MD5; /* or -1 for default */
-int cipher_suite_id = 0; /* or -1 for default */
-int session_timeout = 0; /* 0 for default */
-int retransmission_timeout = 0; /* 0 for default */
-
-/* Workarounds - specify workaround flags if necessary */
-unsigned int workaround_flags = 0;
-
-/* Initialize w/ record id numbers to only monitor specific record ids */
-unsigned int record_ids[] = {0};
-unsigned int record_ids_length = 0;
-
-/* Initialize w/ sensor types to only monitor specific sensor types
- * see ipmi_monitoring.h sensor types list.
- */
-unsigned int sensor_types[] = {0};
-unsigned int sensor_types_length = 0;
-
-/* Set to an appropriate alternate if desired */
-char *sdr_cache_directory = "/tmp";
-char *sensor_config_file = NULL;
-
-/* Set to 1 or 0 to enable these sensor reading flags
- * - See ipmi_monitoring.h for descriptions of these flags.
- */
-int reread_sdr_cache = 0;
-int ignore_non_interpretable_sensors = 1;
-int bridge_sensors = 0;
-int interpret_oem_data = 0;
-int shared_sensors = 0;
-int discrete_reading = 0;
-int ignore_scanning_disabled = 0;
-int assume_bmc_owner = 0;
-int entity_sensor_names = 0;
-
-/* Initialization flags
- *
- * Most commonly bitwise OR IPMI_MONITORING_FLAGS_DEBUG and/or
- * IPMI_MONITORING_FLAGS_DEBUG_IPMI_PACKETS for extra debugging
- * information.
- */
-unsigned int ipmimonitoring_init_flags = 0;
-
-int errnum;
-
-// ----------------------------------------------------------------------------
-// SEL only variables
-
-/* Initialize w/ date range to only monitoring specific date range */
-char *date_begin = NULL; /* use MM/DD/YYYY format */
-char *date_end = NULL; /* use MM/DD/YYYY format */
-
-int assume_system_event_record = 0;
-
-char *sel_config_file = NULL;
-
-
-// ----------------------------------------------------------------------------
-// functions common to sensors and SEL
-
-static void
-_init_ipmi_config (struct ipmi_monitoring_ipmi_config *ipmi_config)
-{
- assert (ipmi_config);
-
- ipmi_config->driver_type = driver_type;
- ipmi_config->disable_auto_probe = disable_auto_probe;
- ipmi_config->driver_address = driver_address;
- ipmi_config->register_spacing = register_spacing;
- ipmi_config->driver_device = driver_device;
-
- ipmi_config->protocol_version = protocol_version;
- ipmi_config->username = username;
- ipmi_config->password = password;
- ipmi_config->k_g = k_g;
- ipmi_config->k_g_len = k_g_len;
- ipmi_config->privilege_level = privilege_level;
- ipmi_config->authentication_type = authentication_type;
- ipmi_config->cipher_suite_id = cipher_suite_id;
- ipmi_config->session_timeout_len = session_timeout;
- ipmi_config->retransmission_timeout_len = retransmission_timeout;
-
- ipmi_config->workaround_flags = workaround_flags;
-}
-
-#ifdef NETDATA_COMMENTED
-static const char *
-_get_sensor_type_string (int sensor_type)
-{
- switch (sensor_type)
- {
- case IPMI_MONITORING_SENSOR_TYPE_RESERVED:
- return ("Reserved");
- case IPMI_MONITORING_SENSOR_TYPE_TEMPERATURE:
- return ("Temperature");
- case IPMI_MONITORING_SENSOR_TYPE_VOLTAGE:
- return ("Voltage");
- case IPMI_MONITORING_SENSOR_TYPE_CURRENT:
- return ("Current");
- case IPMI_MONITORING_SENSOR_TYPE_FAN:
- return ("Fan");
- case IPMI_MONITORING_SENSOR_TYPE_PHYSICAL_SECURITY:
- return ("Physical Security");
- case IPMI_MONITORING_SENSOR_TYPE_PLATFORM_SECURITY_VIOLATION_ATTEMPT:
- return ("Platform Security Violation Attempt");
- case IPMI_MONITORING_SENSOR_TYPE_PROCESSOR:
- return ("Processor");
- case IPMI_MONITORING_SENSOR_TYPE_POWER_SUPPLY:
- return ("Power Supply");
- case IPMI_MONITORING_SENSOR_TYPE_POWER_UNIT:
- return ("Power Unit");
- case IPMI_MONITORING_SENSOR_TYPE_COOLING_DEVICE:
- return ("Cooling Device");
- case IPMI_MONITORING_SENSOR_TYPE_OTHER_UNITS_BASED_SENSOR:
- return ("Other Units Based Sensor");
- case IPMI_MONITORING_SENSOR_TYPE_MEMORY:
- return ("Memory");
- case IPMI_MONITORING_SENSOR_TYPE_DRIVE_SLOT:
- return ("Drive Slot");
- case IPMI_MONITORING_SENSOR_TYPE_POST_MEMORY_RESIZE:
- return ("POST Memory Resize");
- case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS:
- return ("System Firmware Progress");
- case IPMI_MONITORING_SENSOR_TYPE_EVENT_LOGGING_DISABLED:
- return ("Event Logging Disabled");
- case IPMI_MONITORING_SENSOR_TYPE_WATCHDOG1:
- return ("Watchdog 1");
- case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_EVENT:
- return ("System Event");
- case IPMI_MONITORING_SENSOR_TYPE_CRITICAL_INTERRUPT:
- return ("Critical Interrupt");
- case IPMI_MONITORING_SENSOR_TYPE_BUTTON_SWITCH:
- return ("Button/Switch");
- case IPMI_MONITORING_SENSOR_TYPE_MODULE_BOARD:
- return ("Module/Board");
- case IPMI_MONITORING_SENSOR_TYPE_MICROCONTROLLER_COPROCESSOR:
- return ("Microcontroller/Coprocessor");
- case IPMI_MONITORING_SENSOR_TYPE_ADD_IN_CARD:
- return ("Add In Card");
- case IPMI_MONITORING_SENSOR_TYPE_CHASSIS:
- return ("Chassis");
- case IPMI_MONITORING_SENSOR_TYPE_CHIP_SET:
- return ("Chip Set");
- case IPMI_MONITORING_SENSOR_TYPE_OTHER_FRU:
- return ("Other Fru");
- case IPMI_MONITORING_SENSOR_TYPE_CABLE_INTERCONNECT:
- return ("Cable/Interconnect");
- case IPMI_MONITORING_SENSOR_TYPE_TERMINATOR:
- return ("Terminator");
- case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_BOOT_INITIATED:
- return ("System Boot Initiated");
- case IPMI_MONITORING_SENSOR_TYPE_BOOT_ERROR:
- return ("Boot Error");
- case IPMI_MONITORING_SENSOR_TYPE_OS_BOOT:
- return ("OS Boot");
- case IPMI_MONITORING_SENSOR_TYPE_OS_CRITICAL_STOP:
- return ("OS Critical Stop");
- case IPMI_MONITORING_SENSOR_TYPE_SLOT_CONNECTOR:
- return ("Slot/Connector");
- case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE:
- return ("System ACPI Power State");
- case IPMI_MONITORING_SENSOR_TYPE_WATCHDOG2:
- return ("Watchdog 2");
- case IPMI_MONITORING_SENSOR_TYPE_PLATFORM_ALERT:
- return ("Platform Alert");
- case IPMI_MONITORING_SENSOR_TYPE_ENTITY_PRESENCE:
- return ("Entity Presence");
- case IPMI_MONITORING_SENSOR_TYPE_MONITOR_ASIC_IC:
- return ("Monitor ASIC/IC");
- case IPMI_MONITORING_SENSOR_TYPE_LAN:
- return ("LAN");
- case IPMI_MONITORING_SENSOR_TYPE_MANAGEMENT_SUBSYSTEM_HEALTH:
- return ("Management Subsystem Health");
- case IPMI_MONITORING_SENSOR_TYPE_BATTERY:
- return ("Battery");
- case IPMI_MONITORING_SENSOR_TYPE_SESSION_AUDIT:
- return ("Session Audit");
- case IPMI_MONITORING_SENSOR_TYPE_VERSION_CHANGE:
- return ("Version Change");
- case IPMI_MONITORING_SENSOR_TYPE_FRU_STATE:
- return ("FRU State");
- }
-
- return ("Unrecognized");
-}
-#endif // NETDATA_COMMENTED
-
-
-// ----------------------------------------------------------------------------
-// BEGIN NETDATA CODE
-
-static int debug = 0;
-
-static int netdata_update_every = 5; // this is the minimum update frequency
-static int netdata_priority = 90000;
-static int netdata_do_sel = 1;
-
-static size_t netdata_sensors_updated = 0;
-static size_t netdata_sensors_collected = 0;
-static size_t netdata_sel_events = 0;
-static size_t netdata_sensors_states_nominal = 0;
-static size_t netdata_sensors_states_warning = 0;
-static size_t netdata_sensors_states_critical = 0;
-
-struct sensor {
- int record_id;
- int sensor_number;
- int sensor_type;
- int sensor_state;
- int sensor_units;
- char *sensor_name;
-
- int sensor_reading_type;
- union {
- uint8_t bool_value;
- uint32_t uint32_value;
- double double_value;
- } sensor_reading;
-
- int sent;
- int ignore;
- int exposed;
- int updated;
- struct sensor *next;
-} *sensors_root = NULL;
-
-static void netdata_mark_as_not_updated() {
- struct sensor *sn;
- for(sn = sensors_root; sn ;sn = sn->next)
- sn->updated = sn->sent = 0;
-
- netdata_sensors_updated = 0;
- netdata_sensors_collected = 0;
- netdata_sel_events = 0;
-
- netdata_sensors_states_nominal = 0;
- netdata_sensors_states_warning = 0;
- netdata_sensors_states_critical = 0;
-}
-
-static void send_chart_to_netdata_for_units(int units) {
- struct sensor *sn;
-
- switch(units) {
- case IPMI_MONITORING_SENSOR_UNITS_CELSIUS:
- printf("CHART ipmi.temperatures_c '' 'System Celcius Temperatures read by IPMI' 'Celcius' 'temperatures' 'ipmi.temperatures_c' 'line' %d %d\n"
- , netdata_priority + 10
- , netdata_update_every
- );
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT:
- printf("CHART ipmi.temperatures_f '' 'System Fahrenheit Temperatures read by IPMI' 'Fahrenheit' 'temperatures' 'ipmi.temperatures_f' 'line' %d %d\n"
- , netdata_priority + 11
- , netdata_update_every
- );
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_VOLTS:
- printf("CHART ipmi.volts '' 'System Voltages read by IPMI' 'Volts' 'voltages' 'ipmi.voltages' 'line' %d %d\n"
- , netdata_priority + 12
- , netdata_update_every
- );
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_AMPS:
- printf("CHART ipmi.amps '' 'System Current read by IPMI' 'Amps' 'current' 'ipmi.amps' 'line' %d %d\n"
- , netdata_priority + 13
- , netdata_update_every
- );
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_RPM:
- printf("CHART ipmi.rpm '' 'System Fans read by IPMI' 'RPM' 'fans' 'ipmi.rpm' 'line' %d %d\n"
- , netdata_priority + 14
- , netdata_update_every
- );
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_WATTS:
- printf("CHART ipmi.watts '' 'System Power read by IPMI' 'Watts' 'power' 'ipmi.watts' 'line' %d %d\n"
- , netdata_priority + 5
- , netdata_update_every
- );
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_PERCENT:
- printf("CHART ipmi.percent '' 'System Metrics read by IPMI' '%%' 'other' 'ipmi.percent' 'line' %d %d\n"
- , netdata_priority + 15
- , netdata_update_every
- );
- break;
-
- default:
- for(sn = sensors_root; sn; sn = sn->next)
- if(sn->sensor_units == units)
- sn->ignore = 1;
- return;
- }
-
- for(sn = sensors_root; sn; sn = sn->next) {
- if(sn->sensor_units == units && sn->updated && !sn->ignore) {
- sn->exposed = 1;
-
- switch(sn->sensor_reading_type) {
- case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
- case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
- printf("DIMENSION i%d_n%d_r%d '%s i%d' absolute 1 1\n"
- , sn->sensor_number
- , sn->record_id
- , sn->sensor_reading_type
- , sn->sensor_name
- , sn->sensor_number
- );
- break;
-
- case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
- printf("DIMENSION i%d_n%d_r%d '%s i%d' absolute 1 1000\n"
- , sn->sensor_number
- , sn->record_id
- , sn->sensor_reading_type
- , sn->sensor_name
- , sn->sensor_number
- );
- break;
-
- default:
- sn->ignore = 1;
- break;
- }
- }
- }
-}
-
-static void send_metrics_to_netdata_for_units(int units) {
- struct sensor *sn;
-
- switch(units) {
- case IPMI_MONITORING_SENSOR_UNITS_CELSIUS:
- printf("BEGIN ipmi.temperatures_c\n");
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT:
- printf("BEGIN ipmi.temperatures_f\n");
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_VOLTS:
- printf("BEGIN ipmi.volts\n");
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_AMPS:
- printf("BEGIN ipmi.amps\n");
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_RPM:
- printf("BEGIN ipmi.rpm\n");
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_WATTS:
- printf("BEGIN ipmi.watts\n");
- break;
-
- case IPMI_MONITORING_SENSOR_UNITS_PERCENT:
- printf("BEGIN ipmi.percent\n");
- break;
-
- default:
- for(sn = sensors_root; sn; sn = sn->next)
- if(sn->sensor_units == units)
- sn->ignore = 1;
- return;
- }
-
- for(sn = sensors_root; sn; sn = sn->next) {
- if(sn->sensor_units == units && sn->updated && !sn->sent && !sn->ignore) {
- netdata_sensors_updated++;
-
- sn->sent = 1;
-
- switch(sn->sensor_reading_type) {
- case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
- printf("SET i%d_n%d_r%d = %u\n"
- , sn->sensor_number
- , sn->record_id
- , sn->sensor_reading_type
- , sn->sensor_reading.bool_value
- );
- break;
-
- case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
- printf("SET i%d_n%d_r%d = %u\n"
- , sn->sensor_number
- , sn->record_id
- , sn->sensor_reading_type
- , sn->sensor_reading.uint32_value
- );
- break;
-
- case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
- printf("SET i%d_n%d_r%d = %lld\n"
- , sn->sensor_number
- , sn->record_id
- , sn->sensor_reading_type
- , (long long int)(sn->sensor_reading.double_value * 1000)
- );
- break;
-
- default:
- sn->ignore = 1;
- break;
- }
- }
- }
-
- printf("END\n");
-}
-
-static void send_metrics_to_netdata() {
- static int sel_chart_generated = 0, sensors_states_chart_generated = 0;
- struct sensor *sn;
-
- if(netdata_do_sel && !sel_chart_generated) {
- sel_chart_generated = 1;
- printf("CHART ipmi.events '' 'IPMI Events' 'events' 'events' ipmi.sel area %d %d\n"
- , netdata_priority + 2
- , netdata_update_every
- );
- printf("DIMENSION events '' absolute 1 1\n");
- }
-
- if(!sensors_states_chart_generated) {
- sensors_states_chart_generated = 1;
- printf("CHART ipmi.sensors_states '' 'IPMI Sensors State' 'sensors' 'states' ipmi.sensors_states line %d %d\n"
- , netdata_priority + 1
- , netdata_update_every
- );
- printf("DIMENSION nominal '' absolute 1 1\n");
- printf("DIMENSION critical '' absolute 1 1\n");
- printf("DIMENSION warning '' absolute 1 1\n");
- }
-
- // generate the CHART/DIMENSION lines, if we have to
- for(sn = sensors_root; sn; sn = sn->next)
- if(sn->updated && !sn->exposed && !sn->ignore)
- send_chart_to_netdata_for_units(sn->sensor_units);
-
- if(netdata_do_sel) {
- printf(
- "BEGIN ipmi.events\n"
- "SET events = %zu\n"
- "END\n"
- , netdata_sel_events
- );
- }
-
- printf(
- "BEGIN ipmi.sensors_states\n"
- "SET nominal = %zu\n"
- "SET warning = %zu\n"
- "SET critical = %zu\n"
- "END\n"
- , netdata_sensors_states_nominal
- , netdata_sensors_states_warning
- , netdata_sensors_states_critical
- );
-
- // send metrics to netdata
- for(sn = sensors_root; sn; sn = sn->next)
- if(sn->updated && sn->exposed && !sn->sent && !sn->ignore)
- send_metrics_to_netdata_for_units(sn->sensor_units);
-
-}
-
-static int *excluded_record_ids = NULL;
-size_t excluded_record_ids_length = 0;
-
-static void excluded_record_ids_parse(const char *s) {
- if(!s) return;
-
- while(*s) {
- while(*s && !isdigit(*s)) s++;
-
- if(isdigit(*s)) {
- char *e;
- unsigned long n = strtoul(s, &e, 10);
- s = e;
-
- if(n != 0) {
- excluded_record_ids = realloc(excluded_record_ids, (excluded_record_ids_length + 1) * sizeof(int));
- if(!excluded_record_ids) {
- fprintf(stderr, "freeipmi.plugin: failed to allocate memory. Exiting.");
- exit(1);
- }
- excluded_record_ids[excluded_record_ids_length++] = (int)n;
- }
- }
- }
-
- if(debug) {
- fprintf(stderr, "freeipmi.plugin: excluded record ids:");
- size_t i;
- for(i = 0; i < excluded_record_ids_length; i++) {
- fprintf(stderr, " %d", excluded_record_ids[i]);
- }
- fprintf(stderr, "\n");
- }
-}
-
-
-static int excluded_record_ids_check(int record_id) {
- size_t i;
-
- for(i = 0; i < excluded_record_ids_length; i++) {
- if(excluded_record_ids[i] == record_id)
- return 1;
- }
-
- return 0;
-}
-
-static void netdata_get_sensor(
- int record_id
- , int sensor_number
- , int sensor_type
- , int sensor_state
- , int sensor_units
- , int sensor_reading_type
- , char *sensor_name
- , void *sensor_reading
-) {
- // find the sensor record
- struct sensor *sn;
- for(sn = sensors_root; sn ;sn = sn->next)
- if( sn->record_id == record_id &&
- sn->sensor_number == sensor_number &&
- sn->sensor_reading_type == sensor_reading_type &&
- sn->sensor_units == sensor_units &&
- !strcmp(sn->sensor_name, sensor_name)
- )
- break;
-
- if(!sn) {
- // not found, create it
-
- // check if it is excluded
- if(excluded_record_ids_check(record_id))
- return;
-
- sn = calloc(1, sizeof(struct sensor));
- if(!sn) {
- fatal("cannot allocate %zu bytes of memory.", sizeof(struct sensor));
- }
-
- sn->record_id = record_id;
- sn->sensor_number = sensor_number;
- sn->sensor_type = sensor_type;
- sn->sensor_state = sensor_state;
- sn->sensor_units = sensor_units;
- sn->sensor_reading_type = sensor_reading_type;
- sn->sensor_name = strdup(sensor_name);
- if(!sn->sensor_name) {
- fatal("cannot allocate %zu bytes of memory.", strlen(sensor_name));
- }
-
- sn->next = sensors_root;
- sensors_root = sn;
- }
-
- switch(sensor_reading_type) {
- case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
- sn->sensor_reading.bool_value = *((uint8_t *)sensor_reading);
- sn->updated = 1;
- netdata_sensors_collected++;
- break;
-
- case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
- sn->sensor_reading.uint32_value = *((uint32_t *)sensor_reading);
- sn->updated = 1;
- netdata_sensors_collected++;
- break;
-
- case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
- sn->sensor_reading.double_value = *((double *)sensor_reading);
- sn->updated = 1;
- netdata_sensors_collected++;
- break;
-
- default:
- sn->ignore = 1;
- break;
- }
-
- switch(sensor_state) {
- case IPMI_MONITORING_STATE_NOMINAL:
- netdata_sensors_states_nominal++;
- break;
-
- case IPMI_MONITORING_STATE_WARNING:
- netdata_sensors_states_warning++;
- break;
-
- case IPMI_MONITORING_STATE_CRITICAL:
- netdata_sensors_states_critical++;
- break;
-
- default:
- break;
- }
-}
-
-static void netdata_get_sel(
- int record_id
- , int record_type_class
- , int sel_state
-) {
- (void)record_id;
- (void)record_type_class;
- (void)sel_state;
-
- netdata_sel_events++;
-}
-
-
-void netdata_cleanup_and_exit(int ret) {
- exit(ret);
-}
-
-// END NETDATA CODE
-// ----------------------------------------------------------------------------
-
-
-static int
-_ipmimonitoring_sensors (struct ipmi_monitoring_ipmi_config *ipmi_config)
-{
- ipmi_monitoring_ctx_t ctx = NULL;
- unsigned int sensor_reading_flags = 0;
- int i;
- int sensor_count;
- int rv = -1;
-
- if (!(ctx = ipmi_monitoring_ctx_create ())) {
- error("ipmi_monitoring_ctx_create()");
- goto cleanup;
- }
-
- if (sdr_cache_directory)
- {
- if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
- sdr_cache_directory) < 0)
- {
- error("ipmi_monitoring_ctx_sdr_cache_directory(): %s\n",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
-
- /* Must call otherwise only default interpretations ever used */
- if (sensor_config_file)
- {
- if (ipmi_monitoring_ctx_sensor_config_file (ctx,
- sensor_config_file) < 0)
- {
- error( "ipmi_monitoring_ctx_sensor_config_file(): %s\n",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else
- {
- if (ipmi_monitoring_ctx_sensor_config_file (ctx, NULL) < 0)
- {
- error( "ipmi_monitoring_ctx_sensor_config_file(): %s\n",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
-
- if (reread_sdr_cache)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_REREAD_SDR_CACHE;
-
- if (ignore_non_interpretable_sensors)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_NON_INTERPRETABLE_SENSORS;
-
- if (bridge_sensors)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_BRIDGE_SENSORS;
-
- if (interpret_oem_data)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_INTERPRET_OEM_DATA;
-
- if (shared_sensors)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_SHARED_SENSORS;
-
- if (discrete_reading)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_DISCRETE_READING;
-
- if (ignore_scanning_disabled)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_SCANNING_DISABLED;
-
- if (assume_bmc_owner)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ASSUME_BMC_OWNER;
-
-#ifdef IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES
- if (entity_sensor_names)
- sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES;
-#endif // IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES
-
- if (!record_ids_length && !sensor_types_length)
- {
- if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
- hostname,
- ipmi_config,
- sensor_reading_flags,
- NULL,
- 0,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sensor_readings_by_record_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else if (record_ids_length)
- {
- if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
- hostname,
- ipmi_config,
- sensor_reading_flags,
- record_ids,
- record_ids_length,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sensor_readings_by_record_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else
- {
- if ((sensor_count = ipmi_monitoring_sensor_readings_by_sensor_type (ctx,
- hostname,
- ipmi_config,
- sensor_reading_flags,
- sensor_types,
- sensor_types_length,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sensor_readings_by_sensor_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
-
-#ifdef NETDATA_COMMENTED
- printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
- "Record ID",
- "Sensor Name",
- "Sensor Number",
- "Sensor Type",
- "Sensor State",
- "Sensor Reading",
- "Sensor Units",
- "Sensor Event/Reading Type Code",
- "Sensor Event Bitmask",
- "Sensor Event String");
-#endif // NETDATA_COMMENTED
-
- for (i = 0; i < sensor_count; i++, ipmi_monitoring_sensor_iterator_next (ctx))
- {
- int record_id, sensor_number, sensor_type, sensor_state, sensor_units,
- sensor_reading_type;
-
-#ifdef NETDATA_COMMENTED
- int sensor_bitmask_type, sensor_bitmask, event_reading_type_code;
- char **sensor_bitmask_strings = NULL;
- const char *sensor_type_str;
- const char *sensor_state_str;
-#endif // NETDATA_COMMENTED
-
- char *sensor_name = NULL;
- void *sensor_reading;
-
- if ((record_id = ipmi_monitoring_sensor_read_record_id (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_record_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sensor_number = ipmi_monitoring_sensor_read_sensor_number (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_sensor_number(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sensor_type = ipmi_monitoring_sensor_read_sensor_type (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_sensor_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if (!(sensor_name = ipmi_monitoring_sensor_read_sensor_name (ctx)))
- {
- error( "ipmi_monitoring_sensor_read_sensor_name(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sensor_state = ipmi_monitoring_sensor_read_sensor_state (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_sensor_state(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sensor_units = ipmi_monitoring_sensor_read_sensor_units (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_sensor_units(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
-#ifdef NETDATA_COMMENTED
- if ((sensor_bitmask_type = ipmi_monitoring_sensor_read_sensor_bitmask_type (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_sensor_bitmask_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- if ((sensor_bitmask = ipmi_monitoring_sensor_read_sensor_bitmask (ctx)) < 0)
- {
- error(
- "ipmi_monitoring_sensor_read_sensor_bitmask(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if (!(sensor_bitmask_strings = ipmi_monitoring_sensor_read_sensor_bitmask_strings (ctx)))
- {
- error( "ipmi_monitoring_sensor_read_sensor_bitmask_strings(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-#endif // NETDATA_COMMENTED
-
- if ((sensor_reading_type = ipmi_monitoring_sensor_read_sensor_reading_type (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_sensor_reading_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- sensor_reading = ipmi_monitoring_sensor_read_sensor_reading (ctx);
-
-#ifdef NETDATA_COMMENTED
- if ((event_reading_type_code = ipmi_monitoring_sensor_read_event_reading_type_code (ctx)) < 0)
- {
- error( "ipmi_monitoring_sensor_read_event_reading_type_code(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-#endif // NETDATA_COMMENTED
-
- netdata_get_sensor(
- record_id
- , sensor_number
- , sensor_type
- , sensor_state
- , sensor_units
- , sensor_reading_type
- , sensor_name
- , sensor_reading
- );
-
-#ifdef NETDATA_COMMENTED
- if (!strlen (sensor_name))
- sensor_name = "N/A";
-
- sensor_type_str = _get_sensor_type_string (sensor_type);
-
- printf ("%d, %s, %d, %s",
- record_id,
- sensor_name,
- sensor_number,
- sensor_type_str);
-
- if (sensor_state == IPMI_MONITORING_STATE_NOMINAL)
- sensor_state_str = "Nominal";
- else if (sensor_state == IPMI_MONITORING_STATE_WARNING)
- sensor_state_str = "Warning";
- else if (sensor_state == IPMI_MONITORING_STATE_CRITICAL)
- sensor_state_str = "Critical";
- else
- sensor_state_str = "N/A";
-
- printf (", %s", sensor_state_str);
-
- if (sensor_reading)
- {
- const char *sensor_units_str;
-
- if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL)
- printf (", %s",
- (*((uint8_t *)sensor_reading) ? "true" : "false"));
- else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32)
- printf (", %u",
- *((uint32_t *)sensor_reading));
- else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
- printf (", %.2f",
- *((double *)sensor_reading));
- else
- printf (", N/A");
-
- if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_CELSIUS)
- sensor_units_str = "C";
- else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT)
- sensor_units_str = "F";
- else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_VOLTS)
- sensor_units_str = "V";
- else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_AMPS)
- sensor_units_str = "A";
- else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_RPM)
- sensor_units_str = "RPM";
- else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_WATTS)
- sensor_units_str = "W";
- else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_PERCENT)
- sensor_units_str = "%";
- else
- sensor_units_str = "N/A";
-
- printf (", %s", sensor_units_str);
- }
- else
- printf (", N/A, N/A");
-
- printf (", %Xh", event_reading_type_code);
-
- /* It is possible you may want to monitor specific event
- * conditions that may occur. If that is the case, you may want
- * to check out what specific bitmask type and bitmask events
- * occurred. See ipmi_monitoring_bitmasks.h for a list of
- * bitmasks and types.
- */
-
- if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
- printf (", %Xh", sensor_bitmask);
- else
- printf (", N/A");
-
- if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
- {
- unsigned int i = 0;
-
- printf (",");
-
- while (sensor_bitmask_strings[i])
- {
- printf (" ");
-
- printf ("'%s'",
- sensor_bitmask_strings[i]);
-
- i++;
- }
- }
- else
- printf (", N/A");
-
- printf ("\n");
-#endif // NETDATA_COMMENTED
- }
-
- rv = 0;
- cleanup:
- if (ctx)
- ipmi_monitoring_ctx_destroy (ctx);
- return (rv);
-}
-
-
-static int
-_ipmimonitoring_sel (struct ipmi_monitoring_ipmi_config *ipmi_config)
-{
- ipmi_monitoring_ctx_t ctx = NULL;
- unsigned int sel_flags = 0;
- int i;
- int sel_count;
- int rv = -1;
-
- if (!(ctx = ipmi_monitoring_ctx_create ()))
- {
- error("ipmi_monitoring_ctx_create()");
- goto cleanup;
- }
-
- if (sdr_cache_directory)
- {
- if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
- sdr_cache_directory) < 0)
- {
- error( "ipmi_monitoring_ctx_sdr_cache_directory(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
-
- /* Must call otherwise only default interpretations ever used */
- if (sel_config_file)
- {
- if (ipmi_monitoring_ctx_sel_config_file (ctx,
- sel_config_file) < 0)
- {
- error( "ipmi_monitoring_ctx_sel_config_file(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else
- {
- if (ipmi_monitoring_ctx_sel_config_file (ctx, NULL) < 0)
- {
- error( "ipmi_monitoring_ctx_sel_config_file(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
-
- if (reread_sdr_cache)
- sel_flags |= IPMI_MONITORING_SEL_FLAGS_REREAD_SDR_CACHE;
-
- if (interpret_oem_data)
- sel_flags |= IPMI_MONITORING_SEL_FLAGS_INTERPRET_OEM_DATA;
-
- if (assume_system_event_record)
- sel_flags |= IPMI_MONITORING_SEL_FLAGS_ASSUME_SYSTEM_EVENT_RECORD;
-
-#ifdef IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES
- if (entity_sensor_names)
- sel_flags |= IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES;
-#endif // IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES
-
- if (record_ids_length)
- {
- if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
- hostname,
- ipmi_config,
- sel_flags,
- record_ids,
- record_ids_length,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sel_by_record_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else if (sensor_types_length)
- {
- if ((sel_count = ipmi_monitoring_sel_by_sensor_type (ctx,
- hostname,
- ipmi_config,
- sel_flags,
- sensor_types,
- sensor_types_length,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sel_by_sensor_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else if (date_begin
- || date_end)
- {
- if ((sel_count = ipmi_monitoring_sel_by_date_range (ctx,
- hostname,
- ipmi_config,
- sel_flags,
- date_begin,
- date_end,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sel_by_sensor_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
- else
- {
- if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
- hostname,
- ipmi_config,
- sel_flags,
- NULL,
- 0,
- NULL,
- NULL)) < 0)
- {
- error( "ipmi_monitoring_sel_by_record_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
- }
-
-#ifdef NETDATA_COMMENTED
- printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
- "Record ID",
- "Record Type",
- "SEL State",
- "Timestamp",
- "Sensor Name",
- "Sensor Type",
- "Event Direction",
- "Event Type Code",
- "Event Data",
- "Event Offset",
- "Event Offset String");
-#endif // NETDATA_COMMENTED
-
- for (i = 0; i < sel_count; i++, ipmi_monitoring_sel_iterator_next (ctx))
- {
- int record_id, record_type, sel_state, record_type_class;
-#ifdef NETDATA_COMMENTED
- int sensor_type, sensor_number, event_direction,
- event_offset_type, event_offset, event_type_code, manufacturer_id;
- unsigned int timestamp, event_data1, event_data2, event_data3;
- char *event_offset_string = NULL;
- const char *sensor_type_str;
- const char *event_direction_str;
- const char *sel_state_str;
- char *sensor_name = NULL;
- unsigned char oem_data[64];
- int oem_data_len;
- unsigned int j;
-#endif // NETDATA_COMMENTED
-
- if ((record_id = ipmi_monitoring_sel_read_record_id (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_record_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((record_type = ipmi_monitoring_sel_read_record_type (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_record_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((record_type_class = ipmi_monitoring_sel_read_record_type_class (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_record_type_class(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sel_state = ipmi_monitoring_sel_read_sel_state (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_sel_state(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- netdata_get_sel(
- record_id
- , record_type_class
- , sel_state
- );
-
-#ifdef NETDATA_COMMENTED
- if (sel_state == IPMI_MONITORING_STATE_NOMINAL)
- sel_state_str = "Nominal";
- else if (sel_state == IPMI_MONITORING_STATE_WARNING)
- sel_state_str = "Warning";
- else if (sel_state == IPMI_MONITORING_STATE_CRITICAL)
- sel_state_str = "Critical";
- else
- sel_state_str = "N/A";
-
- printf ("%d, %d, %s",
- record_id,
- record_type,
- sel_state_str);
-
- if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD
- || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
- {
-
- if (ipmi_monitoring_sel_read_timestamp (ctx, &timestamp) < 0)
- {
- error( "ipmi_monitoring_sel_read_timestamp(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- /* XXX: This should be converted to a nice date output using
- * your favorite timestamp -> string conversion functions.
- */
- printf (", %u", timestamp);
- }
- else
- printf (", N/A");
-
- if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD)
- {
- /* If you are integrating ipmimonitoring SEL into a monitoring application,
- * you may wish to count the number of times a specific error occurred
- * and report that to the monitoring application.
- *
- * In this particular case, you'll probably want to check out
- * what sensor type each SEL event is reporting, the
- * event offset type, and the specific event offset that occurred.
- *
- * See ipmi_monitoring_offsets.h for a list of event offsets
- * and types.
- */
-
- if (!(sensor_name = ipmi_monitoring_sel_read_sensor_name (ctx)))
- {
- error( "ipmi_monitoring_sel_read_sensor_name(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sensor_type = ipmi_monitoring_sel_read_sensor_type (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_sensor_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((sensor_number = ipmi_monitoring_sel_read_sensor_number (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_sensor_number(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((event_direction = ipmi_monitoring_sel_read_event_direction (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_event_direction(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((event_type_code = ipmi_monitoring_sel_read_event_type_code (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_event_type_code(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if (ipmi_monitoring_sel_read_event_data (ctx,
- &event_data1,
- &event_data2,
- &event_data3) < 0)
- {
- error( "ipmi_monitoring_sel_read_event_data(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((event_offset_type = ipmi_monitoring_sel_read_event_offset_type (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_event_offset_type(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if ((event_offset = ipmi_monitoring_sel_read_event_offset (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_event_offset(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if (!(event_offset_string = ipmi_monitoring_sel_read_event_offset_string (ctx)))
- {
- error( "ipmi_monitoring_sel_read_event_offset_string(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- if (!strlen (sensor_name))
- sensor_name = "N/A";
-
- sensor_type_str = _get_sensor_type_string (sensor_type);
-
- if (event_direction == IPMI_MONITORING_SEL_EVENT_DIRECTION_ASSERTION)
- event_direction_str = "Assertion";
- else
- event_direction_str = "Deassertion";
-
- printf (", %s, %s, %d, %s, %Xh, %Xh-%Xh-%Xh",
- sensor_name,
- sensor_type_str,
- sensor_number,
- event_direction_str,
- event_type_code,
- event_data1,
- event_data2,
- event_data3);
-
- if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
- printf (", %Xh", event_offset);
- else
- printf (", N/A");
-
- if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
- printf (", %s", event_offset_string);
- else
- printf (", N/A");
- }
- else if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD
- || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_NON_TIMESTAMPED_OEM_RECORD)
- {
- if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
- {
- if ((manufacturer_id = ipmi_monitoring_sel_read_manufacturer_id (ctx)) < 0)
- {
- error( "ipmi_monitoring_sel_read_manufacturer_id(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- printf (", Manufacturer ID = %Xh", manufacturer_id);
- }
-
- if ((oem_data_len = ipmi_monitoring_sel_read_oem_data (ctx, oem_data, 1024)) < 0)
- {
- error( "ipmi_monitoring_sel_read_oem_data(): %s",
- ipmi_monitoring_ctx_errormsg (ctx));
- goto cleanup;
- }
-
- printf (", OEM Data = ");
-
- for (j = 0; j < oem_data_len; j++)
- printf ("%02Xh ", oem_data[j]);
- }
- else
- printf (", N/A, N/A, N/A, N/A, N/A, N/A, N/A");
-
- printf ("\n");
-#endif // NETDATA_COMMENTED
- }
-
- rv = 0;
- cleanup:
- if (ctx)
- ipmi_monitoring_ctx_destroy (ctx);
- return (rv);
-}
-
-// ----------------------------------------------------------------------------
-// MAIN PROGRAM FOR NETDATA PLUGIN
-
-int ipmi_collect_data(struct ipmi_monitoring_ipmi_config *ipmi_config) {
- errno = 0;
-
- if (_ipmimonitoring_sensors(ipmi_config) < 0) return -1;
-
- if(netdata_do_sel) {
- if(_ipmimonitoring_sel(ipmi_config) < 0) return -2;
- }
-
- return 0;
-}
-
-int ipmi_detect_speed_secs(struct ipmi_monitoring_ipmi_config *ipmi_config) {
- int i, checks = 10;
- unsigned long long total = 0;
-
- for(i = 0 ; i < checks ; i++) {
- if(debug) fprintf(stderr, "freeipmi.plugin: checking data collection speed iteration %d of %d\n", i+1, checks);
-
- // measure the time a data collection needs
- unsigned long long start = now_realtime_usec();
- if(ipmi_collect_data(ipmi_config) < 0)
- fatal("freeipmi.plugin: data collection failed.");
-
- unsigned long long end = now_realtime_usec();
-
- if(debug) fprintf(stderr, "freeipmi.plugin: data collection speed was %llu usec\n", end - start);
-
- // add it to our total
- total += end - start;
-
- // wait the same time
- // to avoid flooding the IPMI processor with requests
- sleep_usec(end - start);
- }
-
- // so, we assume it needed 2x the time
- // we find the average in microseconds
- // and we round-up to the closest second
-
- return (int)(( total * 2 / checks / 1000000 ) + 1);
-}
-
-int main (int argc, char **argv) {
-
- // ------------------------------------------------------------------------
- // initialization of netdata plugin
-
- program_name = "freeipmi.plugin";
-
- // disable syslog
- error_log_syslog = 0;
-
- // set errors flood protection to 100 logs per hour
- error_log_errors_per_period = 100;
- error_log_throttle_period = 3600;
-
-
- // ------------------------------------------------------------------------
- // parse command line parameters
-
- int i, freq = 0;
- for(i = 1; i < argc ; i++) {
- if(isdigit(*argv[i]) && !freq) {
- int n = atoi(argv[i]);
- if(n > 0 && freq < 86400) {
- freq = n;
- continue;
- }
- }
- else if(strcmp("version", argv[i]) == 0 || strcmp("-version", argv[i]) == 0 || 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;
- }
- else if(strcmp("sel", argv[i]) == 0) {
- netdata_do_sel = 1;
- continue;
- }
- else if(strcmp("no-sel", argv[i]) == 0) {
- netdata_do_sel = 0;
- continue;
- }
- else if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
- fprintf(stderr,
- "\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"
- " ignore N1,N2,N3,... sensor IDs to ignore\n"
- " default: none\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"
- " For more information:\n"
- " https://github.com/firehol/netdata/wiki/monitoring-IPMI\n"
- "\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);
- }
- else if(i < argc && strcmp("hostname", argv[i]) == 0) {
- hostname = strdupz(argv[++i]);
- char *s = argv[i];
- // mask it be hidden from the process tree
- while(*s) *s++ = 'x';
- if(debug) fprintf(stderr, "freeipmi.plugin: hostname set to '%s'\n", hostname);
- continue;
- }
- else if(i < argc && strcmp("username", argv[i]) == 0) {
- username = strdupz(argv[++i]);
- char *s = argv[i];
- // mask it be hidden from the process tree
- while(*s) *s++ = 'x';
- if(debug) fprintf(stderr, "freeipmi.plugin: username set to '%s'\n", username);
- continue;
- }
- else if(i < argc && strcmp("password", argv[i]) == 0) {
- password = strdupz(argv[++i]);
- char *s = argv[i];
- // mask it be hidden from the process tree
- while(*s) *s++ = 'x';
- if(debug) fprintf(stderr, "freeipmi.plugin: password set to '%s'\n", password);
- continue;
- }
- else if(i < argc && strcmp("sdr-cache-dir", argv[i]) == 0) {
- sdr_cache_directory = argv[++i];
- if(debug) fprintf(stderr, "freeipmi.plugin: SDR cache directory set to '%s'\n", sdr_cache_directory);
- continue;
- }
- else if(i < argc && strcmp("sensor-config-file", argv[i]) == 0) {
- sensor_config_file = argv[++i];
- if(debug) fprintf(stderr, "freeipmi.plugin: sensor config file set to '%s'\n", sensor_config_file);
- continue;
- }
- else if(i < argc && strcmp("ignore", argv[i]) == 0) {
- excluded_record_ids_parse(argv[++i]);
- continue;
- }
-
- error("freeipmi.plugin: ignoring parameter '%s'", argv[i]);
- }
-
- errno = 0;
-
- if(freq > netdata_update_every)
- netdata_update_every = freq;
-
- else if(freq)
- error("update frequency %d seconds is too small for IPMI. Using %d.", freq, netdata_update_every);
-
-
- // ------------------------------------------------------------------------
- // initialize IPMI
-
- struct ipmi_monitoring_ipmi_config ipmi_config;
-
- if(debug) fprintf(stderr, "freeipmi.plugin: calling _init_ipmi_config()\n");
-
- _init_ipmi_config(&ipmi_config);
-
- if(debug) fprintf(stderr, "freeipmi.plugin: calling ipmi_monitoring_init()\n");
-
- if(ipmi_monitoring_init(ipmimonitoring_init_flags, &errnum) < 0)
- fatal("ipmi_monitoring_init: %s", ipmi_monitoring_ctx_strerror(errnum));
-
- if(debug) fprintf(stderr, "freeipmi.plugin: detecting IPMI minimum update frequency...\n");
- freq = ipmi_detect_speed_secs(&ipmi_config);
- if(debug) fprintf(stderr, "freeipmi.plugin: IPMI minimum update frequency was calculated to %d seconds.\n", freq);
-
- if(freq > netdata_update_every) {
- info("enforcing minimum data collection frequency, calculated to %d seconds.", freq);
- netdata_update_every = freq;
- }
-
-
- // ------------------------------------------------------------------------
- // the main loop
-
- if(debug) fprintf(stderr, "freeipmi.plugin: starting data collection\n");
-
- time_t started_t = now_monotonic_sec();
-
- size_t iteration = 0;
- usec_t step = netdata_update_every * USEC_PER_SEC;
-
- heartbeat_t hb;
- heartbeat_init(&hb);
- for(iteration = 0; 1 ; iteration++) {
- usec_t dt = heartbeat_next(&hb, step);
-
- if(debug && iteration)
- fprintf(stderr, "freeipmi.plugin: iteration %zu, dt %llu usec, sensors collected %zu, sensors sent to netdata %zu \n"
- , iteration
- , dt
- , netdata_sensors_collected
- , netdata_sensors_updated
- );
-
- netdata_mark_as_not_updated();
-
- if(debug) fprintf(stderr, "freeipmi.plugin: calling ipmi_collect_data()\n");
- if(ipmi_collect_data(&ipmi_config) < 0)
- fatal("data collection failed.");
-
- if(debug) fprintf(stderr, "freeipmi.plugin: calling send_metrics_to_netdata()\n");
- send_metrics_to_netdata();
- fflush(stdout);
-
- // restart check (14400 seconds)
- if(now_monotonic_sec() - started_t > 14400) exit(0);
- }
-}
-
-#else // !HAVE_FREEIPMI
-
-int main(int argc, char **argv) {
- fatal("freeipmi.plugin is not compiled.");
-}
-
-#endif // !HAVE_FREEIPMI
diff --git a/src/global_statistics.c b/src/global_statistics.c
deleted file mode 100644
index 4f34e92df..000000000
--- a/src/global_statistics.c
+++ /dev/null
@@ -1,414 +0,0 @@
-#include "common.h"
-
-volatile struct global_statistics global_statistics = {
- .connected_clients = 0,
- .web_requests = 0,
- .web_usec = 0,
- .bytes_received = 0,
- .bytes_sent = 0,
- .content_size = 0,
- .compressed_content_size = 0,
- .web_client_count = 1
-};
-
-netdata_mutex_t global_statistics_mutex = NETDATA_MUTEX_INITIALIZER;
-
-inline void global_statistics_lock(void) {
- netdata_mutex_lock(&global_statistics_mutex);
-}
-
-inline void global_statistics_unlock(void) {
- netdata_mutex_unlock(&global_statistics_mutex);
-}
-
-void finished_web_request_statistics(uint64_t dt,
- uint64_t bytes_received,
- uint64_t bytes_sent,
- uint64_t content_size,
- uint64_t compressed_content_size) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- uint64_t old_web_usec_max = global_statistics.web_usec_max;
- while(dt > old_web_usec_max)
- __atomic_compare_exchange(&global_statistics.web_usec_max, &old_web_usec_max, &dt, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
-
- __atomic_fetch_add(&global_statistics.web_requests, 1, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&global_statistics.web_usec, dt, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&global_statistics.bytes_received, bytes_received, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&global_statistics.bytes_sent, bytes_sent, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&global_statistics.content_size, content_size, __ATOMIC_SEQ_CST);
- __atomic_fetch_add(&global_statistics.compressed_content_size, compressed_content_size, __ATOMIC_SEQ_CST);
-#else
-#warning NOT using atomic operations - using locks for global statistics
- if (web_server_is_multithreaded)
- global_statistics_lock();
-
- if (dt > global_statistics.web_usec_max)
- global_statistics.web_usec_max = dt;
-
- global_statistics.web_requests++;
- global_statistics.web_usec += dt;
- global_statistics.bytes_received += bytes_received;
- global_statistics.bytes_sent += bytes_sent;
- global_statistics.content_size += content_size;
- global_statistics.compressed_content_size += compressed_content_size;
-
- if (web_server_is_multithreaded)
- global_statistics_unlock();
-#endif
-}
-
-uint64_t web_client_connected(void) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_add(&global_statistics.connected_clients, 1, __ATOMIC_SEQ_CST);
- uint64_t id = __atomic_fetch_add(&global_statistics.web_client_count, 1, __ATOMIC_SEQ_CST);
-#else
- if (web_server_is_multithreaded)
- global_statistics_lock();
-
- global_statistics.connected_clients++;
- uint64_t id = global_statistics.web_client_count++;
-
- if (web_server_is_multithreaded)
- global_statistics_unlock();
-#endif
-
- return id;
-}
-
-void web_client_disconnected(void) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- __atomic_fetch_sub(&global_statistics.connected_clients, 1, __ATOMIC_SEQ_CST);
-#else
- if (web_server_is_multithreaded)
- global_statistics_lock();
-
- global_statistics.connected_clients--;
-
- if (web_server_is_multithreaded)
- global_statistics_unlock();
-#endif
-}
-
-
-inline void global_statistics_copy(struct global_statistics *gs, uint8_t options) {
-#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
- gs->connected_clients = __atomic_fetch_add(&global_statistics.connected_clients, 0, __ATOMIC_SEQ_CST);
- gs->web_requests = __atomic_fetch_add(&global_statistics.web_requests, 0, __ATOMIC_SEQ_CST);
- gs->web_usec = __atomic_fetch_add(&global_statistics.web_usec, 0, __ATOMIC_SEQ_CST);
- gs->web_usec_max = __atomic_fetch_add(&global_statistics.web_usec_max, 0, __ATOMIC_SEQ_CST);
- gs->bytes_received = __atomic_fetch_add(&global_statistics.bytes_received, 0, __ATOMIC_SEQ_CST);
- gs->bytes_sent = __atomic_fetch_add(&global_statistics.bytes_sent, 0, __ATOMIC_SEQ_CST);
- gs->content_size = __atomic_fetch_add(&global_statistics.content_size, 0, __ATOMIC_SEQ_CST);
- gs->compressed_content_size = __atomic_fetch_add(&global_statistics.compressed_content_size, 0, __ATOMIC_SEQ_CST);
- gs->web_client_count = __atomic_fetch_add(&global_statistics.web_client_count, 0, __ATOMIC_SEQ_CST);
-
- if(options & GLOBAL_STATS_RESET_WEB_USEC_MAX) {
- uint64_t n = 0;
- __atomic_compare_exchange(&global_statistics.web_usec_max, &gs->web_usec_max, &n, 1, __ATOMIC_SEQ_CST,
- __ATOMIC_SEQ_CST);
- }
-#else
- global_statistics_lock();
-
- memcpy(gs, (const void *)&global_statistics, sizeof(struct global_statistics));
-
- if (options & GLOBAL_STATS_RESET_WEB_USEC_MAX)
- global_statistics.web_usec_max = 0;
-
- global_statistics_unlock();
-#endif
-}
-
-void global_statistics_charts(void) {
- static unsigned long long old_web_requests = 0,
- old_web_usec = 0,
- old_content_size = 0,
- old_compressed_content_size = 0;
-
- static collected_number compression_ratio = -1,
- average_response_time = -1;
-
- struct global_statistics gs;
- struct rusage me, thread;
-
- global_statistics_copy(&gs, GLOBAL_STATS_RESET_WEB_USEC_MAX);
- getrusage(RUSAGE_THREAD, &thread);
- getrusage(RUSAGE_SELF, &me);
-
- {
- static RRDSET *st_cpu_thread = NULL;
- static RRDDIM *rd_cpu_thread_user = NULL,
- *rd_cpu_thread_system = NULL;
-
-#ifdef __FreeBSD__
- if (unlikely(!st_cpu_thread)) {
- st_cpu_thread = rrdset_create_localhost(
- "netdata"
- , "plugin_freebsd_cpu"
- , NULL
- , "freebsd"
- , NULL
- , "NetData FreeBSD Plugin CPU usage"
- , "milliseconds/s"
- , "netdata"
- , "stats"
- , 132000
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-#else
- if (unlikely(!st_cpu_thread)) {
- st_cpu_thread = rrdset_create_localhost(
- "netdata"
- , "plugin_proc_cpu"
- , NULL
- , "proc"
- , NULL
- , "NetData Proc Plugin CPU usage"
- , "milliseconds/s"
- , "netdata"
- , "stats"
- , 132000
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-#endif
-
- rd_cpu_thread_user = rrddim_add(st_cpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rd_cpu_thread_system = rrddim_add(st_cpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_cpu_thread);
-
- rrddim_set_by_pointer(st_cpu_thread, rd_cpu_thread_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
- rrddim_set_by_pointer(st_cpu_thread, rd_cpu_thread_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
- rrdset_done(st_cpu_thread);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_cpu = NULL;
- static RRDDIM *rd_cpu_user = NULL,
- *rd_cpu_system = NULL;
-
- if (unlikely(!st_cpu)) {
- st_cpu = rrdset_create_localhost(
- "netdata"
- , "server_cpu"
- , NULL
- , "netdata"
- , NULL
- , "NetData CPU usage"
- , "milliseconds/s"
- , "netdata"
- , "stats"
- , 130000
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_cpu_user = rrddim_add(st_cpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rd_cpu_system = rrddim_add(st_cpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_cpu);
-
- rrddim_set_by_pointer(st_cpu, rd_cpu_user, me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec);
- rrddim_set_by_pointer(st_cpu, rd_cpu_system, me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec);
- rrdset_done(st_cpu);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_clients = NULL;
- static RRDDIM *rd_clients = NULL;
-
- if (unlikely(!st_clients)) {
- st_clients = rrdset_create_localhost(
- "netdata"
- , "clients"
- , NULL
- , "netdata"
- , NULL
- , "NetData Web Clients"
- , "connected clients"
- , "netdata"
- , "stats"
- , 130200
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_clients = rrddim_add(st_clients, "clients", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_clients);
-
- rrddim_set_by_pointer(st_clients, rd_clients, gs.connected_clients);
- rrdset_done(st_clients);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_reqs = NULL;
- static RRDDIM *rd_requests = NULL;
-
- if (unlikely(!st_reqs)) {
- st_reqs = rrdset_create_localhost(
- "netdata"
- , "requests"
- , NULL
- , "netdata"
- , NULL
- , "NetData Web Requests"
- , "requests/s"
- , "netdata"
- , "stats"
- , 130300
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_requests = rrddim_add(st_reqs, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_reqs);
-
- rrddim_set_by_pointer(st_reqs, rd_requests, (collected_number) gs.web_requests);
- rrdset_done(st_reqs);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_bytes = NULL;
- static RRDDIM *rd_in = NULL,
- *rd_out = NULL;
-
- if (unlikely(!st_bytes)) {
- st_bytes = rrdset_create_localhost(
- "netdata"
- , "net"
- , NULL
- , "netdata"
- , NULL
- , "NetData Network Traffic"
- , "kilobits/s"
- , "netdata"
- , "stats"
- , 130000
- , localhost->rrd_update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st_bytes, "in", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_bytes, "out", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_bytes);
-
- rrddim_set_by_pointer(st_bytes, rd_in, (collected_number) gs.bytes_received);
- rrddim_set_by_pointer(st_bytes, rd_out, (collected_number) gs.bytes_sent);
- rrdset_done(st_bytes);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_duration = NULL;
- static RRDDIM *rd_average = NULL,
- *rd_max = NULL;
-
- if (unlikely(!st_duration)) {
- st_duration = rrdset_create_localhost(
- "netdata"
- , "response_time"
- , NULL
- , "netdata"
- , NULL
- , "NetData API Response Time"
- , "ms/request"
- , "netdata"
- , "stats"
- , 130400
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_average = rrddim_add(st_duration, "average", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_max = rrddim_add(st_duration, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_duration);
-
- uint64_t gweb_usec = gs.web_usec;
- uint64_t gweb_requests = gs.web_requests;
-
- uint64_t web_usec = (gweb_usec >= old_web_usec) ? gweb_usec - old_web_usec : 0;
- uint64_t web_requests = (gweb_requests >= old_web_requests) ? gweb_requests - old_web_requests : 0;
-
- old_web_usec = gweb_usec;
- old_web_requests = gweb_requests;
-
- if (web_requests)
- average_response_time = (collected_number) (web_usec / web_requests);
-
- if (unlikely(average_response_time != -1))
- rrddim_set_by_pointer(st_duration, rd_average, average_response_time);
- else
- rrddim_set_by_pointer(st_duration, rd_average, 0);
-
- rrddim_set_by_pointer(st_duration, rd_max, ((gs.web_usec_max)?(collected_number)gs.web_usec_max:average_response_time));
- rrdset_done(st_duration);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_compression = NULL;
- static RRDDIM *rd_savings = NULL;
-
- if (unlikely(!st_compression)) {
- st_compression = rrdset_create_localhost(
- "netdata"
- , "compression_ratio"
- , NULL
- , "netdata"
- , NULL
- , "NetData API Responses Compression Savings Ratio"
- , "percentage"
- , "netdata"
- , "stats"
- , 130500
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_savings = rrddim_add(st_compression, "savings", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_compression);
-
- // since we don't lock here to read the global statistics
- // read the smaller value first
- unsigned long long gcompressed_content_size = gs.compressed_content_size;
- unsigned long long gcontent_size = gs.content_size;
-
- unsigned long long compressed_content_size = gcompressed_content_size - old_compressed_content_size;
- unsigned long long content_size = gcontent_size - old_content_size;
-
- old_compressed_content_size = gcompressed_content_size;
- old_content_size = gcontent_size;
-
- if (content_size && content_size >= compressed_content_size)
- compression_ratio = ((content_size - compressed_content_size) * 100 * 1000) / content_size;
-
- if (compression_ratio != -1)
- rrddim_set_by_pointer(st_compression, rd_savings, compression_ratio);
-
- rrdset_done(st_compression);
- }
-}
diff --git a/src/global_statistics.h b/src/global_statistics.h
deleted file mode 100644
index 62fee6e36..000000000
--- a/src/global_statistics.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef NETDATA_GLOBAL_STATISTICS_H
-#define NETDATA_GLOBAL_STATISTICS_H 1
-
-// ----------------------------------------------------------------------------
-// global statistics
-
-struct global_statistics {
- volatile uint16_t connected_clients;
-
- volatile uint64_t web_requests;
- volatile uint64_t web_usec;
- volatile uint64_t web_usec_max;
- volatile uint64_t bytes_received;
- volatile uint64_t bytes_sent;
- volatile uint64_t content_size;
- volatile uint64_t compressed_content_size;
-
- volatile uint64_t web_client_count;
-};
-
-extern volatile struct global_statistics global_statistics;
-
-extern void global_statistics_lock(void);
-extern void global_statistics_unlock(void);
-extern void finished_web_request_statistics(uint64_t dt,
- uint64_t bytes_received,
- uint64_t bytes_sent,
- uint64_t content_size,
- uint64_t compressed_content_size);
-
-extern uint64_t web_client_connected(void);
-extern void web_client_disconnected(void);
-
-#define GLOBAL_STATS_RESET_WEB_USEC_MAX 0x01
-extern void global_statistics_copy(struct global_statistics *gs, uint8_t options);
-extern void global_statistics_charts(void);
-
-#endif /* NETDATA_GLOBAL_STATISTICS_H */
diff --git a/src/health.c b/src/health.c
deleted file mode 100644
index 04e04f089..000000000
--- a/src/health.c
+++ /dev/null
@@ -1,737 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-int default_health_enabled = 1;
-
-// ----------------------------------------------------------------------------
-// health initialization
-
-inline char *health_config_dir(void) {
- char buffer[FILENAME_MAX + 1];
- snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_config_dir);
- return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer);
-}
-
-void health_init(void) {
- debug(D_HEALTH, "Health configuration initializing");
-
- if(!(default_health_enabled = config_get_boolean(CONFIG_SECTION_HEALTH, "enabled", 1))) {
- debug(D_HEALTH, "Health is disabled.");
- return;
- }
-}
-
-// ----------------------------------------------------------------------------
-// re-load health configuration
-
-void health_reload_host(RRDHOST *host) {
- if(unlikely(!host->health_enabled))
- return;
-
- char *path = health_config_dir();
-
- // free all running alarms
- rrdhost_wrlock(host);
-
- while(host->templates)
- rrdcalctemplate_unlink_and_free(host, host->templates);
-
- while(host->alarms)
- rrdcalc_unlink_and_free(host, host->alarms);
-
- rrdhost_unlock(host);
-
- // invalidate all previous entries in the alarm log
- ALARM_ENTRY *t;
- for(t = host->health_log.alarms ; t ; t = t->next) {
- if(t->new_status != RRDCALC_STATUS_REMOVED)
- t->flags |= HEALTH_ENTRY_FLAG_UPDATED;
- }
-
- rrdhost_rdlock(host);
- // reset all thresholds to all charts
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- st->green = NAN;
- st->red = NAN;
- }
- rrdhost_unlock(host);
-
- // load the new alarms
- rrdhost_wrlock(host);
- health_readdir(host, path);
-
- // link the loaded alarms to their charts
- rrdset_foreach_write(st, host) {
- rrdsetcalc_link_matching(st);
- rrdcalctemplate_link_matching(st);
- }
-
- rrdhost_unlock(host);
-}
-
-void health_reload(void) {
-
- rrd_rdlock();
-
- RRDHOST *host;
- rrdhost_foreach_read(host)
- health_reload_host(host);
-
- rrd_unlock();
-}
-
-// ----------------------------------------------------------------------------
-// health main thread and friends
-
-static inline RRDCALC_STATUS rrdcalc_value2status(calculated_number n) {
- if(isnan(n) || isinf(n)) return RRDCALC_STATUS_UNDEFINED;
- if(n) return RRDCALC_STATUS_RAISED;
- return RRDCALC_STATUS_CLEAR;
-}
-
-#define ALARM_EXEC_COMMAND_LENGTH 8192
-
-static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) {
- ae->flags |= HEALTH_ENTRY_FLAG_PROCESSED;
-
- if(unlikely(ae->new_status < RRDCALC_STATUS_CLEAR)) {
- // do not send notifications for internal statuses
- debug(D_HEALTH, "Health not sending notification for alarm '%s.%s' status %s (internal statuses)", ae->chart, ae->name, rrdcalc_status2string(ae->new_status));
- goto done;
- }
-
- if(unlikely(ae->new_status <= RRDCALC_STATUS_CLEAR && (ae->flags & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION))) {
- // do not send notifications for disabled statuses
- debug(D_HEALTH, "Health not sending notification for alarm '%s.%s' status %s (it has no-clear-notification enabled)", ae->chart, ae->name, rrdcalc_status2string(ae->new_status));
- // mark it as run, so that we will send the same alarm if it happens again
- goto done;
- }
-
- // find the previous notification for the same alarm
- // which we have run the exec script
- // exception: alarms with HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION set
- if(likely(!(ae->flags & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION))) {
- uint32_t id = ae->alarm_id;
- ALARM_ENTRY *t;
- for(t = ae->next; t ; t = t->next) {
- if(t->alarm_id == id && t->flags & HEALTH_ENTRY_FLAG_EXEC_RUN)
- break;
- }
-
- if(likely(t)) {
- // we have executed this alarm notification in the past
- if(t && t->new_status == ae->new_status) {
- // don't send the notification for the same status again
- debug(D_HEALTH, "Health not sending again notification for alarm '%s.%s' status %s", ae->chart, ae->name
- , rrdcalc_status2string(ae->new_status));
- goto done;
- }
- }
- else {
- // we have not executed this alarm notification in the past
- // so, don't send CLEAR notifications
- if(unlikely(ae->new_status == RRDCALC_STATUS_CLEAR)) {
- debug(D_HEALTH, "Health not sending notification for first initialization of alarm '%s.%s' status %s"
- , ae->chart, ae->name, rrdcalc_status2string(ae->new_status));
- goto done;
- }
- }
- }
-
- static char command_to_run[ALARM_EXEC_COMMAND_LENGTH + 1];
- pid_t command_pid;
-
- const char *exec = (ae->exec) ? ae->exec : host->health_default_exec;
- const char *recipient = (ae->recipient) ? ae->recipient : host->health_default_recipient;
-
- snprintfz(command_to_run, ALARM_EXEC_COMMAND_LENGTH, "exec %s '%s' '%s' '%u' '%u' '%u' '%lu' '%s' '%s' '%s' '%s' '%s' '" CALCULATED_NUMBER_FORMAT_ZERO "' '" CALCULATED_NUMBER_FORMAT_ZERO "' '%s' '%u' '%u' '%s' '%s' '%s' '%s'",
- exec,
- recipient,
- host->registry_hostname,
- ae->unique_id,
- ae->alarm_id,
- ae->alarm_event_id,
- (unsigned long)ae->when,
- ae->name,
- ae->chart?ae->chart:"NOCAHRT",
- ae->family?ae->family:"NOFAMILY",
- rrdcalc_status2string(ae->new_status),
- rrdcalc_status2string(ae->old_status),
- ae->new_value,
- ae->old_value,
- ae->source?ae->source:"UNKNOWN",
- (uint32_t)ae->duration,
- (uint32_t)ae->non_clear_duration,
- ae->units?ae->units:"",
- ae->info?ae->info:"",
- ae->new_value_string,
- ae->old_value_string
- );
-
- ae->flags |= HEALTH_ENTRY_FLAG_EXEC_RUN;
- ae->exec_run_timestamp = now_realtime_sec();
-
- debug(D_HEALTH, "executing command '%s'", command_to_run);
- FILE *fp = mypopen(command_to_run, &command_pid);
- if(!fp) {
- error("HEALTH: Cannot popen(\"%s\", \"r\").", command_to_run);
- goto done;
- }
- debug(D_HEALTH, "HEALTH reading from command");
- char *s = fgets(command_to_run, FILENAME_MAX, fp);
- (void)s;
- ae->exec_code = mypclose(fp, command_pid);
- debug(D_HEALTH, "done executing command - returned with code %d", ae->exec_code);
-
- if(ae->exec_code != 0)
- ae->flags |= HEALTH_ENTRY_FLAG_EXEC_FAILED;
-
-done:
- health_alarm_log_save(host, ae);
-}
-
-static inline void health_process_notifications(RRDHOST *host, ALARM_ENTRY *ae) {
- debug(D_HEALTH, "Health alarm '%s.%s' = " CALCULATED_NUMBER_FORMAT_AUTO " - changed status from %s to %s",
- ae->chart?ae->chart:"NOCHART", ae->name,
- ae->new_value,
- rrdcalc_status2string(ae->old_status),
- rrdcalc_status2string(ae->new_status)
- );
-
- health_alarm_execute(host, ae);
-}
-
-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();
-
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
-
- ALARM_ENTRY *ae;
- for(ae = host->health_log.alarms; ae && ae->unique_id >= host->health_last_processed_id ; ae = ae->next) {
- if(unlikely(
- !(ae->flags & HEALTH_ENTRY_FLAG_PROCESSED) &&
- !(ae->flags & HEALTH_ENTRY_FLAG_UPDATED)
- )) {
-
- if(unlikely(ae->unique_id < first_waiting))
- first_waiting = ae->unique_id;
-
- if(likely(now >= ae->delay_up_to_timestamp))
- health_process_notifications(host, ae);
- }
- }
-
- // remember this for the next iteration
- host->health_last_processed_id = first_waiting;
-
- 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
- netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
-
- ALARM_ENTRY *last = NULL;
- unsigned int count = host->health_log.max * 2 / 3;
- for(ae = host->health_log.alarms; ae && count ; count--, last = ae, ae = ae->next) ;
-
- if(ae && last && last->next == ae)
- last->next = NULL;
- else
- ae = NULL;
-
- while(ae) {
- debug(D_HEALTH, "Health removing alarm log entry with id: %u", ae->unique_id);
-
- ALARM_ENTRY *t = ae->next;
-
- health_alarm_log_free_one_nochecks_nounlink(ae);
-
- ae = t;
- host->health_log.count--;
- }
-
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-}
-
-static inline int rrdcalc_isrunnable(RRDCALC *rc, time_t now, time_t *next_run) {
- if(unlikely(!rc->rrdset)) {
- debug(D_HEALTH, "Health not running alarm '%s.%s'. It is not linked to a chart.", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- if(unlikely(rc->next_update > now)) {
- if (unlikely(*next_run > rc->next_update)) {
- // update the next_run time of the main loop
- // to run this alarm precisely the time required
- *next_run = rc->next_update;
- }
-
- debug(D_HEALTH, "Health not examining alarm '%s.%s' yet (will do in %d secs).", rc->chart?rc->chart:"NOCHART", rc->name, (int) (rc->next_update - now));
- return 0;
- }
-
- if(unlikely(!rc->update_every)) {
- debug(D_HEALTH, "Health not running alarm '%s.%s'. It does not have an update frequency", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- if(unlikely(rrdset_flag_check(rc->rrdset, RRDSET_FLAG_OBSOLETE))) {
- debug(D_HEALTH, "Health not running alarm '%s.%s'. The chart has been marked as obsolete", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- if(unlikely(!rrdset_flag_check(rc->rrdset, RRDSET_FLAG_ENABLED))) {
- debug(D_HEALTH, "Health not running alarm '%s.%s'. The chart is not enabled", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- if(unlikely(!rc->rrdset->last_collected_time.tv_sec || rc->rrdset->counter_done < 2)) {
- debug(D_HEALTH, "Health not running alarm '%s.%s'. Chart is not fully collected yet.", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- int update_every = rc->rrdset->update_every;
- time_t first = rrdset_first_entry_t(rc->rrdset);
- time_t last = rrdset_last_entry_t(rc->rrdset);
-
- if(unlikely(now + update_every < first /* || now - update_every > last */)) {
- debug(D_HEALTH
- , "Health not examining alarm '%s.%s' yet (wanted time is out of bounds - we need %lu but got %lu - %lu)."
- , rc->chart ? rc->chart : "NOCHART", rc->name, (unsigned long) now, (unsigned long) first
- , (unsigned long) last);
- return 0;
- }
-
- if(RRDCALC_HAS_DB_LOOKUP(rc)) {
- time_t needed = now + rc->before + rc->after;
-
- if(needed + update_every < first || needed - update_every > last) {
- debug(D_HEALTH
- , "Health not examining alarm '%s.%s' yet (not enough data yet - we need %lu but got %lu - %lu)."
- , rc->chart ? rc->chart : "NOCHART", rc->name, (unsigned long) needed, (unsigned long) first
- , (unsigned long) last);
- return 0;
- }
- }
-
- return 1;
-}
-
-static inline int check_if_resumed_from_suspention(void) {
- static usec_t last_realtime = 0, last_monotonic = 0;
- usec_t realtime = now_realtime_usec(), monotonic = now_monotonic_usec();
- int ret = 0;
-
- // detect if monotonic and realtime have twice the difference
- // in which case we assume the system was just waken from hibernation
-
- if(last_realtime && last_monotonic && realtime - last_realtime > 2 * (monotonic - last_monotonic))
- ret = 1;
-
- last_realtime = realtime;
- last_monotonic = monotonic;
-
- return ret;
-}
-
-static void health_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *health_main(void *ptr) {
- netdata_thread_cleanup_push(health_main_cleanup, ptr);
-
- int min_run_every = (int)config_get_number(CONFIG_SECTION_HEALTH, "run at least every seconds", 10);
- if(min_run_every < 1) min_run_every = 1;
-
- time_t now = now_realtime_sec();
- time_t hibernation_delay = config_get_number(CONFIG_SECTION_HEALTH, "postpone alarms during hibernation for seconds", 60);
-
- unsigned int loop = 0;
- while(!netdata_exit) {
- loop++;
- debug(D_HEALTH, "Health monitoring iteration no %u started", loop);
-
- int runnable = 0, apply_hibernation_delay = 0;
- time_t next_run = now + min_run_every;
- RRDCALC *rc;
-
- if(unlikely(check_if_resumed_from_suspention())) {
- apply_hibernation_delay = 1;
-
- info("Postponing alarm checks for %ld seconds, because it seems that the system was just resumed from suspension."
- , hibernation_delay
- );
- }
-
- rrd_rdlock();
-
- RRDHOST *host;
- rrdhost_foreach_read(host) {
- if(unlikely(!host->health_enabled))
- continue;
-
- if(unlikely(apply_hibernation_delay)) {
-
- info("Postponing health checks for %ld seconds, on host '%s'."
- , hibernation_delay
- , host->hostname
- );
-
- host->health_delay_up_to = now + hibernation_delay;
- }
-
- if(unlikely(host->health_delay_up_to)) {
- if(unlikely(now < host->health_delay_up_to))
- continue;
-
- info("Resuming health checks on host '%s'.", host->hostname);
- host->health_delay_up_to = 0;
- }
-
- rrdhost_rdlock(host);
-
- // the first loop is to lookup values from the db
- for(rc = host->alarms; rc; rc = rc->next) {
- if(unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) {
- if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE))
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_RUNNABLE;
- continue;
- }
-
- runnable++;
- rc->old_value = rc->value;
- rc->rrdcalc_flags |= RRDCALC_FLAG_RUNNABLE;
-
- // ------------------------------------------------------------
- // if there is database lookup, do it
-
- if(unlikely(RRDCALC_HAS_DB_LOOKUP(rc))) {
- /* time_t old_db_timestamp = rc->db_before; */
- int value_is_null = 0;
-
- int ret = rrdset2value_api_v1(rc->rrdset
- , NULL
- , &rc->value
- , rc->dimensions
- , 1
- , rc->after
- , rc->before
- , rc->group
- , 0
- , rc->options
- , &rc->db_after
- , &rc->db_before
- , &value_is_null
- );
-
- if(unlikely(ret != 200)) {
- // database lookup failed
- rc->value = NAN;
- rc->rrdcalc_flags |= RRDCALC_FLAG_DB_ERROR;
-
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': database lookup returned error %d"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , ret
- );
- }
- else
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_ERROR;
-
- /* - RRDCALC_FLAG_DB_STALE not currently used
- if (unlikely(old_db_timestamp == rc->db_before)) {
- // database is stale
-
- debug(D_HEALTH, "Health on host '%s', alarm '%s.%s': database is stale", host->hostname, rc->chart?rc->chart:"NOCHART", rc->name);
-
- if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE))) {
- rc->rrdcalc_flags |= RRDCALC_FLAG_DB_STALE;
- error("Health on host '%s', alarm '%s.%s': database is stale", host->hostname, rc->chart?rc->chart:"NOCHART", rc->name);
- }
- }
- else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE))
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_STALE;
- */
-
- if(unlikely(value_is_null)) {
- // collected value is null
- rc->value = NAN;
- rc->rrdcalc_flags |= RRDCALC_FLAG_DB_NAN;
-
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': database lookup returned empty value (possibly value is not collected yet)"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- );
- }
- else
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_NAN;
-
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': database lookup gave value " CALCULATED_NUMBER_FORMAT
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , rc->value
- );
- }
-
- // ------------------------------------------------------------
- // if there is calculation expression, run it
-
- if(unlikely(rc->calculation)) {
- if(unlikely(!expression_evaluate(rc->calculation))) {
- // calculation failed
- rc->value = NAN;
- rc->rrdcalc_flags |= RRDCALC_FLAG_CALC_ERROR;
-
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': expression '%s' failed: %s"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , rc->calculation->parsed_as
- , buffer_tostring(rc->calculation->error_msg)
- );
- }
- else {
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_CALC_ERROR;
-
- debug(D_HEALTH, "Health on host '%s', alarm '%s.%s': expression '%s' gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , rc->calculation->parsed_as
- , rc->calculation->result
- , buffer_tostring(rc->calculation->error_msg)
- , rc->source
- );
-
- rc->value = rc->calculation->result;
- }
- }
- }
- rrdhost_unlock(host);
-
- if(unlikely(runnable && !netdata_exit)) {
- rrdhost_rdlock(host);
-
- for(rc = host->alarms; rc; rc = rc->next) {
- if(unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE)))
- continue;
-
- RRDCALC_STATUS warning_status = RRDCALC_STATUS_UNDEFINED;
- RRDCALC_STATUS critical_status = RRDCALC_STATUS_UNDEFINED;
-
- // --------------------------------------------------------
- // check the warning expression
-
- if(likely(rc->warning)) {
- if(unlikely(!expression_evaluate(rc->warning))) {
- // calculation failed
- rc->rrdcalc_flags |= RRDCALC_FLAG_WARN_ERROR;
-
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': warning expression failed with error: %s"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , buffer_tostring(rc->warning->error_msg)
- );
- }
- else {
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_WARN_ERROR;
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': warning expression gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , rc->warning->result
- , buffer_tostring(rc->warning->error_msg)
- , rc->source
- );
- warning_status = rrdcalc_value2status(rc->warning->result);
- }
- }
-
- // --------------------------------------------------------
- // check the critical expression
-
- if(likely(rc->critical)) {
- if(unlikely(!expression_evaluate(rc->critical))) {
- // calculation failed
- rc->rrdcalc_flags |= RRDCALC_FLAG_CRIT_ERROR;
-
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': critical expression failed with error: %s"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , buffer_tostring(rc->critical->error_msg)
- );
- }
- else {
- rc->rrdcalc_flags &= ~RRDCALC_FLAG_CRIT_ERROR;
- debug(D_HEALTH
- , "Health on host '%s', alarm '%s.%s': critical expression gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)"
- , host->hostname
- , rc->chart ? rc->chart : "NOCHART"
- , rc->name
- , rc->critical->result
- , buffer_tostring(rc->critical->error_msg)
- , rc->source
- );
- critical_status = rrdcalc_value2status(rc->critical->result);
- }
- }
-
- // --------------------------------------------------------
- // decide the final alarm status
-
- RRDCALC_STATUS status = RRDCALC_STATUS_UNDEFINED;
-
- switch(warning_status) {
- case RRDCALC_STATUS_CLEAR:
- status = RRDCALC_STATUS_CLEAR;
- break;
-
- case RRDCALC_STATUS_RAISED:
- status = RRDCALC_STATUS_WARNING;
- break;
-
- default:
- break;
- }
-
- switch(critical_status) {
- case RRDCALC_STATUS_CLEAR:
- if(status == RRDCALC_STATUS_UNDEFINED)
- status = RRDCALC_STATUS_CLEAR;
- break;
-
- case RRDCALC_STATUS_RAISED:
- status = RRDCALC_STATUS_CRITICAL;
- break;
-
- default:
- break;
- }
-
- // --------------------------------------------------------
- // check if the new status and the old differ
-
- if(status != rc->status) {
- int delay = 0;
-
- // apply trigger hysteresis
-
- if(now > rc->delay_up_to_timestamp) {
- rc->delay_up_current = rc->delay_up_duration;
- rc->delay_down_current = rc->delay_down_duration;
- rc->delay_last = 0;
- rc->delay_up_to_timestamp = 0;
- }
- else {
- rc->delay_up_current = (int) (rc->delay_up_current * rc->delay_multiplier);
- if(rc->delay_up_current > rc->delay_max_duration)
- rc->delay_up_current = rc->delay_max_duration;
-
- rc->delay_down_current = (int) (rc->delay_down_current * rc->delay_multiplier);
- if(rc->delay_down_current > rc->delay_max_duration)
- rc->delay_down_current = rc->delay_max_duration;
- }
-
- if(status > rc->status)
- delay = rc->delay_up_current;
- else
- delay = rc->delay_down_current;
-
- // COMMENTED: because we do need to send raising alarms
- // if(now + delay < rc->delay_up_to_timestamp)
- // delay = (int)(rc->delay_up_to_timestamp - now);
-
- rc->delay_last = delay;
- rc->delay_up_to_timestamp = now + delay;
-
- // add the alarm into the log
-
- health_alarm_log(
- host
- , rc->id
- , rc->next_event_id++
- , now
- , rc->name
- , rc->rrdset->id
- , rc->rrdset->family
- , rc->exec
- , rc->recipient
- , now - rc->last_status_change
- , rc->old_value
- , rc->value
- , rc->status
- , status
- , rc->source
- , rc->units
- , rc->info
- , rc->delay_last
- , (rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION) ? HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION : 0
- );
-
- rc->last_status_change = now;
- rc->status = status;
- }
-
- rc->last_updated = now;
- rc->next_update = now + rc->update_every;
-
- if(next_run > rc->next_update)
- next_run = rc->next_update;
- }
-
- rrdhost_unlock(host);
- }
-
- if(unlikely(netdata_exit))
- break;
-
- // execute notifications
- // and cleanup
- health_alarm_log_process(host);
-
- if(unlikely(netdata_exit))
- break;
-
- } /* rrdhost_foreach */
-
- rrd_unlock();
-
- if(unlikely(netdata_exit))
- break;
-
- now = now_realtime_sec();
- if(now < next_run) {
- debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration in %d secs", loop, (int) (next_run - now));
- sleep_usec(USEC_PER_SEC * (usec_t) (next_run - now));
- now = now_realtime_sec();
- }
- else
- debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration now", loop);
-
- } // forever
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/health.h b/src/health.h
deleted file mode 100644
index f41571803..000000000
--- a/src/health.h
+++ /dev/null
@@ -1,438 +0,0 @@
-#ifndef NETDATA_HEALTH_H
-#define NETDATA_HEALTH_H
-
-extern int default_health_enabled;
-
-extern int rrdvar_compare(void *a, void *b);
-
-typedef enum rrdvar_type {
- RRDVAR_TYPE_CALCULATED = 1,
- RRDVAR_TYPE_TIME_T = 2,
- RRDVAR_TYPE_COLLECTED = 3,
- RRDVAR_TYPE_TOTAL = 4,
- RRDVAR_TYPE_INT = 5,
- RRDVAR_TYPE_CALCULATED_ALLOCATED = 6 // a custom variable, allocated on purpose (ie. not inherited from charts)
- // used only for custom host global variables
-} RRDVAR_TYPE;
-
-// the variables as stored in the variables indexes
-// there are 3 indexes:
-// 1. at each chart (RRDSET.rrdvar_root_index)
-// 2. at each context (RRDFAMILY.rrdvar_root_index)
-// 3. at each host (RRDHOST.rrdvar_root_index)
-typedef struct rrdvar {
- avl avl;
-
- char *name;
- uint32_t hash;
-
- RRDVAR_TYPE type;
- void *value;
-
- time_t last_updated;
-} RRDVAR;
-
-// variables linked to charts
-// We link variables to point to the values that are already
-// calculated / processed by the normal data collection process
-// This means, there will be no speed penalty for using
-// these variables
-
-typedef enum rrdvar_options {
- RRDVAR_OPTION_DEFAULT = (0 << 0),
- RRDVAR_OPTION_ALLOCATED = (1 << 0) // the value ptr is allocated (not a reference)
- // future use
-} RRDVAR_OPTIONS;
-
-typedef struct rrdsetvar {
- char *variable; // variable name
- uint32_t hash; // variable name hash
-
- char *key_fullid; // chart type.chart id.variable
- char *key_fullname; // chart type.chart name.variable
-
- RRDVAR_TYPE type;
- void *value;
-
- RRDVAR_OPTIONS options;
-
- RRDVAR *var_local;
- RRDVAR *var_family;
- RRDVAR *var_host;
- RRDVAR *var_family_name;
- RRDVAR *var_host_name;
-
- struct rrdset *rrdset;
-
- struct rrdsetvar *next;
-} RRDSETVAR;
-
-
-// variables linked to individual dimensions
-// We link variables to point the values that are already
-// calculated / processed by the normal data collection process
-// This means, there will be no speed penalty for using
-// these variables
-typedef struct rrddimvar {
- char *prefix;
- char *suffix;
-
- char *key_id; // dimension id
- char *key_name; // dimension name
- char *key_contextid; // context + dimension id
- char *key_contextname; // context + dimension name
- char *key_fullidid; // chart type.chart id + dimension id
- char *key_fullidname; // chart type.chart id + dimension name
- char *key_fullnameid; // chart type.chart name + dimension id
- char *key_fullnamename; // chart type.chart name + dimension name
-
- RRDVAR_TYPE type;
- void *value;
-
- RRDVAR_OPTIONS options;
-
- RRDVAR *var_local_id;
- RRDVAR *var_local_name;
-
- RRDVAR *var_family_id;
- RRDVAR *var_family_name;
- RRDVAR *var_family_contextid;
- RRDVAR *var_family_contextname;
-
- RRDVAR *var_host_chartidid;
- RRDVAR *var_host_chartidname;
- RRDVAR *var_host_chartnameid;
- RRDVAR *var_host_chartnamename;
-
- struct rrddim *rrddim;
-
- struct rrddimvar *next;
-} RRDDIMVAR;
-
-// calculated variables (defined in health configuration)
-// These aggregate time-series data at fixed intervals
-// (defined in their update_every member below)
-// They increase the overhead of netdata.
-//
-// These calculations are allocated and linked (->next)
-// under RRDHOST.
-// Then are also linked to RRDSET (of course only when the
-// chart is found, via ->rrdset_next and ->rrdset_prev).
-// This double-linked list is maintained sorted at all times
-// having as RRDSET.calculations the RRDCALC to be processed
-// next.
-
-#define RRDCALC_FLAG_DB_ERROR 0x00000001
-#define RRDCALC_FLAG_DB_NAN 0x00000002
-/* #define RRDCALC_FLAG_DB_STALE 0x00000004 */
-#define RRDCALC_FLAG_CALC_ERROR 0x00000008
-#define RRDCALC_FLAG_WARN_ERROR 0x00000010
-#define RRDCALC_FLAG_CRIT_ERROR 0x00000020
-#define RRDCALC_FLAG_RUNNABLE 0x00000040
-#define RRDCALC_FLAG_NO_CLEAR_NOTIFICATION 0x80000000
-
-typedef struct rrdcalc {
- uint32_t id; // the unique id of this alarm
- uint32_t next_event_id; // the next event id that will be used for this alarm
-
- char *name; // the name of this alarm
- uint32_t hash;
-
- char *exec; // the command to execute when this alarm switches state
- char *recipient; // the recipient of the alarm (the first parameter to exec)
-
- char *chart; // the chart id this should be linked to
- uint32_t hash_chart;
-
- char *source; // the source of this alarm
- char *units; // the units of the alarm
- char *info; // a short description of the alarm
-
- int update_every; // update frequency for the alarm
-
- // the red and green threshold of this alarm (to be set to the chart)
- calculated_number green;
- calculated_number red;
-
- // ------------------------------------------------------------------------
- // database lookup settings
-
- char *dimensions; // the chart dimensions
- int group; // grouping method: average, max, etc.
- int before; // ending point in time-series
- int after; // starting point in time-series
- uint32_t options; // calculation options
-
- // ------------------------------------------------------------------------
- // expressions related to the alarm
-
- EVAL_EXPRESSION *calculation; // expression to calculate the value of the alarm
- EVAL_EXPRESSION *warning; // expression to check the warning condition
- EVAL_EXPRESSION *critical; // expression to check the critical condition
-
- // ------------------------------------------------------------------------
- // notification delay settings
-
- int delay_up_duration; // duration to delay notifications when alarm raises
- int delay_down_duration; // duration to delay notifications when alarm lowers
- int delay_max_duration; // the absolute max delay to apply to this alarm
- float delay_multiplier; // multiplier for all delays when alarms switch status
- // while now < delay_up_to
-
- // ------------------------------------------------------------------------
- // runtime information
-
- RRDCALC_STATUS status; // the current status of the alarm
-
- calculated_number value; // the current value of the alarm
- calculated_number old_value; // the previous value of the alarm
-
- uint32_t rrdcalc_flags; // check RRDCALC_FLAG_*
-
- time_t last_updated; // the last update timestamp of the alarm
- time_t next_update; // the next update timestamp of the alarm
- time_t last_status_change; // the timestamp of the last time this alarm changed status
-
- time_t db_after; // the first timestamp evaluated by the db lookup
- time_t db_before; // the last timestamp evaluated by the db lookup
-
- time_t delay_up_to_timestamp; // the timestamp up to which we should delay notifications
- int delay_up_current; // the current up notification delay duration
- int delay_down_current; // the current down notification delay duration
- int delay_last; // the last delay we used
-
- // ------------------------------------------------------------------------
- // variables this alarm exposes to the rest of the alarms
-
- RRDVAR *local;
- RRDVAR *family;
- RRDVAR *hostid;
- RRDVAR *hostname;
-
- // ------------------------------------------------------------------------
- // the chart this alarm it is linked to
-
- struct rrdset *rrdset;
-
- // linking of this alarm on its chart
- struct rrdcalc *rrdset_next;
- struct rrdcalc *rrdset_prev;
-
- struct rrdcalc *next;
-} RRDCALC;
-
-#define RRDCALC_HAS_DB_LOOKUP(rc) ((rc)->after)
-
-// RRDCALCTEMPLATE
-// these are to be applied to charts found dynamically
-// based on their context.
-typedef struct rrdcalctemplate {
- char *name;
- uint32_t hash_name;
-
- char *exec;
- char *recipient;
-
- char *context;
- uint32_t hash_context;
-
- char *family_match;
- SIMPLE_PATTERN *family_pattern;
-
- char *source; // the source of this alarm
- char *units; // the units of the alarm
- char *info; // a short description of the alarm
-
- int update_every; // update frequency for the alarm
-
- // the red and green threshold of this alarm (to be set to the chart)
- calculated_number green;
- calculated_number red;
-
- // ------------------------------------------------------------------------
- // database lookup settings
-
- char *dimensions; // the chart dimensions
- int group; // grouping method: average, max, etc.
- int before; // ending point in time-series
- int after; // starting point in time-series
- uint32_t options; // calculation options
-
- // ------------------------------------------------------------------------
- // notification delay settings
-
- int delay_up_duration; // duration to delay notifications when alarm raises
- int delay_down_duration; // duration to delay notifications when alarm lowers
- int delay_max_duration; // the absolute max delay to apply to this alarm
- float delay_multiplier; // multiplier for all delays when alarms switch status
-
- // ------------------------------------------------------------------------
- // expressions related to the alarm
-
- EVAL_EXPRESSION *calculation;
- EVAL_EXPRESSION *warning;
- EVAL_EXPRESSION *critical;
-
- struct rrdcalctemplate *next;
-} RRDCALCTEMPLATE;
-
-#define RRDCALCTEMPLATE_HAS_CALCULATION(rt) ((rt)->after)
-
-#define HEALTH_ENTRY_FLAG_PROCESSED 0x00000001
-#define HEALTH_ENTRY_FLAG_UPDATED 0x00000002
-#define HEALTH_ENTRY_FLAG_EXEC_RUN 0x00000004
-#define HEALTH_ENTRY_FLAG_EXEC_FAILED 0x00000008
-#define HEALTH_ENTRY_FLAG_SAVED 0x10000000
-#define HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION 0x80000000
-
-typedef struct alarm_entry {
- uint32_t unique_id;
- uint32_t alarm_id;
- uint32_t alarm_event_id;
-
- time_t when;
- time_t duration;
- time_t non_clear_duration;
-
- char *name;
- uint32_t hash_name;
-
- char *chart;
- uint32_t hash_chart;
-
- char *family;
-
- char *exec;
- char *recipient;
- time_t exec_run_timestamp;
- int exec_code;
-
- char *source;
- char *units;
- char *info;
-
- calculated_number old_value;
- calculated_number new_value;
-
- char *old_value_string;
- char *new_value_string;
-
- RRDCALC_STATUS old_status;
- RRDCALC_STATUS new_status;
-
- uint32_t flags;
-
- int delay;
- time_t delay_up_to_timestamp;
-
- uint32_t updated_by_id;
- uint32_t updates_id;
-
- struct alarm_entry *next;
-} ALARM_ENTRY;
-
-typedef struct alarm_log {
- uint32_t next_log_id;
- uint32_t next_alarm_id;
- unsigned int count;
- unsigned int max;
- ALARM_ENTRY *alarms;
- netdata_rwlock_t alarm_log_rwlock;
-} ALARM_LOG;
-
-#include "rrd.h"
-
-extern void rrdsetvar_rename_all(RRDSET *st);
-extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options);
-extern void rrdsetvar_free(RRDSETVAR *rs);
-
-extern void rrddimvar_rename_all(RRDDIM *rd);
-extern RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options);
-extern void rrddimvar_free(RRDDIMVAR *rs);
-
-extern void rrdsetcalc_link_matching(RRDSET *st);
-extern void rrdsetcalc_unlink(RRDCALC *rc);
-extern void rrdcalctemplate_link_matching(RRDSET *st);
-extern RRDCALC *rrdcalc_find(RRDSET *st, const char *name);
-
-extern void health_init(void);
-extern void *health_main(void *ptr);
-
-extern void health_reload(void);
-
-extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result);
-extern void health_alarms2json(RRDHOST *host, BUFFER *wb, int all);
-extern void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after);
-
-void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf);
-
-extern RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name);
-extern void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value);
-
-extern RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name);
-extern void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rv, calculated_number value);
-
-extern void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock);
-
-extern const char *rrdcalc_status2string(RRDCALC_STATUS status);
-
-
-extern int health_alarm_log_open(RRDHOST *host);
-extern void health_alarm_log_close(RRDHOST *host);
-extern void health_log_rotate(RRDHOST *host);
-extern void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae);
-extern ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename);
-extern void health_alarm_log_load(RRDHOST *host);
-extern void health_alarm_log(
- RRDHOST *host,
- uint32_t alarm_id,
- uint32_t alarm_event_id,
- time_t when,
- const char *name,
- const char *chart,
- const char *family,
- const char *exec,
- const char *recipient,
- time_t duration,
- calculated_number old_value,
- calculated_number new_value,
- RRDCALC_STATUS old_status,
- RRDCALC_STATUS new_status,
- const char *source,
- const char *units,
- const char *info,
- int delay,
- uint32_t flags
-);
-
-extern void health_readdir(RRDHOST *host, const char *path);
-extern char *health_config_dir(void);
-extern void health_reload_host(RRDHOST *host);
-extern void health_alarm_log_free(RRDHOST *host);
-
-extern void rrdcalc_free(RRDCALC *rc);
-extern void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc);
-
-extern void rrdcalctemplate_free(RRDCALCTEMPLATE *rt);
-extern void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt);
-
-extern int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data);
-
-#ifdef NETDATA_HEALTH_INTERNALS
-#define RRDVAR_MAX_LENGTH 1024
-
-extern int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name);
-extern uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id);
-extern int rrdvar_fix_name(char *variable);
-
-extern RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart);
-extern void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc);
-
-extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value);
-extern void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv);
-
-extern void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae);
-
-#endif // NETDATA_HEALTH_INTERNALS
-
-#endif //NETDATA_HEALTH_H
diff --git a/src/health_config.c b/src/health_config.c
deleted file mode 100644
index a25ee7227..000000000
--- a/src/health_config.c
+++ /dev/null
@@ -1,900 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-#define HEALTH_CONF_MAX_LINE 4096
-
-#define HEALTH_ALARM_KEY "alarm"
-#define HEALTH_TEMPLATE_KEY "template"
-#define HEALTH_ON_KEY "on"
-#define HEALTH_HOST_KEY "hosts"
-#define HEALTH_OS_KEY "os"
-#define HEALTH_FAMILIES_KEY "families"
-#define HEALTH_LOOKUP_KEY "lookup"
-#define HEALTH_CALC_KEY "calc"
-#define HEALTH_EVERY_KEY "every"
-#define HEALTH_GREEN_KEY "green"
-#define HEALTH_RED_KEY "red"
-#define HEALTH_WARN_KEY "warn"
-#define HEALTH_CRIT_KEY "crit"
-#define HEALTH_EXEC_KEY "exec"
-#define HEALTH_RECIPIENT_KEY "to"
-#define HEALTH_UNITS_KEY "units"
-#define HEALTH_INFO_KEY "info"
-#define HEALTH_DELAY_KEY "delay"
-#define HEALTH_OPTIONS_KEY "options"
-
-static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) {
- if(!rc->chart) {
- error("Health configuration for alarm '%s' does not have a chart", rc->name);
- return 0;
- }
-
- if(!rc->update_every) {
- error("Health configuration for alarm '%s.%s' has no frequency (parameter 'every'). Ignoring it.", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- if(!RRDCALC_HAS_DB_LOOKUP(rc) && !rc->calculation && !rc->warning && !rc->critical) {
- error("Health configuration for alarm '%s.%s' is useless (no db lookup, no calculation, no warning and no critical expressions)", rc->chart?rc->chart:"NOCHART", rc->name);
- return 0;
- }
-
- if (rrdcalc_exists(host, rc->chart, rc->name, rc->hash_chart, rc->hash))
- return 0;
-
- rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id);
-
- debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f",
- rc->chart?rc->chart:"NOCHART",
- rc->name,
- rc->id,
- (rc->exec)?rc->exec:"DEFAULT",
- (rc->recipient)?rc->recipient:"DEFAULT",
- rc->green,
- rc->red,
- rc->group,
- rc->after,
- rc->before,
- rc->options,
- (rc->dimensions)?rc->dimensions:"NONE",
- rc->update_every,
- (rc->calculation)?rc->calculation->parsed_as:"NONE",
- (rc->warning)?rc->warning->parsed_as:"NONE",
- (rc->critical)?rc->critical->parsed_as:"NONE",
- rc->source,
- rc->delay_up_duration,
- rc->delay_down_duration,
- rc->delay_max_duration,
- rc->delay_multiplier
- );
-
- rrdcalc_create_part2(host, rc);
- return 1;
-}
-
-static inline int rrdcalctemplate_add_template_from_config(RRDHOST *host, RRDCALCTEMPLATE *rt) {
- if(unlikely(!rt->context)) {
- error("Health configuration for template '%s' does not have a context", rt->name);
- return 0;
- }
-
- if(unlikely(!rt->update_every)) {
- error("Health configuration for template '%s' has no frequency (parameter 'every'). Ignoring it.", rt->name);
- return 0;
- }
-
- if(unlikely(!RRDCALCTEMPLATE_HAS_CALCULATION(rt) && !rt->warning && !rt->critical)) {
- error("Health configuration for template '%s' is useless (no calculation, no warning and no critical evaluation)", rt->name);
- return 0;
- }
-
- RRDCALCTEMPLATE *t, *last = NULL;
- for (t = host->templates; t ; last = t, t = t->next) {
- if(unlikely(t->hash_name == rt->hash_name
- && !strcmp(t->name, rt->name)
- && !strcmp(t->family_match?t->family_match:"*", rt->family_match?rt->family_match:"*")
- )) {
- error("Health configuration template '%s' already exists for host '%s'.", rt->name, host->hostname);
- return 0;
- }
- }
-
- debug(D_HEALTH, "Health configuration adding template '%s': context '%s', exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f",
- rt->name,
- (rt->context)?rt->context:"NONE",
- (rt->exec)?rt->exec:"DEFAULT",
- (rt->recipient)?rt->recipient:"DEFAULT",
- rt->green,
- rt->red,
- rt->group,
- rt->after,
- rt->before,
- rt->options,
- (rt->dimensions)?rt->dimensions:"NONE",
- rt->update_every,
- (rt->calculation)?rt->calculation->parsed_as:"NONE",
- (rt->warning)?rt->warning->parsed_as:"NONE",
- (rt->critical)?rt->critical->parsed_as:"NONE",
- rt->source,
- rt->delay_up_duration,
- rt->delay_down_duration,
- rt->delay_max_duration,
- rt->delay_multiplier
- );
-
- if(likely(last)) {
- last->next = rt;
- }
- else {
- rt->next = host->templates;
- host->templates = rt;
- }
-
- return 1;
-}
-
-static inline int health_parse_duration(char *string, int *result) {
- // make sure it is a number
- if(!*string || !(isdigit(*string) || *string == '+' || *string == '-')) {
- *result = 0;
- return 0;
- }
-
- char *e = NULL;
- calculated_number n = str2ld(string, &e);
- if(e && *e) {
- switch (*e) {
- case 'Y':
- *result = (int) (n * 86400 * 365);
- break;
- case 'M':
- *result = (int) (n * 86400 * 30);
- break;
- case 'w':
- *result = (int) (n * 86400 * 7);
- break;
- case 'd':
- *result = (int) (n * 86400);
- break;
- case 'h':
- *result = (int) (n * 3600);
- break;
- case 'm':
- *result = (int) (n * 60);
- break;
-
- default:
- case 's':
- *result = (int) (n);
- break;
- }
- }
- else
- *result = (int)(n);
-
- return 1;
-}
-
-static inline int health_parse_delay(
- size_t line, const char *path, const char *file, char *string,
- int *delay_up_duration,
- int *delay_down_duration,
- int *delay_max_duration,
- float *delay_multiplier) {
-
- char given_up = 0;
- char given_down = 0;
- char given_max = 0;
- char given_multiplier = 0;
-
- char *s = string;
- while(*s) {
- char *key = s;
-
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
-
- if(!*key) break;
-
- char *value = s;
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
-
- if(!strcasecmp(key, "up")) {
- if (!health_parse_duration(value, delay_up_duration)) {
- error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
- line, path, file, value, key);
- }
- else given_up = 1;
- }
- else if(!strcasecmp(key, "down")) {
- if (!health_parse_duration(value, delay_down_duration)) {
- error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
- line, path, file, value, key);
- }
- else given_down = 1;
- }
- else if(!strcasecmp(key, "multiplier")) {
- *delay_multiplier = strtof(value, NULL);
- if(isnan(*delay_multiplier) || isinf(*delay_multiplier) || islessequal(*delay_multiplier, 0)) {
- error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
- line, path, file, value, key);
- }
- else given_multiplier = 1;
- }
- else if(!strcasecmp(key, "max")) {
- if (!health_parse_duration(value, delay_max_duration)) {
- error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword",
- line, path, file, value, key);
- }
- else given_max = 1;
- }
- else {
- error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'",
- line, path, file, key);
- }
- }
-
- if(!given_up)
- *delay_up_duration = 0;
-
- if(!given_down)
- *delay_down_duration = 0;
-
- if(!given_multiplier)
- *delay_multiplier = 1.0;
-
- if(!given_max) {
- if((*delay_max_duration) < (*delay_up_duration) * (*delay_multiplier))
- *delay_max_duration = (int)((*delay_up_duration) * (*delay_multiplier));
-
- if((*delay_max_duration) < (*delay_down_duration) * (*delay_multiplier))
- *delay_max_duration = (int)((*delay_down_duration) * (*delay_multiplier));
- }
-
- return 1;
-}
-
-static inline uint32_t health_parse_options(const char *s) {
- uint32_t options = 0;
- char buf[100+1] = "";
-
- while(*s) {
- buf[0] = '\0';
-
- // skip spaces
- while(*s && isspace(*s))
- s++;
-
- // find the next space
- size_t count = 0;
- while(*s && count < 100 && !isspace(*s))
- buf[count++] = *s++;
-
- if(buf[0]) {
- buf[count] = '\0';
-
- if(!strcasecmp(buf, "no-clear-notification") || !strcasecmp(buf, "no-clear"))
- options |= RRDCALC_FLAG_NO_CLEAR_NOTIFICATION;
- else
- error("Ignoring unknown alarm option '%s'", buf);
- }
- }
-
- return options;
-}
-
-static inline int health_parse_db_lookup(
- size_t line, const char *path, const char *file, char *string,
- int *group_method, int *after, int *before, int *every,
- uint32_t *options, char **dimensions
-) {
- debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s/%s: %s", line, path, file, string);
-
- if(*dimensions) freez(*dimensions);
- *dimensions = NULL;
- *after = 0;
- *before = 0;
- *every = 0;
- *options = 0;
-
- char *s = string, *key;
-
- // first is the group method
- key = s;
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
- if(!*s) {
- error("Health configuration invalid chart calculation at line %zu of file '%s/%s': expected group method followed by the 'after' time, but got '%s'",
- line, path, file, key);
- return 0;
- }
-
- if((*group_method = web_client_api_request_v1_data_group(key, -1)) == -1) {
- error("Health configuration at line %zu of file '%s/%s': invalid group method '%s'",
- line, path, file, key);
- return 0;
- }
-
- // then is the 'after' time
- key = s;
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
-
- if(!health_parse_duration(key, after)) {
- error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' after group method",
- line, path, file, key);
- return 0;
- }
-
- // sane defaults
- *every = abs(*after);
-
- // now we may have optional parameters
- while(*s) {
- key = s;
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
- if(!*key) break;
-
- if(!strcasecmp(key, "at")) {
- char *value = s;
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
-
- if (!health_parse_duration(value, before)) {
- error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword",
- line, path, file, value, key);
- }
- }
- else if(!strcasecmp(key, HEALTH_EVERY_KEY)) {
- char *value = s;
- while(*s && !isspace(*s)) s++;
- while(*s && isspace(*s)) *s++ = '\0';
-
- if (!health_parse_duration(value, every)) {
- error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword",
- line, path, file, value, key);
- }
- }
- else if(!strcasecmp(key, "absolute") || !strcasecmp(key, "abs") || !strcasecmp(key, "absolute_sum")) {
- *options |= RRDR_OPTION_ABSOLUTE;
- }
- else if(!strcasecmp(key, "min2max")) {
- *options |= RRDR_OPTION_MIN2MAX;
- }
- else if(!strcasecmp(key, "null2zero")) {
- *options |= RRDR_OPTION_NULL2ZERO;
- }
- else if(!strcasecmp(key, "percentage")) {
- *options |= RRDR_OPTION_PERCENTAGE;
- }
- else if(!strcasecmp(key, "unaligned")) {
- *options |= RRDR_OPTION_NOT_ALIGNED;
- }
- else if(!strcasecmp(key, "match-ids") || !strcasecmp(key, "match_ids")) {
- *options |= RRDR_OPTION_MATCH_IDS;
- }
- else if(!strcasecmp(key, "match-names") || !strcasecmp(key, "match_names")) {
- *options |= RRDR_OPTION_MATCH_NAMES;
- }
- else if(!strcasecmp(key, "of")) {
- if(*s && strcasecmp(s, "all") != 0)
- *dimensions = strdupz(s);
- break;
- }
- else {
- error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'",
- line, path, file, key);
- }
- }
-
- return 1;
-}
-
-static inline char *health_source_file(size_t line, const char *path, const char *filename) {
- char buffer[FILENAME_MAX + 1];
- snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename);
- return strdupz(buffer);
-}
-
-static inline void strip_quotes(char *s) {
- while(*s) {
- if(*s == '\'' || *s == '"') *s = ' ';
- s++;
- }
-}
-
-int health_readfile(RRDHOST *host, const char *path, const char *filename) {
- debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename);
-
- static uint32_t
- hash_alarm = 0,
- hash_template = 0,
- hash_os = 0,
- hash_on = 0,
- hash_host = 0,
- hash_families = 0,
- hash_calc = 0,
- hash_green = 0,
- hash_red = 0,
- hash_warn = 0,
- hash_crit = 0,
- hash_exec = 0,
- hash_every = 0,
- hash_lookup = 0,
- hash_units = 0,
- hash_info = 0,
- hash_recipient = 0,
- hash_delay = 0,
- hash_options = 0;
-
- char buffer[HEALTH_CONF_MAX_LINE + 1];
-
- if(unlikely(!hash_alarm)) {
- hash_alarm = simple_uhash(HEALTH_ALARM_KEY);
- hash_template = simple_uhash(HEALTH_TEMPLATE_KEY);
- hash_on = simple_uhash(HEALTH_ON_KEY);
- hash_os = simple_uhash(HEALTH_OS_KEY);
- hash_host = simple_uhash(HEALTH_HOST_KEY);
- hash_families = simple_uhash(HEALTH_FAMILIES_KEY);
- hash_calc = simple_uhash(HEALTH_CALC_KEY);
- hash_lookup = simple_uhash(HEALTH_LOOKUP_KEY);
- hash_green = simple_uhash(HEALTH_GREEN_KEY);
- hash_red = simple_uhash(HEALTH_RED_KEY);
- hash_warn = simple_uhash(HEALTH_WARN_KEY);
- hash_crit = simple_uhash(HEALTH_CRIT_KEY);
- hash_exec = simple_uhash(HEALTH_EXEC_KEY);
- hash_every = simple_uhash(HEALTH_EVERY_KEY);
- hash_units = simple_hash(HEALTH_UNITS_KEY);
- hash_info = simple_hash(HEALTH_INFO_KEY);
- hash_recipient = simple_hash(HEALTH_RECIPIENT_KEY);
- hash_delay = simple_uhash(HEALTH_DELAY_KEY);
- hash_options = simple_uhash(HEALTH_OPTIONS_KEY);
- }
-
- snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename);
- FILE *fp = fopen(buffer, "r");
- if(!fp) {
- error("Health configuration cannot read file '%s'.", buffer);
- return 0;
- }
-
- RRDCALC *rc = NULL;
- RRDCALCTEMPLATE *rt = NULL;
-
- int ignore_this = 0;
- size_t line = 0, append = 0;
- char *s;
- while((s = fgets(&buffer[append], (int)(HEALTH_CONF_MAX_LINE - append), fp)) || append) {
- int stop_appending = !s;
- line++;
- s = trim(buffer);
- if(!s || *s == '#') continue;
-
- append = strlen(s);
- if(!stop_appending && s[append - 1] == '\\') {
- s[append - 1] = ' ';
- append = &s[append] - buffer;
- if(append < HEALTH_CONF_MAX_LINE)
- continue;
- else {
- error("Health configuration has too long muli-line at line %zu of file '%s/%s'.", line, path, filename);
- }
- }
- append = 0;
-
- char *key = s;
- while(*s && *s != ':') s++;
- if(!*s) {
- error("Health configuration has invalid line %zu of file '%s/%s'. It does not contain a ':'. Ignoring it.", line, path, filename);
- continue;
- }
- *s = '\0';
- s++;
-
- char *value = s;
- key = trim_all(key);
- value = trim_all(value);
-
- if(!key) {
- error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename);
- continue;
- }
-
- if(!value) {
- error("Health configuration has invalid line %zu of file '%s/%s'. value is empty. Ignoring it.", line, path, filename);
- continue;
- }
-
- uint32_t hash = simple_uhash(key);
-
- if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) {
- if (rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc)))
- rrdcalc_free(rc);
-
- if(rt) {
- if (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt))
- rrdcalctemplate_free(rt);
-
- rt = NULL;
- }
-
- rc = callocz(1, sizeof(RRDCALC));
- rc->next_event_id = 1;
- rc->name = strdupz(value);
- rc->hash = simple_hash(rc->name);
- rc->source = health_source_file(line, path, filename);
- rc->green = NAN;
- rc->red = NAN;
- rc->value = NAN;
- rc->old_value = NAN;
- rc->delay_multiplier = 1.0;
-
- if(rrdvar_fix_name(rc->name))
- error("Health configuration renamed alarm '%s' to '%s'", value, rc->name);
-
- ignore_this = 0;
- }
- else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) {
- if(rc) {
- if(ignore_this || !rrdcalc_add_alarm_from_config(host, rc))
- rrdcalc_free(rc);
-
- rc = NULL;
- }
-
- if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)))
- rrdcalctemplate_free(rt);
-
- rt = callocz(1, sizeof(RRDCALCTEMPLATE));
- rt->name = strdupz(value);
- rt->hash_name = simple_hash(rt->name);
- rt->source = health_source_file(line, path, filename);
- rt->green = NAN;
- rt->red = NAN;
- rt->delay_multiplier = 1.0;
-
- if(rrdvar_fix_name(rt->name))
- error("Health configuration renamed template '%s' to '%s'", value, rt->name);
-
- ignore_this = 0;
- }
- else if(hash == hash_os && !strcasecmp(key, HEALTH_OS_KEY)) {
- char *os_match = value;
- SIMPLE_PATTERN *os_pattern = simple_pattern_create(os_match, NULL, SIMPLE_PATTERN_EXACT);
-
- if(!simple_pattern_matches(os_pattern, host->os)) {
- if(rc)
- debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rc->name, line, path, filename, os_match);
-
- if(rt)
- debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rt->name, line, path, filename, os_match);
-
- ignore_this = 1;
- }
-
- simple_pattern_free(os_pattern);
- }
- else if(hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) {
- char *host_match = value;
- SIMPLE_PATTERN *host_pattern = simple_pattern_create(host_match, NULL, SIMPLE_PATTERN_EXACT);
-
- if(!simple_pattern_matches(host_pattern, host->hostname)) {
- if(rc)
- debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rc->name, line, path, filename, host_match);
-
- if(rt)
- debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rt->name, line, path, filename, host_match);
-
- ignore_this = 1;
- }
-
- simple_pattern_free(host_pattern);
- }
- else if(rc) {
- if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) {
- if(rc->chart) {
- if(strcmp(rc->chart, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rc->name, key, rc->chart, value, value);
-
- freez(rc->chart);
- }
- rc->chart = strdupz(value);
- rc->hash_chart = simple_hash(rc->chart);
- }
- else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) {
- health_parse_db_lookup(line, path, filename, value, &rc->group, &rc->after, &rc->before,
- &rc->update_every,
- &rc->options, &rc->dimensions);
- }
- else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) {
- if(!health_parse_duration(value, &rc->update_every))
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.",
- line, path, filename, rc->name, key, value);
- }
- else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) {
- char *e;
- rc->green = str2ld(value, &e);
- if(e && *e) {
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.",
- line, path, filename, rc->name, key, e);
- }
- }
- else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) {
- char *e;
- rc->red = str2ld(value, &e);
- if(e && *e) {
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.",
- line, path, filename, rc->name, key, e);
- }
- }
- else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) {
- const char *failed_at = NULL;
- int error = 0;
- rc->calculation = expression_parse(value, &failed_at, &error);
- if(!rc->calculation) {
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
- line, path, filename, rc->name, key, value, expression_strerror(error), failed_at);
- }
- }
- else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) {
- const char *failed_at = NULL;
- int error = 0;
- rc->warning = expression_parse(value, &failed_at, &error);
- if(!rc->warning) {
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
- line, path, filename, rc->name, key, value, expression_strerror(error), failed_at);
- }
- }
- else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) {
- const char *failed_at = NULL;
- int error = 0;
- rc->critical = expression_parse(value, &failed_at, &error);
- if(!rc->critical) {
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
- line, path, filename, rc->name, key, value, expression_strerror(error), failed_at);
- }
- }
- else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) {
- if(rc->exec) {
- if(strcmp(rc->exec, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rc->name, key, rc->exec, value, value);
-
- freez(rc->exec);
- }
- rc->exec = strdupz(value);
- }
- else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) {
- if(rc->recipient) {
- if(strcmp(rc->recipient, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rc->name, key, rc->recipient, value, value);
-
- freez(rc->recipient);
- }
- rc->recipient = strdupz(value);
- }
- else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
- if(rc->units) {
- if(strcmp(rc->units, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rc->name, key, rc->units, value, value);
-
- freez(rc->units);
- }
- rc->units = strdupz(value);
- strip_quotes(rc->units);
- }
- else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
- if(rc->info) {
- if(strcmp(rc->info, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rc->name, key, rc->info, value, value);
-
- freez(rc->info);
- }
- rc->info = strdupz(value);
- strip_quotes(rc->info);
- }
- else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) {
- health_parse_delay(line, path, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier);
- }
- else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) {
- rc->options |= health_parse_options(value);
- }
- else {
- error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.",
- line, path, filename, rc->name, key);
- }
- }
- else if(rt) {
- if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) {
- if(rt->context) {
- if(strcmp(rt->context, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rt->name, key, rt->context, value, value);
-
- freez(rt->context);
- }
- rt->context = strdupz(value);
- rt->hash_context = simple_hash(rt->context);
- }
- else if(hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) {
- freez(rt->family_match);
- simple_pattern_free(rt->family_pattern);
-
- rt->family_match = strdupz(value);
- rt->family_pattern = simple_pattern_create(rt->family_match, NULL, SIMPLE_PATTERN_EXACT);
- }
- else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) {
- health_parse_db_lookup(line, path, filename, value, &rt->group, &rt->after, &rt->before,
- &rt->update_every, &rt->options, &rt->dimensions);
- }
- else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) {
- if(!health_parse_duration(value, &rt->update_every))
- error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' cannot parse duration: '%s'.",
- line, path, filename, rt->name, key, value);
- }
- else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) {
- char *e;
- rt->green = str2ld(value, &e);
- if(e && *e) {
- error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.",
- line, path, filename, rt->name, key, e);
- }
- }
- else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) {
- char *e;
- rt->red = str2ld(value, &e);
- if(e && *e) {
- error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.",
- line, path, filename, rt->name, key, e);
- }
- }
- else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) {
- const char *failed_at = NULL;
- int error = 0;
- rt->calculation = expression_parse(value, &failed_at, &error);
- if(!rt->calculation) {
- error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
- line, path, filename, rt->name, key, value, expression_strerror(error), failed_at);
- }
- }
- else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) {
- const char *failed_at = NULL;
- int error = 0;
- rt->warning = expression_parse(value, &failed_at, &error);
- if(!rt->warning) {
- error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
- line, path, filename, rt->name, key, value, expression_strerror(error), failed_at);
- }
- }
- else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) {
- const char *failed_at = NULL;
- int error = 0;
- rt->critical = expression_parse(value, &failed_at, &error);
- if(!rt->critical) {
- error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
- line, path, filename, rt->name, key, value, expression_strerror(error), failed_at);
- }
- }
- else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) {
- if(rt->exec) {
- if(strcmp(rt->exec, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rt->name, key, rt->exec, value, value);
-
- freez(rt->exec);
- }
- rt->exec = strdupz(value);
- }
- else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) {
- if(rt->recipient) {
- if(strcmp(rt->recipient, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rt->name, key, rt->recipient, value, value);
-
- freez(rt->recipient);
- }
- rt->recipient = strdupz(value);
- }
- else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) {
- if(rt->units) {
- if(strcmp(rt->units, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rt->name, key, rt->units, value, value);
-
- freez(rt->units);
- }
- rt->units = strdupz(value);
- strip_quotes(rt->units);
- }
- else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) {
- if(rt->info) {
- if(strcmp(rt->info, value) != 0)
- error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rt->name, key, rt->info, value, value);
-
- freez(rt->info);
- }
- rt->info = strdupz(value);
- strip_quotes(rt->info);
- }
- else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) {
- health_parse_delay(line, path, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier);
- }
- else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) {
- rt->options |= health_parse_options(value);
- }
- else {
- error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.",
- line, path, filename, rt->name, key);
- }
- }
- else {
- error("Health configuration at line %zu of file '%s/%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.",
- line, path, filename, key);
- }
- }
-
- if(rc && (ignore_this || !rrdcalc_add_alarm_from_config(host, rc)))
- rrdcalc_free(rc);
-
- if(rt && (ignore_this || !rrdcalctemplate_add_template_from_config(host, rt)))
- rrdcalctemplate_free(rt);
-
- fclose(fp);
- return 1;
-}
-
-void health_readdir(RRDHOST *host, const char *path) {
- if(!host->health_enabled) return;
-
- size_t pathlen = strlen(path);
-
- debug(D_HEALTH, "Health configuration reading directory '%s'", path);
-
- DIR *dir = opendir(path);
- if (!dir) {
- error("Health configuration cannot open directory '%s'.", path);
- return;
- }
-
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- size_t len = strlen(de->d_name);
-
- if(de->d_type == DT_DIR
- && (
- (de->d_name[0] == '.' && de->d_name[1] == '\0')
- || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- )) {
- debug(D_HEALTH, "Ignoring directory '%s'", de->d_name);
- continue;
- }
-
- else if(de->d_type == DT_DIR) {
- char *s = mallocz(pathlen + strlen(de->d_name) + 2);
- strcpy(s, path);
- strcat(s, "/");
- strcat(s, de->d_name);
- health_readdir(host, s);
- freez(s);
- continue;
- }
-
- else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) &&
- len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
- health_readfile(host, path, de->d_name);
- }
-
- else debug(D_HEALTH, "Ignoring file '%s'", de->d_name);
- }
-
- closedir(dir);
-}
-
-
diff --git a/src/health_json.c b/src/health_json.c
deleted file mode 100644
index aba7425d7..000000000
--- a/src/health_json.c
+++ /dev/null
@@ -1,260 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) {
- if(value && *value) {
- buffer_sprintf(wb, "%s\"%s\":\"", prefix, label);
- buffer_strcat_htmlescape(wb, value);
- buffer_strcat(wb, "\"");
- buffer_strcat(wb, suffix);
- }
- else
- buffer_sprintf(wb, "%s\"%s\":null%s", prefix, label, suffix);
-}
-
-static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host) {
- buffer_sprintf(wb,
- "\n\t{\n"
- "\t\t\"hostname\": \"%s\",\n"
- "\t\t\"unique_id\": %u,\n"
- "\t\t\"alarm_id\": %u,\n"
- "\t\t\"alarm_event_id\": %u,\n"
- "\t\t\"name\": \"%s\",\n"
- "\t\t\"chart\": \"%s\",\n"
- "\t\t\"family\": \"%s\",\n"
- "\t\t\"processed\": %s,\n"
- "\t\t\"updated\": %s,\n"
- "\t\t\"exec_run\": %lu,\n"
- "\t\t\"exec_failed\": %s,\n"
- "\t\t\"exec\": \"%s\",\n"
- "\t\t\"recipient\": \"%s\",\n"
- "\t\t\"exec_code\": %d,\n"
- "\t\t\"source\": \"%s\",\n"
- "\t\t\"units\": \"%s\",\n"
- "\t\t\"when\": %lu,\n"
- "\t\t\"duration\": %lu,\n"
- "\t\t\"non_clear_duration\": %lu,\n"
- "\t\t\"status\": \"%s\",\n"
- "\t\t\"old_status\": \"%s\",\n"
- "\t\t\"delay\": %d,\n"
- "\t\t\"delay_up_to_timestamp\": %lu,\n"
- "\t\t\"updated_by_id\": %u,\n"
- "\t\t\"updates_id\": %u,\n"
- "\t\t\"value_string\": \"%s\",\n"
- "\t\t\"old_value_string\": \"%s\",\n"
- , host->hostname
- , ae->unique_id
- , ae->alarm_id
- , ae->alarm_event_id
- , ae->name
- , ae->chart
- , ae->family
- , (ae->flags & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false"
- , (ae->flags & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false"
- , (unsigned long)ae->exec_run_timestamp
- , (ae->flags & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false"
- , ae->exec?ae->exec:host->health_default_exec
- , ae->recipient?ae->recipient:host->health_default_recipient
- , ae->exec_code
- , ae->source
- , ae->units?ae->units:""
- , (unsigned long)ae->when
- , (unsigned long)ae->duration
- , (unsigned long)ae->non_clear_duration
- , rrdcalc_status2string(ae->new_status)
- , rrdcalc_status2string(ae->old_status)
- , ae->delay
- , (unsigned long)ae->delay_up_to_timestamp
- , ae->updated_by_id
- , ae->updates_id
- , ae->new_value_string
- , ae->old_value_string
- );
-
- health_string2json(wb, "\t\t", "info", ae->info?ae->info:"", ",\n");
-
- if(unlikely(ae->flags & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
- buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n");
- }
-
- buffer_strcat(wb, "\t\t\"value\":");
- buffer_rrd_value(wb, ae->new_value);
- buffer_strcat(wb, ",\n");
-
- buffer_strcat(wb, "\t\t\"old_value\":");
- buffer_rrd_value(wb, ae->old_value);
- buffer_strcat(wb, "\n");
-
- buffer_strcat(wb, "\t}");
-}
-
-void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after) {
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
-
- buffer_strcat(wb, "[");
-
- unsigned int max = host->health_log.max;
- unsigned int count = 0;
- ALARM_ENTRY *ae;
- for(ae = host->health_log.alarms; ae && count < max ; count++, ae = ae->next) {
- if(ae->unique_id > after) {
- if(likely(count)) buffer_strcat(wb, ",");
- health_alarm_entry2json_nolock(wb, ae, host);
- }
- }
-
- buffer_strcat(wb, "\n]\n");
-
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-}
-
-static inline void health_rrdcalc2json_nolock(RRDHOST *host, BUFFER *wb, RRDCALC *rc) {
- char value_string[100 + 1];
- format_value_and_unit(value_string, 100, rc->value, rc->units, -1);
-
- buffer_sprintf(wb,
- "\t\t\"%s.%s\": {\n"
- "\t\t\t\"id\": %lu,\n"
- "\t\t\t\"name\": \"%s\",\n"
- "\t\t\t\"chart\": \"%s\",\n"
- "\t\t\t\"family\": \"%s\",\n"
- "\t\t\t\"active\": %s,\n"
- "\t\t\t\"exec\": \"%s\",\n"
- "\t\t\t\"recipient\": \"%s\",\n"
- "\t\t\t\"source\": \"%s\",\n"
- "\t\t\t\"units\": \"%s\",\n"
- "\t\t\t\"info\": \"%s\",\n"
- "\t\t\t\"status\": \"%s\",\n"
- "\t\t\t\"last_status_change\": %lu,\n"
- "\t\t\t\"last_updated\": %lu,\n"
- "\t\t\t\"next_update\": %lu,\n"
- "\t\t\t\"update_every\": %d,\n"
- "\t\t\t\"delay_up_duration\": %d,\n"
- "\t\t\t\"delay_down_duration\": %d,\n"
- "\t\t\t\"delay_max_duration\": %d,\n"
- "\t\t\t\"delay_multiplier\": %f,\n"
- "\t\t\t\"delay\": %d,\n"
- "\t\t\t\"delay_up_to_timestamp\": %lu,\n"
- "\t\t\t\"value_string\": \"%s\",\n"
- , rc->chart, rc->name
- , (unsigned long)rc->id
- , rc->name
- , rc->chart
- , (rc->rrdset && rc->rrdset->family)?rc->rrdset->family:""
- , (rc->rrdset)?"true":"false"
- , rc->exec?rc->exec:host->health_default_exec
- , rc->recipient?rc->recipient:host->health_default_recipient
- , rc->source
- , rc->units?rc->units:""
- , rc->info?rc->info:""
- , rrdcalc_status2string(rc->status)
- , (unsigned long)rc->last_status_change
- , (unsigned long)rc->last_updated
- , (unsigned long)rc->next_update
- , rc->update_every
- , rc->delay_up_duration
- , rc->delay_down_duration
- , rc->delay_max_duration
- , rc->delay_multiplier
- , rc->delay_last
- , (unsigned long)rc->delay_up_to_timestamp
- , value_string
- );
-
- if(unlikely(rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION)) {
- buffer_strcat(wb, "\t\t\t\"no_clear_notification\": true,\n");
- }
-
- if(RRDCALC_HAS_DB_LOOKUP(rc)) {
- if(rc->dimensions && *rc->dimensions)
- health_string2json(wb, "\t\t\t", "lookup_dimensions", rc->dimensions, ",\n");
-
- buffer_sprintf(wb,
- "\t\t\t\"db_after\": %lu,\n"
- "\t\t\t\"db_before\": %lu,\n"
- "\t\t\t\"lookup_method\": \"%s\",\n"
- "\t\t\t\"lookup_after\": %d,\n"
- "\t\t\t\"lookup_before\": %d,\n"
- "\t\t\t\"lookup_options\": \"",
- (unsigned long) rc->db_after,
- (unsigned long) rc->db_before,
- group_method2string(rc->group),
- rc->after,
- rc->before
- );
- buffer_data_options2string(wb, rc->options);
- buffer_strcat(wb, "\",\n");
- }
-
- if(rc->calculation) {
- health_string2json(wb, "\t\t\t", "calc", rc->calculation->source, ",\n");
- health_string2json(wb, "\t\t\t", "calc_parsed", rc->calculation->parsed_as, ",\n");
- }
-
- if(rc->warning) {
- health_string2json(wb, "\t\t\t", "warn", rc->warning->source, ",\n");
- health_string2json(wb, "\t\t\t", "warn_parsed", rc->warning->parsed_as, ",\n");
- }
-
- if(rc->critical) {
- health_string2json(wb, "\t\t\t", "crit", rc->critical->source, ",\n");
- health_string2json(wb, "\t\t\t", "crit_parsed", rc->critical->parsed_as, ",\n");
- }
-
- buffer_strcat(wb, "\t\t\t\"green\":");
- buffer_rrd_value(wb, rc->green);
- buffer_strcat(wb, ",\n");
-
- buffer_strcat(wb, "\t\t\t\"red\":");
- buffer_rrd_value(wb, rc->red);
- buffer_strcat(wb, ",\n");
-
- buffer_strcat(wb, "\t\t\t\"value\":");
- buffer_rrd_value(wb, rc->value);
- buffer_strcat(wb, "\n");
-
- buffer_strcat(wb, "\t\t}");
-}
-
-//void health_rrdcalctemplate2json_nolock(BUFFER *wb, RRDCALCTEMPLATE *rt) {
-//
-//}
-
-void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) {
- int i;
-
- rrdhost_rdlock(host);
- buffer_sprintf(wb, "{\n\t\"hostname\": \"%s\","
- "\n\t\"latest_alarm_log_unique_id\": %u,"
- "\n\t\"status\": %s,"
- "\n\t\"now\": %lu,"
- "\n\t\"alarms\": {\n",
- host->hostname,
- (host->health_log.next_log_id > 0)?(host->health_log.next_log_id - 1):0,
- host->health_enabled?"true":"false",
- (unsigned long)now_realtime_sec());
-
- RRDCALC *rc;
- for(i = 0, rc = host->alarms; rc ; rc = rc->next) {
- if(unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
- continue;
-
- if(likely(!all && !(rc->status == RRDCALC_STATUS_WARNING || rc->status == RRDCALC_STATUS_CRITICAL)))
- continue;
-
- if(likely(i)) buffer_strcat(wb, ",\n");
- health_rrdcalc2json_nolock(host, wb, rc);
- i++;
- }
-
-// buffer_strcat(wb, "\n\t},\n\t\"templates\": {");
-// RRDCALCTEMPLATE *rt;
-// for(rt = host->templates; rt ; rt = rt->next)
-// health_rrdcalctemplate2json_nolock(wb, rt);
-
- buffer_strcat(wb, "\n\t}\n}\n");
- rrdhost_unlock(host);
-}
-
-
-
diff --git a/src/health_log.c b/src/health_log.c
deleted file mode 100644
index a44fbadb0..000000000
--- a/src/health_log.c
+++ /dev/null
@@ -1,463 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// health alarm log load/save
-// no need for locking - only one thread is reading / writing the alarms log
-
-inline int health_alarm_log_open(RRDHOST *host) {
- if(host->health_log_fp)
- fclose(host->health_log_fp);
-
- host->health_log_fp = fopen(host->health_log_filename, "a");
-
- if(host->health_log_fp) {
- if (setvbuf(host->health_log_fp, NULL, _IOLBF, 0) != 0)
- error("HEALTH [%s]: cannot set line buffering on health log file '%s'.", host->hostname, host->health_log_filename);
- return 0;
- }
-
- error("HEALTH [%s]: cannot open health log file '%s'. Health data will be lost in case of netdata or server crash.", host->hostname, host->health_log_filename);
- return -1;
-}
-
-inline void health_alarm_log_close(RRDHOST *host) {
- if(host->health_log_fp) {
- fclose(host->health_log_fp);
- host->health_log_fp = NULL;
- }
-}
-
-inline void health_log_rotate(RRDHOST *host) {
- static size_t rotate_every = 0;
-
- if(unlikely(rotate_every == 0)) {
- rotate_every = (size_t)config_get_number(CONFIG_SECTION_HEALTH, "rotate log every lines", 2000);
- if(rotate_every < 100) rotate_every = 100;
- }
-
- if(unlikely(host->health_log_entries_written > rotate_every)) {
- health_alarm_log_close(host);
-
- char old_filename[FILENAME_MAX + 1];
- snprintfz(old_filename, FILENAME_MAX, "%s.old", host->health_log_filename);
-
- if(unlink(old_filename) == -1 && errno != ENOENT)
- error("HEALTH [%s]: cannot remove old alarms log file '%s'", host->hostname, old_filename);
-
- if(link(host->health_log_filename, old_filename) == -1 && errno != ENOENT)
- error("HEALTH [%s]: cannot move file '%s' to '%s'.", host->hostname, host->health_log_filename, old_filename);
-
- if(unlink(host->health_log_filename) == -1 && errno != ENOENT)
- error("HEALTH [%s]: cannot remove old alarms log file '%s'", host->hostname, host->health_log_filename);
-
- // open it with truncate
- host->health_log_fp = fopen(host->health_log_filename, "w");
-
- if(host->health_log_fp)
- fclose(host->health_log_fp);
- else
- error("HEALTH [%s]: cannot truncate health log '%s'", host->hostname, host->health_log_filename);
-
- host->health_log_fp = NULL;
-
- host->health_log_entries_written = 0;
- health_alarm_log_open(host);
- }
-}
-
-inline void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae) {
- health_log_rotate(host);
-
- if(likely(host->health_log_fp)) {
- if(unlikely(fprintf(host->health_log_fp
- , "%c\t%s"
- "\t%08x\t%08x\t%08x\t%08x\t%08x"
- "\t%08x\t%08x\t%08x"
- "\t%08x\t%08x\t%08x"
- "\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s"
- "\t%d\t%d\t%d\t%d"
- "\t" CALCULATED_NUMBER_FORMAT_AUTO "\t" CALCULATED_NUMBER_FORMAT_AUTO
- "\n"
- , (ae->flags & HEALTH_ENTRY_FLAG_SAVED)?'U':'A'
- , host->hostname
-
- , ae->unique_id
- , ae->alarm_id
- , ae->alarm_event_id
- , ae->updated_by_id
- , ae->updates_id
-
- , (uint32_t)ae->when
- , (uint32_t)ae->duration
- , (uint32_t)ae->non_clear_duration
- , (uint32_t)ae->flags
- , (uint32_t)ae->exec_run_timestamp
- , (uint32_t)ae->delay_up_to_timestamp
-
- , (ae->name)?ae->name:""
- , (ae->chart)?ae->chart:""
- , (ae->family)?ae->family:""
- , (ae->exec)?ae->exec:""
- , (ae->recipient)?ae->recipient:""
- , (ae->source)?ae->source:""
- , (ae->units)?ae->units:""
- , (ae->info)?ae->info:""
-
- , ae->exec_code
- , ae->new_status
- , ae->old_status
- , ae->delay
-
- , ae->new_value
- , ae->old_value
- ) < 0))
- error("HEALTH [%s]: failed to save alarm log entry to '%s'. Health data may be lost in case of abnormal restart.", host->hostname, host->health_log_filename);
- else {
- ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
- host->health_log_entries_written++;
- }
- }
-}
-
-inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename) {
- errno = 0;
-
- char *s, *buf = mallocz(65536 + 1);
- size_t line = 0, len = 0;
- ssize_t loaded = 0, updated = 0, errored = 0, duplicate = 0;
-
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
-
- while((s = fgets_trim_len(buf, 65536, fp, &len))) {
- host->health_log_entries_written++;
- line++;
-
- int max_entries = 30, entries = 0;
- char *pointers[max_entries];
-
- pointers[entries++] = s++;
- while(*s) {
- if(unlikely(*s == '\t')) {
- *s = '\0';
- pointers[entries++] = ++s;
- if(entries >= max_entries) {
- error("HEALTH [%s]: line %zu of file '%s' has more than %d entries. Ignoring excessive entries.", host->hostname, line, filename, max_entries);
- break;
- }
- }
- else s++;
- }
-
- if(likely(*pointers[0] == 'U' || *pointers[0] == 'A')) {
- ALARM_ENTRY *ae = NULL;
-
- if(entries < 26) {
- error("HEALTH [%s]: line %zu of file '%s' should have at least 26 entries, but it has %d. Ignoring it.", host->hostname, line, filename, entries);
- errored++;
- continue;
- }
-
- // check that we have valid ids
- uint32_t unique_id = (uint32_t)strtoul(pointers[2], NULL, 16);
- if(!unique_id) {
- error("HEALTH [%s]: line %zu of file '%s' states alarm entry with invalid unique id %u (%s). Ignoring it.", host->hostname, line, filename, unique_id, pointers[2]);
- errored++;
- continue;
- }
-
- uint32_t alarm_id = (uint32_t)strtoul(pointers[3], NULL, 16);
- if(!alarm_id) {
- error("HEALTH [%s]: line %zu of file '%s' states alarm entry for invalid alarm id %u (%s). Ignoring it.", host->hostname, line, filename, alarm_id, pointers[3]);
- errored++;
- continue;
- }
-
- if(unlikely(*pointers[0] == 'A')) {
- // make sure it is properly numbered
- if(unlikely(host->health_log.alarms && unique_id < host->health_log.alarms->unique_id)) {
- error("HEALTH [%s]: line %zu of file '%s' has alarm log entry %u in wrong order. Ignoring it.", host->hostname, line, filename, unique_id);
- errored++;
- continue;
- }
-
- ae = callocz(1, sizeof(ALARM_ENTRY));
- }
- else if(unlikely(*pointers[0] == 'U')) {
- // find the original
- for(ae = host->health_log.alarms; ae; ae = ae->next) {
- if(unlikely(unique_id == ae->unique_id)) {
- if(unlikely(*pointers[0] == 'A')) {
- error("HEALTH [%s]: line %zu of file '%s' adds duplicate alarm log entry %u. Using the later."
- , host->hostname, line, filename, unique_id);
- *pointers[0] = 'U';
- duplicate++;
- }
- break;
- }
- else if(unlikely(unique_id > ae->unique_id)) {
- // no need to continue
- // the linked list is sorted
- ae = NULL;
- break;
- }
- }
- }
-
- // if not found, skip this line
- if(unlikely(!ae)) {
- // error("HEALTH [%s]: line %zu of file '%s' updates alarm log entry with unique id %u, but it is not found.", host->hostname, line, filename, unique_id);
- continue;
- }
-
- // check for a possible host missmatch
- //if(strcmp(pointers[1], host->hostname))
- // error("HEALTH [%s]: line %zu of file '%s' provides an alarm for host '%s' but this is named '%s'.", host->hostname, line, filename, pointers[1], host->hostname);
-
- ae->unique_id = unique_id;
- ae->alarm_id = alarm_id;
- ae->alarm_event_id = (uint32_t)strtoul(pointers[4], NULL, 16);
- ae->updated_by_id = (uint32_t)strtoul(pointers[5], NULL, 16);
- ae->updates_id = (uint32_t)strtoul(pointers[6], NULL, 16);
-
- ae->when = (uint32_t)strtoul(pointers[7], NULL, 16);
- ae->duration = (uint32_t)strtoul(pointers[8], NULL, 16);
- ae->non_clear_duration = (uint32_t)strtoul(pointers[9], NULL, 16);
-
- ae->flags = (uint32_t)strtoul(pointers[10], NULL, 16);
- ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
-
- ae->exec_run_timestamp = (uint32_t)strtoul(pointers[11], NULL, 16);
- ae->delay_up_to_timestamp = (uint32_t)strtoul(pointers[12], NULL, 16);
-
- freez(ae->name);
- ae->name = strdupz(pointers[13]);
- ae->hash_name = simple_hash(ae->name);
-
- freez(ae->chart);
- ae->chart = strdupz(pointers[14]);
- ae->hash_chart = simple_hash(ae->chart);
-
- freez(ae->family);
- ae->family = strdupz(pointers[15]);
-
- freez(ae->exec);
- ae->exec = strdupz(pointers[16]);
- if(!*ae->exec) { freez(ae->exec); ae->exec = NULL; }
-
- freez(ae->recipient);
- ae->recipient = strdupz(pointers[17]);
- if(!*ae->recipient) { freez(ae->recipient); ae->recipient = NULL; }
-
- freez(ae->source);
- ae->source = strdupz(pointers[18]);
- if(!*ae->source) { freez(ae->source); ae->source = NULL; }
-
- freez(ae->units);
- ae->units = strdupz(pointers[19]);
- if(!*ae->units) { freez(ae->units); ae->units = NULL; }
-
- freez(ae->info);
- ae->info = strdupz(pointers[20]);
- if(!*ae->info) { freez(ae->info); ae->info = NULL; }
-
- ae->exec_code = str2i(pointers[21]);
- ae->new_status = str2i(pointers[22]);
- ae->old_status = str2i(pointers[23]);
- ae->delay = str2i(pointers[24]);
-
- ae->new_value = str2l(pointers[25]);
- ae->old_value = str2l(pointers[26]);
-
- char value_string[100 + 1];
- freez(ae->old_value_string);
- freez(ae->new_value_string);
- ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1));
- ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1));
-
- // add it to host if not already there
- if(unlikely(*pointers[0] == 'A')) {
- ae->next = host->health_log.alarms;
- host->health_log.alarms = ae;
- loaded++;
- }
- else updated++;
-
- if(unlikely(ae->unique_id > host->health_max_unique_id))
- host->health_max_unique_id = ae->unique_id;
-
- if(unlikely(ae->alarm_id >= host->health_max_alarm_id))
- host->health_max_alarm_id = ae->alarm_id;
- }
- else {
- error("HEALTH [%s]: line %zu of file '%s' is invalid (unrecognized entry type '%s').", host->hostname, line, filename, pointers[0]);
- errored++;
- }
- }
-
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-
- freez(buf);
-
- if(!host->health_max_unique_id) host->health_max_unique_id = (uint32_t)now_realtime_sec();
- if(!host->health_max_alarm_id) host->health_max_alarm_id = (uint32_t)now_realtime_sec();
-
- host->health_log.next_log_id = host->health_max_unique_id + 1;
- host->health_log.next_alarm_id = host->health_max_alarm_id + 1;
-
- debug(D_HEALTH, "HEALTH [%s]: loaded file '%s' with %zd new alarm entries, updated %zd alarms, errors %zd entries, duplicate %zd", host->hostname, filename, loaded, updated, errored, duplicate);
- return loaded;
-}
-
-inline void health_alarm_log_load(RRDHOST *host) {
- health_alarm_log_close(host);
-
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s.old", host->health_log_filename);
- FILE *fp = fopen(filename, "r");
- if(!fp)
- error("HEALTH [%s]: cannot open health file: %s", host->hostname, filename);
- else {
- health_alarm_log_read(host, fp, filename);
- fclose(fp);
- }
-
- host->health_log_entries_written = 0;
- fp = fopen(host->health_log_filename, "r");
- if(!fp)
- error("HEALTH [%s]: cannot open health file: %s", host->hostname, host->health_log_filename);
- else {
- health_alarm_log_read(host, fp, host->health_log_filename);
- fclose(fp);
- }
-
- health_alarm_log_open(host);
-}
-
-
-// ----------------------------------------------------------------------------
-// health alarm log management
-
-inline void health_alarm_log(
- RRDHOST *host,
- uint32_t alarm_id,
- uint32_t alarm_event_id,
- time_t when,
- const char *name,
- const char *chart,
- const char *family,
- const char *exec,
- const char *recipient,
- time_t duration,
- calculated_number old_value,
- calculated_number new_value,
- RRDCALC_STATUS old_status,
- RRDCALC_STATUS new_status,
- const char *source,
- const char *units,
- const char *info,
- int delay,
- uint32_t flags
-) {
- debug(D_HEALTH, "Health adding alarm log entry with id: %u", host->health_log.next_log_id);
-
- ALARM_ENTRY *ae = callocz(1, sizeof(ALARM_ENTRY));
- ae->name = strdupz(name);
- ae->hash_name = simple_hash(ae->name);
-
- if(chart) {
- ae->chart = strdupz(chart);
- ae->hash_chart = simple_hash(ae->chart);
- }
-
- if(family)
- ae->family = strdupz(family);
-
- if(exec) ae->exec = strdupz(exec);
- if(recipient) ae->recipient = strdupz(recipient);
- if(source) ae->source = strdupz(source);
- if(units) ae->units = strdupz(units);
- if(info) ae->info = strdupz(info);
-
- ae->unique_id = host->health_log.next_log_id++;
- ae->alarm_id = alarm_id;
- ae->alarm_event_id = alarm_event_id;
- ae->when = when;
- ae->old_value = old_value;
- ae->new_value = new_value;
-
- char value_string[100 + 1];
- ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1));
- ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1));
-
- ae->old_status = old_status;
- ae->new_status = new_status;
- ae->duration = duration;
- ae->delay = delay;
- ae->delay_up_to_timestamp = when + delay;
-
- ae->flags |= flags;
-
- if(ae->old_status == RRDCALC_STATUS_WARNING || ae->old_status == RRDCALC_STATUS_CRITICAL)
- ae->non_clear_duration += ae->duration;
-
- // link it
- netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
- ae->next = host->health_log.alarms;
- host->health_log.alarms = ae;
- host->health_log.count++;
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-
- // match previous alarms
- 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) {
- if(!(t->flags & HEALTH_ENTRY_FLAG_UPDATED) && !t->updated_by_id) {
- t->flags |= HEALTH_ENTRY_FLAG_UPDATED;
- t->updated_by_id = ae->unique_id;
- ae->updates_id = t->unique_id;
-
- if((t->new_status == RRDCALC_STATUS_WARNING || t->new_status == RRDCALC_STATUS_CRITICAL) &&
- (t->old_status == RRDCALC_STATUS_WARNING || t->old_status == RRDCALC_STATUS_CRITICAL))
- ae->non_clear_duration += t->non_clear_duration;
-
- health_alarm_log_save(host, t);
- }
-
- // no need to continue
- break;
- }
- }
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-
- health_alarm_log_save(host, ae);
-}
-
-inline void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae) {
- freez(ae->name);
- freez(ae->chart);
- freez(ae->family);
- freez(ae->exec);
- freez(ae->recipient);
- freez(ae->source);
- freez(ae->units);
- freez(ae->info);
- freez(ae->old_value_string);
- freez(ae->new_value_string);
- freez(ae);
-}
-
-inline void health_alarm_log_free(RRDHOST *host) {
- rrdhost_check_wrlock(host);
-
- netdata_rwlock_wrlock(&host->health_log.alarm_log_rwlock);
-
- ALARM_ENTRY *ae;
- while((ae = host->health_log.alarms)) {
- host->health_log.alarms = ae->next;
- health_alarm_log_free_one_nochecks_nounlink(ae);
- }
-
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
-}
diff --git a/src/inlined.h b/src/inlined.h
deleted file mode 100644
index 9ab2dca73..000000000
--- a/src/inlined.h
+++ /dev/null
@@ -1,291 +0,0 @@
-#ifndef NETDATA_INLINED_H
-#define NETDATA_INLINED_H
-
-#include "common.h"
-
-#ifdef KERNEL_32BIT
-typedef uint32_t kernel_uint_t;
-#define str2kernel_uint_t(string) str2uint32_t(string)
-#define KERNEL_UINT_FORMAT "%u"
-#else
-typedef uint64_t kernel_uint_t;
-#define str2kernel_uint_t(string) str2uint64_t(string)
-#define KERNEL_UINT_FORMAT "%" PRIu64
-#endif
-
-#define str2pid_t(string) str2uint32_t(string)
-
-
-// for faster execution, allow the compiler to inline
-// these functions that are called thousands of times per second
-
-static inline uint32_t simple_hash(const char *name) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5;
- while (*s) {
- hval *= 16777619;
- hval ^= (uint32_t) *s++;
- }
- return hval;
-}
-
-static inline uint32_t simple_uhash(const char *name) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5, c;
- while ((c = *s++)) {
- if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
- hval *= 16777619;
- hval ^= c;
- }
- return hval;
-}
-
-static inline int simple_hash_strcmp(const char *name, const char *b, uint32_t *hash) {
- unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5;
- int ret = 0;
- while (*s) {
- if(!ret) ret = *s - *b++;
- hval *= 16777619;
- hval ^= (uint32_t) *s++;
- }
- *hash = hval;
- return ret;
-}
-
-static inline int str2i(const char *s) {
- int n = 0;
- char c, negative = (*s == '-');
-
- for(c = (negative)?*(++s):*s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
-
- if(unlikely(negative))
- return -n;
-
- return n;
-}
-
-static inline long str2l(const char *s) {
- long n = 0;
- char c, negative = (*s == '-');
-
- for(c = (negative)?*(++s):*s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
-
- if(unlikely(negative))
- return -n;
-
- return n;
-}
-
-static inline uint32_t str2uint32_t(const char *s) {
- uint32_t n = 0;
- char c;
- for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
- return n;
-}
-
-static inline uint64_t str2uint64_t(const char *s) {
- uint64_t n = 0;
- char c;
- for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
- return n;
-}
-
-static inline unsigned long str2ul(const char *s) {
- unsigned long n = 0;
- char c;
- for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
- return n;
-}
-
-static inline unsigned long long str2ull(const char *s) {
- unsigned long long n = 0;
- char c;
- for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
- return n;
-}
-
-static inline long long str2ll(const char *s, char **endptr) {
- int negative = 0;
-
- if(unlikely(*s == '-')) {
- s++;
- negative = 1;
- }
- else if(unlikely(*s == '+'))
- s++;
-
- long long n = 0;
- char c;
- for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
-
- if(unlikely(endptr))
- *endptr = (char *)s;
-
- if(unlikely(negative))
- return -n;
- else
- return n;
-}
-
-static inline long double str2ld(const char *s, char **endptr) {
- int negative = 0;
- const char *start = s;
- unsigned long long integer_part = 0;
- unsigned long decimal_part = 0;
- size_t decimal_digits = 0;
-
- switch(*s) {
- case '-':
- s++;
- negative = 1;
- break;
-
- case '+':
- s++;
- break;
-
- case 'n':
- if(s[1] == 'a' && s[2] == 'n') {
- if(endptr) *endptr = (char *)&s[3];
- return NAN;
- }
- break;
-
- case 'i':
- if(s[1] == 'n' && s[2] == 'f') {
- if(endptr) *endptr = (char *)&s[3];
- return INFINITY;
- }
- break;
-
- default:
- break;
- }
-
- while (*s >= '0' && *s <= '9') {
- integer_part = (integer_part * 10) + (*s - '0');
- s++;
- }
-
- if(unlikely(*s == '.')) {
- decimal_part = 0;
- s++;
-
- while (*s >= '0' && *s <= '9') {
- decimal_part = (decimal_part * 10) + (*s - '0');
- s++;
- decimal_digits++;
- }
- }
-
- if(unlikely(*s == 'e' || *s == 'E'))
- return strtold(start, endptr);
-
- if(unlikely(endptr))
- *endptr = (char *)s;
-
- if(unlikely(negative)) {
- if(unlikely(decimal_digits))
- return -((long double)integer_part + (long double)decimal_part / powl(10.0, decimal_digits));
- else
- return -((long double)integer_part);
- }
- else {
- if(unlikely(decimal_digits))
- return (long double)integer_part + (long double)decimal_part / powl(10.0, decimal_digits);
- else
- return (long double)integer_part;
- }
-}
-
-#ifdef NETDATA_STRCMP_OVERRIDE
-#ifdef strcmp
-#undef strcmp
-#endif
-#define strcmp(a, b) strsame(a, b)
-#endif // NETDATA_STRCMP_OVERRIDE
-
-static inline int strsame(const char *a, const char *b) {
- if(unlikely(a == b)) return 0;
- while(*a && *a == *b) { a++; b++; }
- return *a - *b;
-}
-
-static inline char *strncpyz(char *dst, const char *src, size_t n) {
- char *p = dst;
-
- while (*src && n--)
- *dst++ = *src++;
-
- *dst = '\0';
-
- return p;
-}
-
-static inline int read_file(const char *filename, char *buffer, size_t size) {
- int fd = open(filename, O_RDONLY, 0666);
- if(unlikely(fd == -1))
- return 1;
-
- ssize_t r = read(fd, buffer, size);
- if(unlikely(r == -1)) {
- close(fd);
- return 2;
- }
- buffer[r] = '\0';
-
- close(fd);
- return 0;
-}
-
-static inline int read_single_number_file(const char *filename, unsigned long long *result) {
- char buffer[30 + 1];
-
- int ret = read_file(filename, buffer, 30);
- if(unlikely(ret)) {
- *result = 0;
- return ret;
- }
-
- buffer[30] = '\0';
- *result = str2ull(buffer);
- return 0;
-}
-
-static inline int read_single_signed_number_file(const char *filename, long long *result) {
- char buffer[30 + 1];
-
- int ret = read_file(filename, buffer, 30);
- if(unlikely(ret)) {
- *result = 0;
- return ret;
- }
-
- buffer[30] = '\0';
- *result = atoll(buffer);
- return 0;
-}
-
-#endif //NETDATA_INLINED_H
diff --git a/src/ipc.c b/src/ipc.c
deleted file mode 100644
index a9076fca4..000000000
--- a/src/ipc.c
+++ /dev/null
@@ -1,261 +0,0 @@
-#include "common.h"
-
-#include <sys/sem.h>
-#include <sys/msg.h>
-#include <sys/shm.h>
-
-
-#ifndef SEMVMX
-#define SEMVMX 32767 /* <= 32767 semaphore maximum value */
-#endif
-
-/* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */
-#ifndef IPC_INFO
-#define IPC_INFO 3
-#endif
-
-struct ipc_limits {
- uint64_t shmmni; /* max number of segments */
- uint64_t shmmax; /* max segment size */
- uint64_t shmall; /* max total shared memory */
- uint64_t shmmin; /* min segment size */
-
- int semmni; /* max number of arrays */
- int semmsl; /* max semaphores per array */
- int semmns; /* max semaphores system wide */
- int semopm; /* max ops per semop call */
- unsigned int semvmx; /* semaphore max value (constant) */
-
- int msgmni; /* max queues system wide */
- size_t msgmax; /* max size of message */
- int msgmnb; /* default max size of queue */
-};
-
-struct ipc_status {
- int semusz; /* current number of arrays */
- int semaem; /* current semaphores system wide */
-};
-
-/*
- * The last arg of semctl is a union semun, but where is it defined? X/OPEN
- * tells us to define it ourselves, but until recently Linux include files
- * would also define it.
- */
-#ifndef HAVE_UNION_SEMUN
-/* according to X/OPEN we have to define it ourselves */
-union semun {
- int val;
- struct semid_ds *buf;
- unsigned short int *array;
- struct seminfo *__buf;
-};
-#endif
-
-static inline int ipc_sem_get_limits(struct ipc_limits *lim) {
- static procfile *ff = NULL;
- static int error_shown = 0;
- static char filename[FILENAME_MAX + 1] = "";
-
- if(unlikely(!filename[0]))
- snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/sem", netdata_configured_host_prefix);
-
- if(unlikely(!ff)) {
- ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- if(unlikely(!error_shown)) {
- error("IPC: Cannot open file '%s'.", filename);
- error_shown = 1;
- }
- goto ipc;
- }
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) {
- if(unlikely(!error_shown)) {
- error("IPC: Cannot read file '%s'.", filename);
- error_shown = 1;
- }
- goto ipc;
- }
-
- if(procfile_lines(ff) >= 1 && procfile_linewords(ff, 0) >= 4) {
- lim->semvmx = SEMVMX;
- lim->semmsl = str2i(procfile_lineword(ff, 0, 0));
- lim->semmns = str2i(procfile_lineword(ff, 0, 1));
- lim->semopm = str2i(procfile_lineword(ff, 0, 2));
- lim->semmni = str2i(procfile_lineword(ff, 0, 3));
- return 0;
- }
- else {
- if(unlikely(!error_shown)) {
- error("IPC: Invalid content in file '%s'.", filename);
- error_shown = 1;
- }
- goto ipc;
- }
-
-ipc:
- // cannot do it from the file
- // query IPC
- {
- struct seminfo seminfo = {.semmni = 0};
- union semun arg = {.array = (ushort *) &seminfo};
-
- if(unlikely(semctl(0, 0, IPC_INFO, arg) < 0)) {
- error("IPC: Failed to read '%s' and request IPC_INFO with semctl().", filename);
- goto error;
- }
-
- lim->semvmx = SEMVMX;
- lim->semmni = seminfo.semmni;
- lim->semmsl = seminfo.semmsl;
- lim->semmns = seminfo.semmns;
- lim->semopm = seminfo.semopm;
- return 0;
- }
-
-error:
- lim->semvmx = 0;
- lim->semmni = 0;
- lim->semmsl = 0;
- lim->semmns = 0;
- lim->semopm = 0;
- return -1;
-}
-
-/*
-printf ("------ Semaphore Limits --------\n");
-printf ("max number of arrays = %d\n", limits.semmni);
-printf ("max semaphores per array = %d\n", limits.semmsl);
-printf ("max semaphores system wide = %d\n", limits.semmns);
-printf ("max ops per semop call = %d\n", limits.semopm);
-printf ("semaphore max value = %u\n", limits.semvmx);
-
-printf ("------ Semaphore Status --------\n");
-printf ("used arrays = %d\n", status.semusz);
-printf ("allocated semaphores = %d\n", status.semaem);
-*/
-
-static inline int ipc_sem_get_status(struct ipc_status *st) {
- struct seminfo seminfo;
- union semun arg;
-
- arg.array = (ushort *) (void *) &seminfo;
-
- if(unlikely(semctl (0, 0, SEM_INFO, arg) < 0)) {
- /* kernel not configured for semaphores */
- static int error_shown = 0;
- if(unlikely(!error_shown)) {
- error("IPC: kernel is not configured for semaphores");
- error_shown = 1;
- }
- st->semusz = 0;
- st->semaem = 0;
- return -1;
- }
-
- st->semusz = seminfo.semusz;
- st->semaem = seminfo.semaem;
- return 0;
-}
-
-int do_ipc(int update_every, usec_t dt) {
- (void)dt;
-
- static int initialized = 0, read_limits_next = -1;
- static struct ipc_limits limits;
- static struct ipc_status status;
- static RRDSETVAR *arrays_max = NULL, *semaphores_max = NULL;
- static RRDSET *st_semaphores = NULL, *st_arrays = NULL;
- static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL;
-
- if(unlikely(!initialized)) {
- initialized = 1;
-
- // make sure it works
- if(ipc_sem_get_limits(&limits) == -1) {
- error("unable to fetch semaphore limits");
- return 1;
- }
-
- // make sure it works
- if(ipc_sem_get_status(&status) == -1) {
- error("unable to fetch semaphore statistics");
- return 1;
- }
-
- // create the charts
- if(unlikely(!st_semaphores)) {
- st_semaphores = rrdset_create_localhost(
- "system"
- , "ipc_semaphores"
- , NULL
- , "ipc semaphores"
- , NULL
- , "IPC Semaphores"
- , "semaphores"
- , "linux"
- , "ipc"
- , 1000
- , localhost->rrd_update_every
- , RRDSET_TYPE_AREA
- );
- rd_semaphores = rrddim_add(st_semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
-
- if(unlikely(!st_arrays)) {
- st_arrays = rrdset_create_localhost(
- "system"
- , "ipc_semaphore_arrays"
- , NULL
- , "ipc semaphores"
- , NULL
- , "IPC Semaphore Arrays"
- , "arrays"
- , "linux"
- , "ipc"
- , 1000
- , localhost->rrd_update_every
- , RRDSET_TYPE_AREA
- );
- rd_arrays = rrddim_add(st_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
-
- // variables
- semaphores_max = rrdsetvar_custom_chart_variable_create(st_semaphores, "ipc.semaphores.max");
- arrays_max = rrdsetvar_custom_chart_variable_create(st_arrays, "ipc.semaphores.arrays.max");
- }
-
- if(unlikely(read_limits_next < 0)) {
- if(unlikely(ipc_sem_get_limits(&limits) == -1)) {
- error("Unable to fetch semaphore limits.");
- }
- else {
- if(semaphores_max) rrdsetvar_custom_chart_variable_set(semaphores_max, limits.semmns);
- if(arrays_max) rrdsetvar_custom_chart_variable_set(arrays_max, limits.semmni);
-
- st_arrays->red = limits.semmni;
- st_semaphores->red = limits.semmns;
-
- read_limits_next = 60 / update_every;
- }
- }
- else
- read_limits_next--;
-
- if(unlikely(ipc_sem_get_status(&status) == -1)) {
- error("Unable to get semaphore statistics");
- return 0;
- }
-
- if(st_semaphores->counter_done) rrdset_next(st_semaphores);
- rrddim_set_by_pointer(st_semaphores, rd_semaphores, status.semaem);
- rrdset_done(st_semaphores);
-
- if(st_arrays->counter_done) rrdset_next(st_arrays);
- rrddim_set_by_pointer(st_arrays, rd_arrays, status.semusz);
- rrdset_done(st_arrays);
-
- return 0;
-}
diff --git a/src/ipc.h b/src/ipc.h
deleted file mode 100644
index 04f9df5cd..000000000
--- a/src/ipc.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef NETDATA_PLUGIN_IPC_H
-#define NETDATA_PLUGIN_IPC_H 1
-
-extern int do_ipc(int update_every, usec_t dt);
-
-#endif /* NETDATA_PLUGIN_IPC_H */
-
diff --git a/src/locks.c b/src/locks.c
deleted file mode 100644
index c5b42c921..000000000
--- a/src/locks.c
+++ /dev/null
@@ -1,319 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// automatic thread cancelability management, based on locks
-
-static __thread int netdata_thread_first_cancelability = 0;
-static __thread int netdata_thread_lock_cancelability = 0;
-
-inline void netdata_thread_disable_cancelability(void) {
- int old;
- int ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
- if(ret != 0)
- error("THREAD_CANCELABILITY: pthread_setcancelstate() on thread %s returned error %d", netdata_thread_tag(), ret);
- else {
- if(!netdata_thread_lock_cancelability)
- netdata_thread_first_cancelability = old;
-
- netdata_thread_lock_cancelability++;
- }
-}
-
-inline void netdata_thread_enable_cancelability(void) {
- if(netdata_thread_lock_cancelability < 1) {
- error("THREAD_CANCELABILITY: netdata_thread_enable_cancelability(): invalid thread cancelability count %d on thread %s - results will be undefined - please report this!", netdata_thread_lock_cancelability, netdata_thread_tag());
- }
- else if(netdata_thread_lock_cancelability == 1) {
- int old = 1;
- int ret = pthread_setcancelstate(netdata_thread_first_cancelability, &old);
- if(ret != 0)
- error("THREAD_CANCELABILITY: pthread_setcancelstate() on thread %s returned error %d", netdata_thread_tag(), ret);
- else {
- if(old != PTHREAD_CANCEL_DISABLE)
- error("THREAD_CANCELABILITY: netdata_thread_enable_cancelability(): old thread cancelability on thread %s was changed, expected DISABLED (%d), found %s (%d) - please report this!", netdata_thread_tag(), PTHREAD_CANCEL_DISABLE, (old == PTHREAD_CANCEL_ENABLE)?"ENABLED":"UNKNOWN", old);
- }
-
- netdata_thread_lock_cancelability = 0;
- }
- else
- netdata_thread_lock_cancelability--;
-}
-
-// ----------------------------------------------------------------------------
-// mutex
-
-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;
-}
-
-int __netdata_mutex_lock(netdata_mutex_t *mutex) {
- netdata_thread_disable_cancelability();
-
- int ret = pthread_mutex_lock(mutex);
- if(unlikely(ret != 0)) {
- netdata_thread_enable_cancelability();
- error("MUTEX_LOCK: failed to get lock (code %d)", ret);
- }
- return ret;
-}
-
-int __netdata_mutex_trylock(netdata_mutex_t *mutex) {
- netdata_thread_disable_cancelability();
-
- int ret = pthread_mutex_trylock(mutex);
- if(ret != 0)
- netdata_thread_enable_cancelability();
-
- return ret;
-}
-
-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);
- else
- netdata_thread_enable_cancelability();
-
- return ret;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-
-// ----------------------------------------------------------------------------
-// r/w lock
-
-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;
-}
-
-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;
-}
-
-int __netdata_rwlock_rdlock(netdata_rwlock_t *rwlock) {
- netdata_thread_disable_cancelability();
-
- int ret = pthread_rwlock_rdlock(rwlock);
- if(unlikely(ret != 0)) {
- netdata_thread_enable_cancelability();
- error("RW_LOCK: failed to obtain read lock (code %d)", ret);
- }
-
- return ret;
-}
-
-int __netdata_rwlock_wrlock(netdata_rwlock_t *rwlock) {
- netdata_thread_disable_cancelability();
-
- int ret = pthread_rwlock_wrlock(rwlock);
- if(unlikely(ret != 0)) {
- error("RW_LOCK: failed to obtain write lock (code %d)", ret);
- netdata_thread_enable_cancelability();
- }
-
- return ret;
-}
-
-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);
- else
- netdata_thread_enable_cancelability();
-
- return ret;
-}
-
-int __netdata_rwlock_tryrdlock(netdata_rwlock_t *rwlock) {
- netdata_thread_disable_cancelability();
-
- int ret = pthread_rwlock_tryrdlock(rwlock);
- if(ret != 0)
- netdata_thread_enable_cancelability();
-
- return ret;
-}
-
-int __netdata_rwlock_trywrlock(netdata_rwlock_t *rwlock) {
- netdata_thread_disable_cancelability();
-
- int ret = pthread_rwlock_trywrlock(rwlock);
- if(ret != 0)
- netdata_thread_enable_cancelability();
-
- return ret;
-}
-
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
diff --git a/src/locks.h b/src/locks.h
deleted file mode 100644
index 36962fef2..000000000
--- a/src/locks.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef NETDATA_LOCKS_H
-#define NETDATA_LOCKS_H
-
-typedef pthread_mutex_t netdata_mutex_t;
-#define NETDATA_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-
-typedef pthread_rwlock_t netdata_rwlock_t;
-#define NETDATA_RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
-
-extern int __netdata_mutex_init(netdata_mutex_t *mutex);
-extern int __netdata_mutex_lock(netdata_mutex_t *mutex);
-extern int __netdata_mutex_trylock(netdata_mutex_t *mutex);
-extern int __netdata_mutex_unlock(netdata_mutex_t *mutex);
-
-extern int __netdata_rwlock_destroy(netdata_rwlock_t *rwlock);
-extern int __netdata_rwlock_init(netdata_rwlock_t *rwlock);
-extern int __netdata_rwlock_rdlock(netdata_rwlock_t *rwlock);
-extern int __netdata_rwlock_wrlock(netdata_rwlock_t *rwlock);
-extern int __netdata_rwlock_unlock(netdata_rwlock_t *rwlock);
-extern int __netdata_rwlock_tryrdlock(netdata_rwlock_t *rwlock);
-extern int __netdata_rwlock_trywrlock(netdata_rwlock_t *rwlock);
-
-extern int netdata_mutex_init_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex);
-extern int netdata_mutex_lock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex);
-extern int netdata_mutex_trylock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex);
-extern int netdata_mutex_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex);
-
-extern int netdata_rwlock_destroy_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-extern int netdata_rwlock_init_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-extern int netdata_rwlock_rdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-extern int netdata_rwlock_wrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-extern int netdata_rwlock_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-extern int netdata_rwlock_tryrdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-extern int netdata_rwlock_trywrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock);
-
-extern void netdata_thread_disable_cancelability(void);
-extern void netdata_thread_enable_cancelability(void);
-
-#ifdef NETDATA_INTERNAL_CHECKS
-
-#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)
-
-#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_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)
-
-#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
diff --git a/src/log.c b/src/log.c
deleted file mode 100644
index edb4482a0..000000000
--- a/src/log.c
+++ /dev/null
@@ -1,427 +0,0 @@
-#include "common.h"
-
-int web_server_is_multithreaded = 1;
-
-const char *program_name = "";
-uint64_t debug_flags = DEBUG;
-
-int access_log_syslog = 1;
-int error_log_syslog = 1;
-int output_log_syslog = 1; // debug log
-
-int stdaccess_fd = -1;
-FILE *stdaccess = NULL;
-
-const char *stdaccess_filename = NULL;
-const char *stderr_filename = NULL;
-const char *stdout_filename = NULL;
-
-void syslog_init(void) {
- static int i = 0;
-
- if(!i) {
- openlog(program_name, LOG_PID, LOG_DAEMON);
- i = 1;
- }
-}
-
-#define LOG_DATE_LENGTH 26
-
-static inline void log_date(char *buffer, size_t len) {
- if(unlikely(!buffer || !len))
- return;
-
- time_t t;
- struct tm *tmp, tmbuf;
-
- t = now_realtime_sec();
- tmp = localtime_r(&t, &tmbuf);
-
- if (tmp == NULL) {
- buffer[0] = '\0';
- return;
- }
-
- if (unlikely(strftime(buffer, len, "%Y-%m-%d %H:%M:%S", tmp) == 0))
- buffer[0] = '\0';
-
- buffer[len - 1] = '\0';
-}
-
-static netdata_mutex_t log_mutex = NETDATA_MUTEX_INITIALIZER;
-static inline void log_lock() {
- netdata_mutex_lock(&log_mutex);
-}
-static inline void log_unlock() {
- netdata_mutex_unlock(&log_mutex);
-}
-
-int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) {
- int f, devnull = 0;
-
- if(!filename || !*filename || !strcmp(filename, "none") || !strcmp(filename, "/dev/null")) {
- filename = "/dev/null";
- devnull = 1;
- }
-
- if(!strcmp(filename, "syslog")) {
- filename = "/dev/null";
- devnull = 1;
- syslog_init();
- if(enabled_syslog) *enabled_syslog = 1;
- }
- else if(enabled_syslog) *enabled_syslog = 0;
-
- // don't do anything if the user is willing
- // to have the standard one
- if(!strcmp(filename, "system")) {
- if(fd != -1 && fp != &stdaccess)
- return fd;
-
- filename = "stderr";
- }
-
- if(!strcmp(filename, "stdout"))
- f = STDOUT_FILENO;
-
- else if(!strcmp(filename, "stderr"))
- f = STDERR_FILENO;
-
- else {
- f = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0664);
- if(f == -1) {
- error("Cannot open file '%s'. Leaving %d to its default.", filename, fd);
- return fd;
- }
- }
-
- if(devnull && fp == &stdaccess) {
- fd = -1;
- *fp = NULL;
- }
-
- // if there is a level-2 file pointer
- // flush it before switching the level-1 fds
- if(fp && *fp)
- fflush(*fp);
-
- if(fd != f && fd != -1) {
- // it automatically closes
- int t = dup2(f, fd);
- if (t == -1) {
- error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
- close(f);
- return fd;
- }
- // info("dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
- close(f);
- }
- else fd = f;
-
- if(fp && !*fp) {
- *fp = fdopen(fd, "a");
- if (!*fp)
- error("Cannot fdopen() fd %d ('%s')", fd, filename);
- else {
- if (setvbuf(*fp, NULL, _IOLBF, 0) != 0)
- error("Cannot set line buffering on fd %d ('%s')", fd, filename);
- }
- }
-
- return fd;
-}
-
-void reopen_all_log_files() {
- if(stdout_filename)
- open_log_file(STDOUT_FILENO, (FILE **)&stdout, stdout_filename, &output_log_syslog);
-
- if(stderr_filename)
- open_log_file(STDERR_FILENO, (FILE **)&stderr, stderr_filename, &error_log_syslog);
-
- if(stdaccess_filename)
- stdaccess_fd = open_log_file(stdaccess_fd, (FILE **)&stdaccess, stdaccess_filename, &access_log_syslog);
-}
-
-void open_all_log_files() {
- // disable stdin
- open_log_file(STDIN_FILENO, (FILE **)&stdin, "/dev/null", NULL);
-
- open_log_file(STDOUT_FILENO, (FILE **)&stdout, stdout_filename, &output_log_syslog);
- open_log_file(STDERR_FILENO, (FILE **)&stderr, stderr_filename, &error_log_syslog);
- stdaccess_fd = open_log_file(stdaccess_fd, (FILE **)&stdaccess, stdaccess_filename, &access_log_syslog);
-}
-
-// ----------------------------------------------------------------------------
-// error log throttling
-
-time_t error_log_throttle_period_backup = 0;
-time_t error_log_throttle_period = 1200;
-unsigned long error_log_errors_per_period = 200;
-
-int error_log_limit(int reset) {
- static time_t start = 0;
- static unsigned long counter = 0, prevented = 0;
-
- // do not throttle if the period is 0
- if(error_log_throttle_period == 0)
- return 0;
-
- // prevent all logs if the errors per period is 0
- if(error_log_errors_per_period == 0)
-#ifdef NETDATA_INTERNAL_CHECKS
- return 0;
-#else
- return 1;
-#endif
-
- time_t now = now_monotonic_sec();
- if(!start) start = now;
-
- if(reset) {
- if(prevented) {
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
- fprintf(stderr, "%s: %s Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n"
- , date
- , program_name
- , program_name
- , prevented
- , now - start
- );
- }
-
- start = now;
- counter = 0;
- prevented = 0;
- }
-
- // detect if we log too much
- counter++;
-
- if(now - start > error_log_throttle_period) {
- if(prevented) {
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
- fprintf(stderr, "%s: %s Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n"
- , date
- , program_name
- , program_name
- , prevented
- , error_log_throttle_period
- );
- }
-
- // restart the period accounting
- start = now;
- counter = 1;
- prevented = 0;
-
- // log this error
- return 0;
- }
-
- if(counter > error_log_errors_per_period) {
- if(!prevented) {
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
- fprintf(stderr, "%s: %s Too many logs (%lu logs in %ld seconds, threshold is set to %lu logs in %ld seconds). Preventing more logs from process '%s' for %ld seconds.\n"
- , date
- , program_name
- , counter
- , now - start
- , error_log_errors_per_period
- , error_log_throttle_period
- , program_name
- , start + error_log_throttle_period - now);
- }
-
- prevented++;
-
- // prevent logging this error
-#ifdef NETDATA_INTERNAL_CHECKS
- return 0;
-#else
- return 1;
-#endif
- }
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// debug log
-
-void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) {
- va_list args;
-
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
-
- va_start( args, fmt );
- printf("%s: %s DEBUG : %s : (%04lu@%-10.10s:%-15.15s): ", date, program_name, netdata_thread_tag(), line, file, function);
- vprintf(fmt, args);
- va_end( args );
- putchar('\n');
-
- if(output_log_syslog) {
- va_start( args, fmt );
- vsyslog(LOG_ERR, fmt, args );
- va_end( args );
- }
-
- fflush(stdout);
-}
-
-// ----------------------------------------------------------------------------
-// info log
-
-void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
-{
- va_list args;
-
- // prevent logging too much
- if(error_log_limit(0)) return;
-
- if(error_log_syslog) {
- va_start( args, fmt );
- vsyslog(LOG_INFO, fmt, args );
- va_end( args );
- }
-
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
-
- log_lock();
-
- va_start( args, fmt );
- if(debug_flags) fprintf(stderr, "%s: %s INFO : %s : (%04lu@%-10.10s:%-15.15s): ", date, program_name, netdata_thread_tag(), line, file, function);
- else fprintf(stderr, "%s: %s INFO : %s : ", date, program_name, netdata_thread_tag());
- vfprintf( stderr, fmt, args );
- va_end( args );
-
- fputc('\n', stderr);
-
- log_unlock();
-}
-
-// ----------------------------------------------------------------------------
-// error log
-
-#if defined(STRERROR_R_CHAR_P)
-// GLIBC version of strerror_r
-static const char *strerror_result(const char *a, const char *b) { (void)b; return a; }
-#elif defined(HAVE_STRERROR_R)
-// POSIX version of strerror_r
-static const char *strerror_result(int a, const char *b) { (void)a; return b; }
-#elif defined(HAVE_C__GENERIC)
-
-// what a trick!
-// http://stackoverflow.com/questions/479207/function-overloading-in-c
-static const char *strerror_result_int(int a, const char *b) { (void)a; return b; }
-static const char *strerror_result_string(const char *a, const char *b) { (void)b; return a; }
-
-#define strerror_result(a, b) _Generic((a), \
- int: strerror_result_int, \
- char *: strerror_result_string \
- )(a, b)
-
-#else
-#error "cannot detect the format of function strerror_r()"
-#endif
-
-void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... ) {
- // save a copy of errno - just in case this function generates a new error
- int __errno = errno;
-
- va_list args;
-
- // prevent logging too much
- if(error_log_limit(0)) return;
-
- if(error_log_syslog) {
- va_start( args, fmt );
- vsyslog(LOG_ERR, fmt, args );
- va_end( args );
- }
-
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
-
- log_lock();
-
- va_start( args, fmt );
- if(debug_flags) fprintf(stderr, "%s: %s %-5.5s : %s : (%04lu@%-10.10s:%-15.15s): ", date, program_name, prefix, netdata_thread_tag(), line, file, function);
- else fprintf(stderr, "%s: %s %-5.5s : %s : ", date, program_name, prefix, netdata_thread_tag());
- vfprintf( stderr, fmt, args );
- va_end( args );
-
- if(__errno) {
- char buf[1024];
- fprintf(stderr, " (errno %d, %s)\n", __errno, strerror_result(strerror_r(__errno, buf, 1023), buf));
- errno = 0;
- }
- else
- fputc('\n', stderr);
-
- log_unlock();
-}
-
-void fatal_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) {
- va_list args;
-
- if(error_log_syslog) {
- va_start( args, fmt );
- vsyslog(LOG_CRIT, fmt, args );
- va_end( args );
- }
-
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
-
- log_lock();
-
- va_start( args, fmt );
- if(debug_flags) fprintf(stderr, "%s: %s FATAL : %s : (%04lu@%-10.10s:%-15.15s): ", date, program_name, netdata_thread_tag(), line, file, function);
- else fprintf(stderr, "%s: %s FATAL : %s :", date, program_name, netdata_thread_tag());
- vfprintf( stderr, fmt, args );
- va_end( args );
-
- perror(" # ");
- fputc('\n', stderr);
-
- log_unlock();
-
- netdata_cleanup_and_exit(1);
-}
-
-// ----------------------------------------------------------------------------
-// access log
-
-void log_access( const char *fmt, ... ) {
- va_list args;
-
- if(access_log_syslog) {
- va_start( args, fmt );
- vsyslog(LOG_INFO, fmt, args );
- va_end( args );
- }
-
- if(stdaccess) {
- static netdata_mutex_t access_mutex = NETDATA_MUTEX_INITIALIZER;
-
- if(web_server_is_multithreaded)
- netdata_mutex_lock(&access_mutex);
-
- char date[LOG_DATE_LENGTH];
- log_date(date, LOG_DATE_LENGTH);
- fprintf(stdaccess, "%s: ", date);
-
- va_start( args, fmt );
- vfprintf( stdaccess, fmt, args );
- va_end( args );
- fputc('\n', stdaccess);
-
- if(web_server_is_multithreaded)
- netdata_mutex_unlock(&access_mutex);
- }
-}
diff --git a/src/log.h b/src/log.h
deleted file mode 100644
index 81c85481b..000000000
--- a/src/log.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef NETDATA_LOG_H
-#define NETDATA_LOG_H 1
-
-#define D_WEB_BUFFER 0x0000000000000001
-#define D_WEB_CLIENT 0x0000000000000002
-#define D_LISTENER 0x0000000000000004
-#define D_WEB_DATA 0x0000000000000008
-#define D_OPTIONS 0x0000000000000010
-#define D_PROCNETDEV_LOOP 0x0000000000000020
-#define D_RRD_STATS 0x0000000000000040
-#define D_WEB_CLIENT_ACCESS 0x0000000000000080
-#define D_TC_LOOP 0x0000000000000100
-#define D_DEFLATE 0x0000000000000200
-#define D_CONFIG 0x0000000000000400
-#define D_PLUGINSD 0x0000000000000800
-#define D_CHILDS 0x0000000000001000
-#define D_EXIT 0x0000000000002000
-#define D_CHECKS 0x0000000000004000
-#define D_NFACCT_LOOP 0x0000000000008000
-#define D_PROCFILE 0x0000000000010000
-#define D_RRD_CALLS 0x0000000000020000
-#define D_DICTIONARY 0x0000000000040000
-#define D_MEMORY 0x0000000000080000
-#define D_CGROUP 0x0000000000100000
-#define D_REGISTRY 0x0000000000200000
-#define D_VARIABLES 0x0000000000400000
-#define D_HEALTH 0x0000000000800000
-#define D_CONNECT_TO 0x0000000001000000
-#define D_RRDHOST 0x0000000002000000
-#define D_LOCKS 0x0000000004000000
-#define D_BACKEND 0x0000000008000000
-#define D_STATSD 0x0000000010000000
-#define D_POLLFD 0x0000000020000000
-#define D_STREAM 0x0000000040000000
-#define D_SYSTEM 0x8000000000000000
-
-//#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
-//#define DEBUG 0xffffffff
-#define DEBUG (0)
-
-extern int web_server_is_multithreaded;
-
-extern uint64_t debug_flags;
-
-extern const char *program_name;
-
-extern int stdaccess_fd;
-extern FILE *stdaccess;
-
-extern const char *stdaccess_filename;
-extern const char *stderr_filename;
-extern const char *stdout_filename;
-
-extern int access_log_syslog;
-extern int error_log_syslog;
-extern int output_log_syslog;
-
-extern time_t error_log_throttle_period, error_log_throttle_period_backup;
-extern unsigned long error_log_errors_per_period;
-extern int error_log_limit(int reset);
-
-extern void open_all_log_files();
-extern void reopen_all_log_files();
-
-static inline void debug_dummy(void) {}
-
-#define error_log_limit_reset() do { error_log_throttle_period = error_log_throttle_period_backup; error_log_limit(1); } while(0)
-#define error_log_limit_unlimited() do { error_log_throttle_period = 0; } while(0)
-
-#ifdef NETDATA_INTERNAL_CHECKS
-#define debug(type, args...) do { if(unlikely(debug_flags & type)) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0)
-#else
-#define debug(type, args...) debug_dummy()
-#endif
-
-#define info(args...) info_int(__FILE__, __FUNCTION__, __LINE__, ##args)
-#define infoerr(args...) error_int("INFO", __FILE__, __FUNCTION__, __LINE__, ##args)
-#define error(args...) error_int("ERROR", __FILE__, __FUNCTION__, __LINE__, ##args)
-#define fatal(args...) fatal_int(__FILE__, __FUNCTION__, __LINE__, ##args)
-
-extern void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) PRINTFLIKE(4, 5);
-extern void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) PRINTFLIKE(4, 5);
-extern void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... ) PRINTFLIKE(5, 6);
-extern void fatal_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) NORETURN PRINTFLIKE(4, 5);
-extern void log_access( const char *fmt, ... ) PRINTFLIKE(1, 2);
-
-#endif /* NETDATA_LOG_H */
diff --git a/src/macos_fw.c b/src/macos_fw.c
deleted file mode 100644
index 5e8ce0ee4..000000000
--- a/src/macos_fw.c
+++ /dev/null
@@ -1,684 +0,0 @@
-#include "common.h"
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOBlockStorageDriver.h>
-#include <IOKit/IOBSD.h>
-// NEEDED BY do_space, do_inodes
-#include <sys/mount.h>
-// NEEDED BY: struct ifaddrs, getifaddrs()
-#include <net/if.h>
-#include <ifaddrs.h>
-
-// NEEDED BY: do_bandwidth
-#define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
-
-#define MAXDRIVENAME 31
-
-#define KILO_FACTOR 1024
-#define MEGA_FACTOR 1048576 // 1024 * 1024
-#define GIGA_FACTOR 1073741824 // 1024 * 1024 * 1024
-
-int do_macos_iokit(int update_every, usec_t dt) {
- (void)dt;
-
- static int do_io = -1, do_space = -1, do_inodes = -1, do_bandwidth = -1;
-
- if (unlikely(do_io == -1)) {
- do_io = config_get_boolean("plugin:macos:iokit", "disk i/o", 1);
- do_space = config_get_boolean("plugin:macos:sysctl", "space usage for all disks", 1);
- do_inodes = config_get_boolean("plugin:macos:sysctl", "inodes usage for all disks", 1);
- do_bandwidth = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
- }
-
- RRDSET *st;
-
- mach_port_t master_port;
- io_registry_entry_t drive, drive_media;
- io_iterator_t drive_list;
- CFDictionaryRef properties, statistics;
- CFStringRef name;
- CFNumberRef number;
- kern_return_t status;
- collected_number total_disk_reads = 0;
- collected_number total_disk_writes = 0;
- struct diskstat {
- char name[MAXDRIVENAME];
- collected_number bytes_read;
- collected_number bytes_write;
- collected_number reads;
- collected_number writes;
- collected_number time_read;
- collected_number time_write;
- collected_number latency_read;
- collected_number latency_write;
- } diskstat;
- struct cur_diskstat {
- collected_number duration_read_ns;
- collected_number duration_write_ns;
- collected_number busy_time_ns;
- } cur_diskstat;
- struct prev_diskstat {
- collected_number bytes_read;
- collected_number bytes_write;
- collected_number operations_read;
- collected_number operations_write;
- collected_number duration_read_ns;
- collected_number duration_write_ns;
- collected_number busy_time_ns;
- } prev_diskstat;
-
- // NEEDED BY: do_space, do_inodes
- struct statfs *mntbuf;
- int mntsize, i;
- char mntonname[MNAMELEN + 1];
- char title[4096 + 1];
-
- // NEEDED BY: do_bandwidth
- struct ifaddrs *ifa, *ifap;
-
- /* Get ports and services for drive statistics. */
- if (unlikely(IOMasterPort(bootstrap_port, &master_port))) {
- error("MACOS: IOMasterPort() failed");
- do_io = 0;
- error("DISABLED: system.io");
- /* Get the list of all drive objects. */
- } else if (unlikely(IOServiceGetMatchingServices(master_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list))) {
- error("MACOS: IOServiceGetMatchingServices() failed");
- do_io = 0;
- error("DISABLED: system.io");
- } else {
- while ((drive = IOIteratorNext(drive_list)) != 0) {
- properties = 0;
- statistics = 0;
- number = 0;
- bzero(&diskstat, sizeof(diskstat));
-
- /* Get drive media object. */
- status = IORegistryEntryGetChildEntry(drive, kIOServicePlane, &drive_media);
- if (unlikely(status != KERN_SUCCESS)) {
- IOObjectRelease(drive);
- continue;
- }
-
- /* Get drive media properties. */
- if (likely(!IORegistryEntryCreateCFProperties(drive_media, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
- /* Get disk name. */
- if (likely(name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)))) {
- CFStringGetCString(name, diskstat.name, MAXDRIVENAME, kCFStringEncodingUTF8);
- }
- }
-
- /* Release. */
- CFRelease(properties);
- IOObjectRelease(drive_media);
-
- if(unlikely(!diskstat.name || !*diskstat.name)) {
- IOObjectRelease(drive);
- continue;
- }
-
- /* Obtain the properties for this drive object. */
- if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) {
- IOObjectRelease(drive);
- error("MACOS: IORegistryEntryCreateCFProperties() failed");
- do_io = 0;
- error("DISABLED: system.io");
- break;
- } else if (likely(properties)) {
- /* Obtain the statistics from the drive properties. */
- if (likely(statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)))) {
-
- // --------------------------------------------------------------------
-
- /* Get bytes read. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_read);
- total_disk_reads += diskstat.bytes_read;
- }
-
- /* Get bytes written. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_write);
- total_disk_writes += diskstat.bytes_write;
- }
-
- st = rrdset_find_bytype_localhost("disk", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.io"
- , "Disk I/O Bandwidth"
- , "kilobytes/s"
- , "macos"
- , "iokit"
- , 2000
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- prev_diskstat.bytes_read = rrddim_set(st, "reads", diskstat.bytes_read);
- prev_diskstat.bytes_write = rrddim_set(st, "writes", diskstat.bytes_write);
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- /* Get number of reads. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.reads);
- }
-
- /* Get number of writes. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.writes);
- }
-
- st = rrdset_find_bytype_localhost("disk_ops", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk_ops"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.ops"
- , "Disk Completed I/O Operations"
- , "operations/s"
- , "macos"
- , "iokit"
- , 2001
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- prev_diskstat.operations_read = rrddim_set(st, "reads", diskstat.reads);
- prev_diskstat.operations_write = rrddim_set(st, "writes", diskstat.writes);
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- /* Get reads time. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_read);
- }
-
- /* Get writes time. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_write);
- }
-
- st = rrdset_find_bytype_localhost("disk_util", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk_util"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.util"
- , "Disk Utilization Time"
- , "% of time working"
- , "macos"
- , "iokit"
- , 2004
- , update_every
- , RRDSET_TYPE_AREA
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "utilization", NULL, 1, 10000000, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- cur_diskstat.busy_time_ns = (diskstat.time_read + diskstat.time_write);
- prev_diskstat.busy_time_ns = rrddim_set(st, "utilization", cur_diskstat.busy_time_ns);
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- /* Get reads latency. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_read);
- }
-
- /* Get writes latency. */
- if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)))) {
- CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_write);
- }
-
- st = rrdset_find_bytype_localhost("disk_iotime", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk_iotime"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.iotime"
- , "Disk Total I/O Time"
- , "milliseconds/s"
- , "macos"
- , "iokit"
- , 2022
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- cur_diskstat.duration_read_ns = diskstat.time_read + diskstat.latency_read;
- cur_diskstat.duration_write_ns = diskstat.time_write + diskstat.latency_write;
- prev_diskstat.duration_read_ns = rrddim_set(st, "reads", cur_diskstat.duration_read_ns);
- prev_diskstat.duration_write_ns = rrddim_set(st, "writes", cur_diskstat.duration_write_ns);
- rrdset_done(st);
-
- // --------------------------------------------------------------------
- // calculate differential charts
- // only if this is not the first time we run
-
- if (likely(dt)) {
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("disk_await", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk_await"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.await"
- , "Average Completed I/O Operation Time"
- , "ms per operation"
- , "macos"
- , "iokit"
- , 2005
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
- (cur_diskstat.duration_read_ns - prev_diskstat.duration_read_ns) / (diskstat.reads - prev_diskstat.operations_read) : 0);
- rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
- (cur_diskstat.duration_write_ns - prev_diskstat.duration_write_ns) / (diskstat.writes - prev_diskstat.operations_write) : 0);
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("disk_avgsz", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk_avgsz"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.avgsz"
- , "Average Completed I/O Operation Bandwidth"
- , "kilobytes per operation"
- , "macos"
- , "iokit"
- , 2006
- , update_every
- , RRDSET_TYPE_AREA
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ?
- (diskstat.bytes_read - prev_diskstat.bytes_read) / (diskstat.reads - prev_diskstat.operations_read) : 0);
- rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ?
- (diskstat.bytes_write - prev_diskstat.bytes_write) / (diskstat.writes - prev_diskstat.operations_write) : 0);
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("disk_svctm", diskstat.name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "disk_svctm"
- , diskstat.name
- , NULL
- , diskstat.name
- , "disk.svctm"
- , "Average Service Time"
- , "ms per operation"
- , "macos"
- , "iokit"
- , 2007
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "svctm", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "svctm", ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) ?
- (cur_diskstat.busy_time_ns - prev_diskstat.busy_time_ns) / ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) : 0);
- rrdset_done(st);
- }
- }
-
- /* Release. */
- CFRelease(properties);
- }
-
- /* Release. */
- IOObjectRelease(drive);
- }
- IOIteratorReset(drive_list);
-
- /* Release. */
- IOObjectRelease(drive_list);
- }
-
- if (likely(do_io)) {
- st = rrdset_find_bytype_localhost("system", "io");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "io"
- , NULL
- , "disk"
- , NULL
- , "Disk I/O"
- , "kilobytes/s"
- , "macos"
- , "iokit"
- , 150
- , update_every
- , RRDSET_TYPE_AREA
- );
- rrddim_add(st, "in", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "out", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "in", total_disk_reads);
- rrddim_set(st, "out", total_disk_writes);
- rrdset_done(st);
- }
-
- // Can be merged with FreeBSD plugin
- // --------------------------------------------------------------------------
-
- if (likely(do_space || do_inodes)) {
- // there is no mount info in sysctl MIBs
- if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
- error("MACOS: getmntinfo() failed");
- do_space = 0;
- error("DISABLED: disk_space.X");
- do_inodes = 0;
- error("DISABLED: disk_inodes.X");
- } else {
- for (i = 0; i < mntsize; i++) {
- if (mntbuf[i].f_flags == MNT_RDONLY ||
- mntbuf[i].f_blocks == 0 ||
- // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
- strcmp(mntbuf[i].f_fstypename, "autofs") == 0 ||
- strcmp(mntbuf[i].f_fstypename, "procfs") == 0 ||
- strcmp(mntbuf[i].f_fstypename, "subfs") == 0 ||
- strcmp(mntbuf[i].f_fstypename, "devfs") == 0 ||
- strcmp(mntbuf[i].f_fstypename, "none") == 0)
- continue;
-
- // --------------------------------------------------------------------------
-
- if (likely(do_space)) {
- st = rrdset_find_bytype_localhost("disk_space", mntbuf[i].f_mntonname);
- if (unlikely(!st)) {
- snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
- st = rrdset_create_localhost(
- "disk_space"
- , mntbuf[i].f_mntonname
- , NULL
- , mntbuf[i].f_mntonname
- , "disk.space"
- , title
- , "GB"
- , "macos"
- , "iokit"
- , 2023
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "avail", (collected_number) mntbuf[i].f_bavail);
- rrddim_set(st, "used", (collected_number) (mntbuf[i].f_blocks - mntbuf[i].f_bfree));
- rrddim_set(st, "reserved_for_root", (collected_number) (mntbuf[i].f_bfree - mntbuf[i].f_bavail));
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------------
-
- if (likely(do_inodes)) {
- st = rrdset_find_bytype_localhost("disk_inodes", mntbuf[i].f_mntonname);
- if (unlikely(!st)) {
- snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
- st = rrdset_create_localhost(
- "disk_inodes"
- , mntbuf[i].f_mntonname
- , NULL
- , mntbuf[i].f_mntonname
- , "disk.inodes"
- , title
- , "Inodes"
- , "macos"
- , "iokit"
- , 2024
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "avail", (collected_number) mntbuf[i].f_ffree);
- rrddim_set(st, "used", (collected_number) (mntbuf[i].f_files - mntbuf[i].f_ffree));
- rrdset_done(st);
- }
- }
- }
- }
-
- // Can be merged with FreeBSD plugin
- // --------------------------------------------------------------------
-
- if (likely(do_bandwidth)) {
- if (unlikely(getifaddrs(&ifap))) {
- error("MACOS: getifaddrs()");
- do_bandwidth = 0;
- error("DISABLED: system.ipv4");
- } else {
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("net", ifa->ifa_name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "net"
- , ifa->ifa_name
- , NULL
- , ifa->ifa_name
- , "net.net"
- , "Bandwidth"
- , "kilobits/s"
- , "macos"
- , "iokit"
- , 7000
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "received", IFA_DATA(ibytes));
- rrddim_set(st, "sent", IFA_DATA(obytes));
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("net_packets", ifa->ifa_name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "net_packets"
- , ifa->ifa_name
- , NULL
- , ifa->ifa_name
- , "net.packets"
- , "Packets"
- , "packets/s"
- , "macos"
- , "iokit"
- , 7001
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "received", IFA_DATA(ipackets));
- rrddim_set(st, "sent", IFA_DATA(opackets));
- rrddim_set(st, "multicast_received", IFA_DATA(imcasts));
- rrddim_set(st, "multicast_sent", IFA_DATA(omcasts));
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("net_errors", ifa->ifa_name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "net_errors"
- , ifa->ifa_name
- , NULL
- , ifa->ifa_name
- , "net.errors"
- , "Interface Errors"
- , "errors/s"
- , "macos"
- , "iokit"
- , 7002
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "inbound", IFA_DATA(ierrors));
- rrddim_set(st, "outbound", IFA_DATA(oerrors));
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("net_drops", ifa->ifa_name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "net_drops"
- , ifa->ifa_name
- , NULL
- , ifa->ifa_name
- , "net.drops"
- , "Interface Drops"
- , "drops/s"
- , "macos"
- , "iokit"
- , 7003
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "inbound", IFA_DATA(iqdrops));
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("net_events", ifa->ifa_name);
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "net_events"
- , ifa->ifa_name
- , NULL
- , ifa->ifa_name
- , "net.events"
- , "Network Interface Events"
- , "events/s"
- , "macos"
- , "iokit"
- , 7006
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "collisions", IFA_DATA(collisions));
- rrdset_done(st);
- }
-
- freeifaddrs(ifap);
- }
- }
-
-
- return 0;
-}
diff --git a/src/macos_mach_smi.c b/src/macos_mach_smi.c
deleted file mode 100644
index 47d32a9f7..000000000
--- a/src/macos_mach_smi.c
+++ /dev/null
@@ -1,238 +0,0 @@
-#include "common.h"
-#include <mach/mach.h>
-
-int do_macos_mach_smi(int update_every, usec_t dt) {
- (void)dt;
-
- static int do_cpu = -1, do_ram = - 1, do_swapio = -1, do_pgfaults = -1;
-
- if (unlikely(do_cpu == -1)) {
- do_cpu = config_get_boolean("plugin:macos:mach_smi", "cpu utilization", 1);
- do_ram = config_get_boolean("plugin:macos:mach_smi", "system ram", 1);
- do_swapio = config_get_boolean("plugin:macos:mach_smi", "swap i/o", 1);
- do_pgfaults = config_get_boolean("plugin:macos:mach_smi", "memory page faults", 1);
- }
-
- RRDSET *st;
-
- kern_return_t kr;
- mach_msg_type_number_t count;
- host_t host;
- vm_size_t system_pagesize;
-
-
- // NEEDED BY: do_cpu
- natural_t cp_time[CPU_STATE_MAX];
-
- // NEEDED BY: do_ram, do_swapio, do_pgfaults
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
- vm_statistics64_data_t vm_statistics;
-#else
- vm_statistics_data_t vm_statistics;
-#endif
-
- host = mach_host_self();
- kr = host_page_size(host, &system_pagesize);
- if (unlikely(kr != KERN_SUCCESS))
- return -1;
-
- // --------------------------------------------------------------------
-
- if (likely(do_cpu)) {
- if (unlikely(HOST_CPU_LOAD_INFO_COUNT != 4)) {
- error("MACOS: There are %d CPU states (4 was expected)", HOST_CPU_LOAD_INFO_COUNT);
- do_cpu = 0;
- error("DISABLED: system.cpu");
- } else {
- count = HOST_CPU_LOAD_INFO_COUNT;
- kr = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)cp_time, &count);
- if (unlikely(kr != KERN_SUCCESS)) {
- error("MACOS: host_statistics() failed: %s", mach_error_string(kr));
- do_cpu = 0;
- error("DISABLED: system.cpu");
- } else {
-
- st = rrdset_find_bytype_localhost("system", "cpu");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "cpu"
- , NULL
- , "cpu"
- , "system.cpu"
- , "Total CPU utilization"
- , "percentage"
- , "macos"
- , "mach_smi"
- , 100
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_add(st, "system", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_hide(st, "idle");
- }
- else rrdset_next(st);
-
- rrddim_set(st, "user", cp_time[CPU_STATE_USER]);
- rrddim_set(st, "nice", cp_time[CPU_STATE_NICE]);
- rrddim_set(st, "system", cp_time[CPU_STATE_SYSTEM]);
- rrddim_set(st, "idle", cp_time[CPU_STATE_IDLE]);
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ram || do_swapio || do_pgfaults)) {
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
- count = sizeof(vm_statistics64_data_t);
- kr = host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_statistics, &count);
-#else
- count = sizeof(vm_statistics_data_t);
- kr = host_statistics(host, HOST_VM_INFO, (host_info_t)&vm_statistics, &count);
-#endif
- if (unlikely(kr != KERN_SUCCESS)) {
- error("MACOS: host_statistics64() failed: %s", mach_error_string(kr));
- do_ram = 0;
- error("DISABLED: system.ram");
- do_swapio = 0;
- error("DISABLED: system.swapio");
- do_pgfaults = 0;
- error("DISABLED: mem.pgfaults");
- } else {
- if (likely(do_ram)) {
- st = rrdset_find_localhost("system.ram");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "ram"
- , NULL
- , "ram"
- , NULL
- , "System RAM"
- , "MB"
- , "macos"
- , "mach_smi"
- , 200
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(st, "active", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "wired", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- rrddim_add(st, "throttled", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "compressor", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
-#endif
- rrddim_add(st, "inactive", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "purgeable", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "speculative", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "free", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "active", vm_statistics.active_count);
- rrddim_set(st, "wired", vm_statistics.wire_count);
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- rrddim_set(st, "throttled", vm_statistics.throttled_count);
- rrddim_set(st, "compressor", vm_statistics.compressor_page_count);
-#endif
- rrddim_set(st, "inactive", vm_statistics.inactive_count);
- rrddim_set(st, "purgeable", vm_statistics.purgeable_count);
- rrddim_set(st, "speculative", vm_statistics.speculative_count);
- rrddim_set(st, "free", (vm_statistics.free_count - vm_statistics.speculative_count));
- rrdset_done(st);
- }
-
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- // --------------------------------------------------------------------
-
- if (likely(do_swapio)) {
- st = rrdset_find_localhost("system.swapio");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "swapio"
- , NULL
- , "swap"
- , NULL
- , "Swap I/O"
- , "kilobytes/s"
- , "macos"
- , "mach_smi"
- , 250
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(st, "in", NULL, system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "in", vm_statistics.swapins);
- rrddim_set(st, "out", vm_statistics.swapouts);
- rrdset_done(st);
- }
-#endif
-
- // --------------------------------------------------------------------
-
- if (likely(do_pgfaults)) {
- st = rrdset_find_localhost("mem.pgfaults");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "mem"
- , "pgfaults"
- , NULL
- , "system"
- , NULL
- , "Memory Page Faults"
- , "page faults/s"
- , "macos"
- , "mach_smi"
- , NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "memory", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "cow", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "pagein", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "pageout", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- rrddim_add(st, "compress", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "decompress", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#endif
- rrddim_add(st, "zero_fill", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "reactivate", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "purge", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "memory", vm_statistics.faults);
- rrddim_set(st, "cow", vm_statistics.cow_faults);
- rrddim_set(st, "pagein", vm_statistics.pageins);
- rrddim_set(st, "pageout", vm_statistics.pageouts);
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- rrddim_set(st, "compress", vm_statistics.compressions);
- rrddim_set(st, "decompress", vm_statistics.decompressions);
-#endif
- rrddim_set(st, "zero_fill", vm_statistics.zero_fill_count);
- rrddim_set(st, "reactivate", vm_statistics.reactivations);
- rrddim_set(st, "purge", vm_statistics.purges);
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- return 0;
-}
diff --git a/src/macos_sysctl.c b/src/macos_sysctl.c
deleted file mode 100644
index cb6fa8af9..000000000
--- a/src/macos_sysctl.c
+++ /dev/null
@@ -1,1504 +0,0 @@
-#include "common.h"
-#include <Availability.h>
-#include <sys/sysctl.h>
-// NEEDED BY: do_bandwidth
-#include <net/route.h>
-// NEEDED BY do_tcp...
-#include <sys/socketvar.h>
-#include <netinet/tcp_var.h>
-#include <netinet/tcp_fsm.h>
-// NEEDED BY do_udp..., do_ip...
-#include <netinet/ip_var.h>
-// NEEDED BY do_udp...
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-// NEEDED BY do_icmp...
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/icmp_var.h>
-// NEEDED BY do_icmp6...
-#include <netinet/icmp6.h>
-// NEEDED BY do_uptime
-#include <time.h>
-
-// MacOS calculates load averages once every 5 seconds
-#define MIN_LOADAVG_UPDATE_EVERY 5
-
-int do_macos_sysctl(int update_every, usec_t dt) {
- static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1,
- do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_ecn = -1,
- do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1,
- do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1,
- do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
- do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1,
- do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1,
- do_icmp6_router = -1, do_icmp6_neighbor = -1, do_icmp6_types = -1, do_uptime = -1;
-
-
- if (unlikely(do_loadavg == -1)) {
- do_loadavg = config_get_boolean("plugin:macos:sysctl", "enable load average", 1);
- do_swap = config_get_boolean("plugin:macos:sysctl", "system swap", 1);
- do_bandwidth = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
- do_tcp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1);
- do_tcp_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1);
- do_tcp_handshake = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1);
- do_ecn = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_BOOLEAN_AUTO);
- do_tcpext_syscookies = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO);
- do_tcpext_ofo = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO);
- do_tcpext_connaborts = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_BOOLEAN_AUTO);
- do_udp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP packets", 1);
- do_udp_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP errors", 1);
- do_icmp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP packets", 1);
- do_icmpmsg = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP messages", 1);
- do_ip_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 packets", 1);
- do_ip_fragsout = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments sent", 1);
- do_ip_fragsin = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments assembly", 1);
- do_ip_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 errors", 1);
- do_ip6_packets = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 packets", CONFIG_BOOLEAN_AUTO);
- do_ip6_fragsout = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO);
- do_ip6_fragsin = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO);
- do_ip6_errors = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 errors", CONFIG_BOOLEAN_AUTO);
- do_icmp6 = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp", CONFIG_BOOLEAN_AUTO);
- do_icmp6_redir = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp redirects", CONFIG_BOOLEAN_AUTO);
- do_icmp6_errors = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp errors", CONFIG_BOOLEAN_AUTO);
- do_icmp6_echos = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp echos", CONFIG_BOOLEAN_AUTO);
- do_icmp6_router = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp router", CONFIG_BOOLEAN_AUTO);
- do_icmp6_neighbor = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp neighbor", CONFIG_BOOLEAN_AUTO);
- do_icmp6_types = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp types", CONFIG_BOOLEAN_AUTO);
- do_uptime = config_get_boolean("plugin:macos:sysctl", "system uptime", 1);
- }
-
- RRDSET *st;
-
- int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
- int i, n;
- int common_error = 0;
- size_t size;
-
- // NEEDED BY: do_loadavg
- static usec_t next_loadavg_dt = 0;
- struct loadavg sysload;
-
- // NEEDED BY: do_swap
- struct xsw_usage swap_usage;
-
- // NEEDED BY: do_bandwidth
- int mib[6];
- static char *ifstatdata = NULL;
- char *lim, *next;
- struct if_msghdr *ifm;
- struct iftot {
- u_long ift_ibytes;
- u_long ift_obytes;
- } iftot = {0, 0};
-
- // NEEDED BY: do_tcp...
- struct tcpstat tcpstat;
- uint64_t tcps_states[TCP_NSTATES];
-
- // NEEDED BY: do_udp...
- struct udpstat udpstat;
-
- // NEEDED BY: do_icmp...
- struct icmpstat icmpstat;
- struct icmp_total {
- u_long msgs_in;
- u_long msgs_out;
- } icmp_total = {0, 0};
-
- // NEEDED BY: do_ip...
- struct ipstat ipstat;
-
- // NEEDED BY: do_ip6...
- /*
- * Dirty workaround for /usr/include/netinet6/ip6_var.h absence.
- * Struct ip6stat was copied from bsd/netinet6/ip6_var.h from xnu sources.
- * Do the same for previously missing scope6_var.h on OS X < 10.11.
- */
-#define IP6S_SRCRULE_COUNT 16
-
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100)
-#ifndef _NETINET6_SCOPE6_VAR_H_
-#define _NETINET6_SCOPE6_VAR_H_
-#include <sys/appleapiopts.h>
-
-#define SCOPE6_ID_MAX 16
-#endif
-#else
-#include <netinet6/scope6_var.h>
-#endif
-
- struct ip6stat {
- u_quad_t ip6s_total; /* total packets received */
- u_quad_t ip6s_tooshort; /* packet too short */
- u_quad_t ip6s_toosmall; /* not enough data */
- u_quad_t ip6s_fragments; /* fragments received */
- u_quad_t ip6s_fragdropped; /* frags dropped(dups, out of space) */
- u_quad_t ip6s_fragtimeout; /* fragments timed out */
- u_quad_t ip6s_fragoverflow; /* fragments that exceeded limit */
- u_quad_t ip6s_forward; /* packets forwarded */
- u_quad_t ip6s_cantforward; /* packets rcvd for unreachable dest */
- u_quad_t ip6s_redirectsent; /* packets forwarded on same net */
- u_quad_t ip6s_delivered; /* datagrams delivered to upper level */
- u_quad_t ip6s_localout; /* total ip packets generated here */
- u_quad_t ip6s_odropped; /* lost packets due to nobufs, etc. */
- u_quad_t ip6s_reassembled; /* total packets reassembled ok */
- u_quad_t ip6s_atmfrag_rcvd; /* atomic fragments received */
- u_quad_t ip6s_fragmented; /* datagrams successfully fragmented */
- u_quad_t ip6s_ofragments; /* output fragments created */
- u_quad_t ip6s_cantfrag; /* don't fragment flag was set, etc. */
- u_quad_t ip6s_badoptions; /* error in option processing */
- u_quad_t ip6s_noroute; /* packets discarded due to no route */
- u_quad_t ip6s_badvers; /* ip6 version != 6 */
- u_quad_t ip6s_rawout; /* total raw ip packets generated */
- u_quad_t ip6s_badscope; /* scope error */
- u_quad_t ip6s_notmember; /* don't join this multicast group */
- u_quad_t ip6s_nxthist[256]; /* next header history */
- u_quad_t ip6s_m1; /* one mbuf */
- u_quad_t ip6s_m2m[32]; /* two or more mbuf */
- u_quad_t ip6s_mext1; /* one ext mbuf */
- u_quad_t ip6s_mext2m; /* two or more ext mbuf */
- u_quad_t ip6s_exthdrtoolong; /* ext hdr are not continuous */
- u_quad_t ip6s_nogif; /* no match gif found */
- u_quad_t ip6s_toomanyhdr; /* discarded due to too many headers */
-
- /*
- * statistics for improvement of the source address selection
- * algorithm:
- */
- /* number of times that address selection fails */
- u_quad_t ip6s_sources_none;
- /* number of times that an address on the outgoing I/F is chosen */
- u_quad_t ip6s_sources_sameif[SCOPE6_ID_MAX];
- /* number of times that an address on a non-outgoing I/F is chosen */
- u_quad_t ip6s_sources_otherif[SCOPE6_ID_MAX];
- /*
- * number of times that an address that has the same scope
- * from the destination is chosen.
- */
- u_quad_t ip6s_sources_samescope[SCOPE6_ID_MAX];
- /*
- * number of times that an address that has a different scope
- * from the destination is chosen.
- */
- u_quad_t ip6s_sources_otherscope[SCOPE6_ID_MAX];
- /* number of times that a deprecated address is chosen */
- u_quad_t ip6s_sources_deprecated[SCOPE6_ID_MAX];
-
- u_quad_t ip6s_forward_cachehit;
- u_quad_t ip6s_forward_cachemiss;
-
- /* number of times that each rule of source selection is applied. */
- u_quad_t ip6s_sources_rule[IP6S_SRCRULE_COUNT];
-
- /* number of times we ignored address on expensive secondary interfaces */
- u_quad_t ip6s_sources_skip_expensive_secondary_if;
-
- /* pkt dropped, no mbufs for control data */
- u_quad_t ip6s_pktdropcntrl;
-
- /* total packets trimmed/adjusted */
- u_quad_t ip6s_adj;
- /* hwcksum info discarded during adjustment */
- u_quad_t ip6s_adj_hwcsum_clr;
-
- /* duplicate address detection collisions */
- u_quad_t ip6s_dad_collide;
-
- /* DAD NS looped back */
- u_quad_t ip6s_dad_loopcount;
- } ip6stat;
-
- // NEEDED BY: do_icmp6...
- struct icmp6stat icmp6stat;
- struct icmp6_total {
- u_long msgs_in;
- u_long msgs_out;
- } icmp6_total = {0, 0};
-
- // NEEDED BY: do_uptime
- struct timespec boot_time, cur_time;
-
- // --------------------------------------------------------------------
-
- if (next_loadavg_dt <= dt) {
- if (likely(do_loadavg)) {
- if (unlikely(GETSYSCTL_BY_NAME("vm.loadavg", sysload))) {
- do_loadavg = 0;
- error("DISABLED: system.load");
- } else {
-
- st = rrdset_find_bytype_localhost("system", "load");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "load"
- , NULL
- , "load"
- , NULL
- , "System Load Average"
- , "load"
- , "macos"
- , "sysctl"
- , 100
- , (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every
- , RRDSET_TYPE_LINE
- );
- rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000));
- rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000));
- rrddim_set(st, "load15", (collected_number) ((double)sysload.ldavg[2] / sysload.fscale * 1000));
- rrdset_done(st);
- }
- }
-
- next_loadavg_dt = st->update_every * USEC_PER_SEC;
- }
- else next_loadavg_dt -= dt;
-
- // --------------------------------------------------------------------
-
- if (likely(do_swap)) {
- if (unlikely(GETSYSCTL_BY_NAME("vm.swapusage", swap_usage))) {
- do_swap = 0;
- error("DISABLED: system.swap");
- } else {
- st = rrdset_find_localhost("system.swap");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "swap"
- , NULL
- , "swap"
- , NULL
- , "System Swap"
- , "MB"
- , "macos"
- , "sysctl"
- , 201
- , update_every
- , RRDSET_TYPE_STACKED
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "free", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(st, "used", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "free", swap_usage.xsu_avail);
- rrddim_set(st, "used", swap_usage.xsu_used);
- rrdset_done(st);
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_bandwidth)) {
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = AF_INET;
- mib[4] = NET_RT_IFLIST2;
- mib[5] = 0;
- if (unlikely(sysctl(mib, 6, NULL, &size, NULL, 0))) {
- error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
- do_bandwidth = 0;
- error("DISABLED: system.ipv4");
- } else {
- ifstatdata = reallocz(ifstatdata, size);
- if (unlikely(sysctl(mib, 6, ifstatdata, &size, NULL, 0) < 0)) {
- error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
- do_bandwidth = 0;
- error("DISABLED: system.ipv4");
- } else {
- lim = ifstatdata + size;
- iftot.ift_ibytes = iftot.ift_obytes = 0;
- for (next = ifstatdata; next < lim; ) {
- ifm = (struct if_msghdr *)next;
- next += ifm->ifm_msglen;
-
- if (ifm->ifm_type == RTM_IFINFO2) {
- struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
-
- iftot.ift_ibytes += if2m->ifm_data.ifi_ibytes;
- iftot.ift_obytes += if2m->ifm_data.ifi_obytes;
- }
- }
- st = rrdset_find_localhost("system.ipv4");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "ipv4"
- , NULL
- , "network"
- , NULL
- , "IPv4 Bandwidth"
- , "kilobits/s"
- , "macos"
- , "sysctl"
- , 500
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "InOctets", iftot.ift_ibytes);
- rrddim_set(st, "OutOctets", iftot.ift_obytes);
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
- if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
- if (unlikely(GETSYSCTL_BY_NAME("net.inet.tcp.stats", tcpstat))){
- do_tcp_packets = 0;
- error("DISABLED: ipv4.tcppackets");
- do_tcp_errors = 0;
- error("DISABLED: ipv4.tcperrors");
- do_tcp_handshake = 0;
- error("DISABLED: ipv4.tcphandshake");
- do_tcpext_connaborts = 0;
- error("DISABLED: ipv4.tcpconnaborts");
- do_tcpext_ofo = 0;
- error("DISABLED: ipv4.tcpofo");
- do_tcpext_syscookies = 0;
- error("DISABLED: ipv4.tcpsyncookies");
- do_ecn = 0;
- error("DISABLED: ipv4.ecnpkts");
- } else {
- if (likely(do_tcp_packets)) {
- st = rrdset_find_localhost("ipv4.tcppackets");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "tcppackets"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Packets"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 2600
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal);
- rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_tcp_errors)) {
- st = rrdset_find_localhost("ipv4.tcperrors");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "tcperrors"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Errors"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 2700
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
- rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
- rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_tcp_handshake)) {
- st = rrdset_find_localhost("ipv4.tcphandshake");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "tcphandshake"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Handshake Issues"
- , "events/s"
- , "macos"
- , "sysctl"
- , 2900
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "EstabResets", tcpstat.tcps_drops);
- rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
- rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
- rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop))) {
- do_tcpext_connaborts = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv4.tcpconnaborts");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "tcpconnaborts"
- , NULL
- , "tcp"
- , NULL
- , "TCP Connection Aborts"
- , "connections/s"
- , "macos"
- , "sysctl"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "TCPAbortOnData", tcpstat.tcps_rcvpackafterwin);
- rrddim_set(st, "TCPAbortOnClose", tcpstat.tcps_rcvafterclose);
- rrddim_set(st, "TCPAbortOnMemory", tcpstat.tcps_rcvmemdrop);
- rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_rcvoopack)) {
- do_tcpext_ofo = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv4.tcpofo");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "tcpofo"
- , NULL
- , "tcp"
- , NULL
- , "TCP Out-Of-Order Queue"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3050
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "TCPOFOQueue", tcpstat.tcps_rcvoopack);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) {
- do_tcpext_syscookies = CONFIG_BOOLEAN_YES;
-
- st = rrdset_find_localhost("ipv4.tcpsyncookies");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "tcpsyncookies"
- , NULL
- , "tcp"
- , NULL
- , "TCP SYN Cookies"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3100
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "SyncookiesRecv", tcpstat.tcps_sc_recvcookie);
- rrddim_set(st, "SyncookiesSent", tcpstat.tcps_sc_sendcookie);
- rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
-
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
- if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) {
- do_ecn = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv4.ecnpkts");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "ecnpkts"
- , NULL
- , "ecn"
- , NULL
- , "IPv4 ECN Statistics"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 8700
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce);
- rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported);
- rrdset_done(st);
- }
-#endif
-
- }
- }
-
- // --------------------------------------------------------------------
-
- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
- if (likely(do_udp_packets || do_udp_errors)) {
- if (unlikely(GETSYSCTL_BY_NAME("net.inet.udp.stats", udpstat))) {
- do_udp_packets = 0;
- error("DISABLED: ipv4.udppackets");
- do_udp_errors = 0;
- error("DISABLED: ipv4.udperrors");
- } else {
- if (likely(do_udp_packets)) {
- st = rrdset_find_localhost("ipv4.udppackets");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "udppackets"
- , NULL
- , "udp"
- , NULL
- , "IPv4 UDP Packets"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 2601
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InDatagrams", udpstat.udps_ipackets);
- rrddim_set(st, "OutDatagrams", udpstat.udps_opackets);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_udp_errors)) {
- st = rrdset_find_localhost("ipv4.udperrors");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "udperrors"
- , NULL
- , "udp"
- , NULL
- , "IPv4 UDP Errors"
- , "events/s"
- , "macos"
- , "sysctl"
- , 2701
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#endif
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen);
- rrddim_set(st, "NoPorts", udpstat.udps_noport);
- rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock);
-#if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
- rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum);
- rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast);
-#else
- rrddim_set(st, "InCsumErrors", udpstat.udps_badsum);
-#endif
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmp_packets || do_icmpmsg)) {
- if (unlikely(GETSYSCTL_BY_NAME("net.inet.icmp.stats", icmpstat))) {
- do_icmp_packets = 0;
- error("DISABLED: ipv4.icmp");
- error("DISABLED: ipv4.icmp_errors");
- do_icmpmsg = 0;
- error("DISABLED: ipv4.icmpmsg");
- } else {
- for (i = 0; i <= ICMP_MAXTYPE; i++) {
- icmp_total.msgs_in += icmpstat.icps_inhist[i];
- icmp_total.msgs_out += icmpstat.icps_outhist[i];
- }
- icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmp_packets)) {
- st = rrdset_find_localhost("ipv4.icmp");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "icmp"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Packets"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 2602
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InMsgs", icmp_total.msgs_in);
- rrddim_set(st, "OutMsgs", icmp_total.msgs_out);
-
- rrdset_done(st);
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_localhost("ipv4.icmp_errors");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "icmp_errors"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Errors"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 2603
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InErrors", icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort);
- rrddim_set(st, "OutErrors", icmpstat.icps_error);
- rrddim_set(st, "InCsumErrors", icmpstat.icps_checksum);
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmpmsg)) {
- st = rrdset_find_localhost("ipv4.icmpmsg");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "icmpmsg"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Messages"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 2604
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InEchoReps", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]);
- rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]);
- rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]);
- rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]);
-
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
- if (likely(do_ip_packets || do_ip_fragsout || do_ip_fragsin || do_ip_errors)) {
- if (unlikely(GETSYSCTL_BY_NAME("net.inet.ip.stats", ipstat))) {
- do_ip_packets = 0;
- error("DISABLED: ipv4.packets");
- do_ip_fragsout = 0;
- error("DISABLED: ipv4.fragsout");
- do_ip_fragsin = 0;
- error("DISABLED: ipv4.fragsin");
- do_ip_errors = 0;
- error("DISABLED: ipv4.errors");
- } else {
- if (likely(do_ip_packets)) {
- st = rrdset_find_localhost("ipv4.packets");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "packets"
- , NULL
- , "packets"
- , NULL
- , "IPv4 Packets"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "OutRequests", ipstat.ips_localout);
- rrddim_set(st, "InReceives", ipstat.ips_total);
- rrddim_set(st, "ForwDatagrams", ipstat.ips_forward);
- rrddim_set(st, "InDelivers", ipstat.ips_delivered);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_fragsout)) {
- st = rrdset_find_localhost("ipv4.fragsout");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "fragsout"
- , NULL
- , "fragments"
- , NULL
- , "IPv4 Fragments Sent"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "FragOKs", ipstat.ips_fragmented);
- rrddim_set(st, "FragFails", ipstat.ips_cantfrag);
- rrddim_set(st, "FragCreates", ipstat.ips_ofragments);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_fragsin)) {
- st = rrdset_find_localhost("ipv4.fragsin");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "fragsin"
- , NULL
- , "fragments"
- , NULL
- , "IPv4 Fragments Reassembly"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3011
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "ReasmOKs", ipstat.ips_fragments);
- rrddim_set(st, "ReasmFails", ipstat.ips_fragdropped);
- rrddim_set(st, "ReasmReqds", ipstat.ips_reassembled);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip_errors)) {
- st = rrdset_find_localhost("ipv4.errors");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "errors"
- , NULL
- , "errors"
- , NULL
- , "IPv4 Errors"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3002
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InDiscards", ipstat.ips_badsum + ipstat.ips_tooshort + ipstat.ips_toosmall + ipstat.ips_toolong);
- rrddim_set(st, "OutDiscards", ipstat.ips_odropped);
- rrddim_set(st, "InHdrErrors", ipstat.ips_badhlen + ipstat.ips_badlen + ipstat.ips_badoptions + ipstat.ips_badvers);
- rrddim_set(st, "InAddrErrors", ipstat.ips_badaddr);
- rrddim_set(st, "InUnknownProtos", ipstat.ips_noproto);
- rrddim_set(st, "OutNoRoutes", ipstat.ips_noroute);
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) {
- if (unlikely(GETSYSCTL_BY_NAME("net.inet6.ip6.stats", ip6stat))) {
- do_ip6_packets = 0;
- error("DISABLED: ipv6.packets");
- do_ip6_fragsout = 0;
- error("DISABLED: ipv6.fragsout");
- do_ip6_fragsin = 0;
- error("DISABLED: ipv6.fragsin");
- do_ip6_errors = 0;
- error("DISABLED: ipv6.errors");
- } else {
- if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO &&
- (ip6stat.ip6s_localout || ip6stat.ip6s_total ||
- ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) {
- do_ip6_packets = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.packets");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "packets"
- , NULL
- , "packets"
- , NULL
- , "IPv6 Packets"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "sent", ip6stat.ip6s_localout);
- rrddim_set(st, "received", ip6stat.ip6s_total);
- rrddim_set(st, "forwarded", ip6stat.ip6s_forward);
- rrddim_set(st, "delivers", ip6stat.ip6s_delivered);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO &&
- (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag ||
- ip6stat.ip6s_ofragments))) {
- do_ip6_fragsout = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.fragsout");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "fragsout"
- , NULL
- , "fragments"
- , NULL
- , "IPv6 Fragments Sent"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "ok", ip6stat.ip6s_fragmented);
- rrddim_set(st, "failed", ip6stat.ip6s_cantfrag);
- rrddim_set(st, "all", ip6stat.ip6s_ofragments);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO &&
- (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped ||
- ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) {
- do_ip6_fragsin = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.fragsin");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "fragsin"
- , NULL
- , "fragments"
- , NULL
- , "IPv6 Fragments Reassembly"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3011
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "ok", ip6stat.ip6s_reassembled);
- rrddim_set(st, "failed", ip6stat.ip6s_fragdropped);
- rrddim_set(st, "timeout", ip6stat.ip6s_fragtimeout);
- rrddim_set(st, "all", ip6stat.ip6s_fragments);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && (
- ip6stat.ip6s_toosmall ||
- ip6stat.ip6s_odropped ||
- ip6stat.ip6s_badoptions ||
- ip6stat.ip6s_badvers ||
- ip6stat.ip6s_exthdrtoolong ||
- ip6stat.ip6s_sources_none ||
- ip6stat.ip6s_tooshort ||
- ip6stat.ip6s_cantforward ||
- ip6stat.ip6s_noroute))) {
- do_ip6_errors = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.errors");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "errors"
- , NULL
- , "errors"
- , NULL
- , "IPv6 Errors"
- , "packets/s"
- , "macos"
- , "sysctl"
- , 3002
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InDiscards", ip6stat.ip6s_toosmall);
- rrddim_set(st, "OutDiscards", ip6stat.ip6s_odropped);
-
- rrddim_set(st, "InHdrErrors",
- ip6stat.ip6s_badoptions + ip6stat.ip6s_badvers + ip6stat.ip6s_exthdrtoolong);
- rrddim_set(st, "InAddrErrors", ip6stat.ip6s_sources_none);
- rrddim_set(st, "InTruncatedPkts", ip6stat.ip6s_tooshort);
- rrddim_set(st, "InNoRoutes", ip6stat.ip6s_cantforward);
-
- rrddim_set(st, "OutNoRoutes", ip6stat.ip6s_noroute);
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) {
- if (unlikely(GETSYSCTL_BY_NAME("net.inet6.icmp6.stats", icmp6stat))) {
- do_icmp6 = 0;
- error("DISABLED: ipv6.icmp");
- } else {
- for (i = 0; i <= ICMP6_MAXTYPE; i++) {
- icmp6_total.msgs_in += icmp6stat.icp6s_inhist[i];
- icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i];
- }
- icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort;
- if (do_icmp6 == CONFIG_BOOLEAN_YES || (do_icmp6 == CONFIG_BOOLEAN_AUTO && (icmp6_total.msgs_in || icmp6_total.msgs_out))) {
- do_icmp6 = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmp");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmp"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 ICMP Messages"
- , "messages/s"
- , "macos"
- , "sysctl"
- , 10000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "sent", icmp6_total.msgs_in);
- rrddim_set(st, "received", icmp6_total.msgs_out);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) {
- do_icmp6_redir = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmpredir");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmpredir"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 ICMP Redirects"
- , "redirects/s"
- , "macos"
- , "sysctl"
- , 10050
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "sent", icmp6stat.icp6s_inhist[ND_REDIRECT]);
- rrddim_set(st, "received", icmp6stat.icp6s_outhist[ND_REDIRECT]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_badcode ||
- icmp6stat.icp6s_badlen ||
- icmp6stat.icp6s_checksum ||
- icmp6stat.icp6s_tooshort ||
- icmp6stat.icp6s_error ||
- icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH] ||
- icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED] ||
- icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB] ||
- icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] ||
- icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] ||
- icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) {
- do_icmp6_errors = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmperrors");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmperrors"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 ICMP Errors"
- , "errors/s"
- , "macos"
- , "sysctl"
- , 10100
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InErrors", icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort);
- rrddim_set(st, "OutErrors", icmp6stat.icp6s_error);
- rrddim_set(st, "InCsumErrors", icmp6stat.icp6s_checksum);
- rrddim_set(st, "InDestUnreachs", icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH]);
- rrddim_set(st, "InPktTooBigs", icmp6stat.icp6s_badlen);
- rrddim_set(st, "InTimeExcds", icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED]);
- rrddim_set(st, "InParmProblems", icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB]);
- rrddim_set(st, "OutDestUnreachs", icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH]);
- rrddim_set(st, "OutTimeExcds", icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED]);
- rrddim_set(st, "OutParmProblems", icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] ||
- icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] ||
- icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] ||
- icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) {
- do_icmp6_echos = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmpechos");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmpechos"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 ICMP Echo"
- , "messages/s"
- , "macos"
- , "sysctl"
- , 10200
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InEchos", icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]);
- rrddim_set(st, "OutEchos", icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]);
- rrddim_set(st, "InEchoReplies", icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY]);
- rrddim_set(st, "OutEchoReplies", icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] ||
- icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] ||
- icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] ||
- icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) {
- do_icmp6_router = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmprouter");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmprouter"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 Router Messages"
- , "messages/s"
- , "macos"
- , "sysctl"
- , 10400
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]);
- rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]);
- rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT]);
- rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] ||
- icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] ||
- icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] ||
- icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) {
- do_icmp6_neighbor = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmpneighbor");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmpneighbor"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 Neighbor Messages"
- , "messages/s"
- , "macos"
- , "sysctl"
- , 10500
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]);
- rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
- rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]);
- rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && (
- icmp6stat.icp6s_inhist[1] ||
- icmp6stat.icp6s_inhist[128] ||
- icmp6stat.icp6s_inhist[129] ||
- icmp6stat.icp6s_inhist[136] ||
- icmp6stat.icp6s_outhist[1] ||
- icmp6stat.icp6s_outhist[128] ||
- icmp6stat.icp6s_outhist[129] ||
- icmp6stat.icp6s_outhist[133] ||
- icmp6stat.icp6s_outhist[135] ||
- icmp6stat.icp6s_outhist[136]))) {
- do_icmp6_types = CONFIG_BOOLEAN_YES;
- st = rrdset_find_localhost("ipv6.icmptypes");
- if (unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "icmptypes"
- , NULL
- , "icmp"
- , NULL
- , "IPv6 ICMP Types"
- , "messages/s"
- , "macos"
- , "sysctl"
- , 10700
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- } else
- rrdset_next(st);
-
- rrddim_set(st, "InType1", icmp6stat.icp6s_inhist[1]);
- rrddim_set(st, "InType128", icmp6stat.icp6s_inhist[128]);
- rrddim_set(st, "InType129", icmp6stat.icp6s_inhist[129]);
- rrddim_set(st, "InType136", icmp6stat.icp6s_inhist[136]);
- rrddim_set(st, "OutType1", icmp6stat.icp6s_outhist[1]);
- rrddim_set(st, "OutType128", icmp6stat.icp6s_outhist[128]);
- rrddim_set(st, "OutType129", icmp6stat.icp6s_outhist[129]);
- rrddim_set(st, "OutType133", icmp6stat.icp6s_outhist[133]);
- rrddim_set(st, "OutType135", icmp6stat.icp6s_outhist[135]);
- rrddim_set(st, "OutType143", icmp6stat.icp6s_outhist[143]);
- rrdset_done(st);
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if (likely(do_uptime)) {
- if (unlikely(GETSYSCTL_BY_NAME("kern.boottime", boot_time))) {
- do_uptime = 0;
- error("DISABLED: system.uptime");
- } else {
- clock_gettime(CLOCK_REALTIME, &cur_time);
- st = rrdset_find_localhost("system.uptime");
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "uptime"
- , NULL
- , "uptime"
- , NULL
- , "System Uptime"
- , "seconds"
- , "macos"
- , "sysctl"
- , 1000
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "uptime", cur_time.tv_sec - boot_time.tv_sec);
- rrdset_done(st);
- }
- }
-
- return 0;
-}
-
-int getsysctl_by_name(const char *name, void *ptr, size_t len)
-{
- size_t nlen = len;
-
- if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
- error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno));
- return 1;
- }
- if (unlikely(nlen != len)) {
- error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
- return 1;
- }
- return 0;
-}
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 798c7f0fc..000000000
--- a/src/main.c
+++ /dev/null
@@ -1,1071 +0,0 @@
-#include "common.h"
-
-extern void *cgroups_main(void *ptr);
-
-void netdata_cleanup_and_exit(int ret) {
- // enabling this, is wrong
- // because the threads will be cancelled while cleaning up
- // netdata_exit = 1;
-
- error_log_limit_unlimited();
- info("EXIT: netdata prepares to exit with code %d...", ret);
-
- // cleanup/save the database and exit
- info("EXIT: cleaning up the database...");
- rrdhost_cleanup_all();
-
- if(!ret) {
- // exit cleanly
-
- // stop everything
- info("EXIT: stopping master threads...");
- cancel_main_threads();
-
- // free the database
- info("EXIT: freeing database memory...");
- rrdhost_free_all();
- }
-
- // unlink the pid
- if(pidfile[0]) {
- info("EXIT: removing netdata PID file '%s'...", pidfile);
- if(unlink(pidfile) != 0)
- error("EXIT: cannot unlink pidfile '%s'.", pidfile);
- }
-
- info("EXIT: all done - netdata is now exiting - bye bye...");
- exit(ret);
-}
-
-struct netdata_static_thread static_threads[] = {
-
-#ifdef INTERNAL_PLUGIN_NFACCT
- // nfacct requires root access
- // so, we build it as an external plugin with setuid to root
- {"PLUGIN[nfacct]", CONFIG_SECTION_PLUGINS, "nfacct", 1, NULL, NULL, nfacct_main},
-#endif
-
-#ifdef NETDATA_INTERNAL_CHECKS
- // debugging plugin
- {"PLUGIN[check]", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main},
-#endif
-
-#if defined(__FreeBSD__)
- // FreeBSD internal plugins
- {"PLUGIN[freebsd]", CONFIG_SECTION_PLUGINS, "freebsd", 1, NULL, NULL, freebsd_main},
-#elif defined(__APPLE__)
- // macOS internal plugins
- {"PLUGIN[macos]", CONFIG_SECTION_PLUGINS, "macos", 1, NULL, NULL, macos_main},
-#else
- // linux internal plugins
- {"PLUGIN[proc]", CONFIG_SECTION_PLUGINS, "proc", 1, NULL, NULL, proc_main},
- {"PLUGIN[diskspace]", CONFIG_SECTION_PLUGINS, "diskspace", 1, NULL, NULL, proc_diskspace_main},
- {"PLUGIN[cgroup]", CONFIG_SECTION_PLUGINS, "cgroups", 1, NULL, NULL, cgroups_main},
- {"PLUGIN[tc]", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main},
-#endif /* __FreeBSD__, __APPLE__*/
-
- // common plugins for all systems
- {"PLUGIN[idlejitter]", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main},
- {"BACKENDS", NULL, NULL, 1, NULL, NULL, backends_main},
- {"HEALTH", NULL, NULL, 1, NULL, NULL, health_main},
- {"PLUGINSD", NULL, NULL, 1, NULL, NULL, pluginsd_main},
- {"WEB_SERVER[multi]", NULL, NULL, 1, NULL, NULL, socket_listen_main_multi_threaded},
- {"WEB_SERVER[single]", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded},
- {"WEB_SERVER[static1]", NULL, NULL, 0, NULL, NULL, socket_listen_main_static_threaded},
- {"STREAM", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread},
- {"STATSD", NULL, NULL, 1, NULL, NULL, statsd_main},
-
- {NULL, NULL, NULL, 0, NULL, NULL, NULL}
-};
-
-void web_server_threading_selection(void) {
- web_server_mode = web_server_mode_id(config_get(CONFIG_SECTION_WEB, "mode", web_server_mode_name(web_server_mode)));
-
- int multi_threaded = (web_server_mode == WEB_SERVER_MODE_MULTI_THREADED);
- int single_threaded = (web_server_mode == WEB_SERVER_MODE_SINGLE_THREADED);
- int static_threaded = (web_server_mode == WEB_SERVER_MODE_STATIC_THREADED);
-
- int i;
- for (i = 0; static_threads[i].name; i++) {
- if (static_threads[i].start_routine == socket_listen_main_multi_threaded)
- static_threads[i].enabled = multi_threaded;
-
- if (static_threads[i].start_routine == socket_listen_main_single_threaded)
- static_threads[i].enabled = single_threaded;
-
- if (static_threads[i].start_routine == socket_listen_main_static_threaded)
- static_threads[i].enabled = static_threaded;
- }
-}
-
-void web_server_config_options(void) {
- web_client_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "disconnect idle clients after seconds", web_client_timeout);
- web_client_first_request_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "timeout for first request", web_client_first_request_timeout);
-
- respect_web_browser_do_not_track_policy = config_get_boolean(CONFIG_SECTION_WEB, "respect do not track policy", respect_web_browser_do_not_track_policy);
- web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", "");
- if(!*web_x_frame_options) web_x_frame_options = NULL;
-
- web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
- web_allow_dashboard_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
- web_allow_badges_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), NULL, SIMPLE_PATTERN_EXACT);
- web_allow_registry_from = simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT);
- web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"), NULL, SIMPLE_PATTERN_EXACT);
- web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from", "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*"), NULL, SIMPLE_PATTERN_EXACT);
-
-#ifdef NETDATA_WITH_ZLIB
- web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip);
-
- char *s = config_get(CONFIG_SECTION_WEB, "gzip compression strategy", "default");
- if(!strcmp(s, "default"))
- web_gzip_strategy = Z_DEFAULT_STRATEGY;
- else if(!strcmp(s, "filtered"))
- web_gzip_strategy = Z_FILTERED;
- else if(!strcmp(s, "huffman only"))
- web_gzip_strategy = Z_HUFFMAN_ONLY;
- else if(!strcmp(s, "rle"))
- web_gzip_strategy = Z_RLE;
- else if(!strcmp(s, "fixed"))
- web_gzip_strategy = Z_FIXED;
- else {
- error("Invalid compression strategy '%s'. Valid strategies are 'default', 'filtered', 'huffman only', 'rle' and 'fixed'. Proceeding with 'default'.", s);
- web_gzip_strategy = Z_DEFAULT_STRATEGY;
- }
-
- web_gzip_level = (int)config_get_number(CONFIG_SECTION_WEB, "gzip compression level", 3);
- if(web_gzip_level < 1) {
- error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 1 (fastest compression).", web_gzip_level);
- web_gzip_level = 1;
- }
- else if(web_gzip_level > 9) {
- error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 9 (best compression).", web_gzip_level);
- web_gzip_level = 9;
- }
-#endif /* NETDATA_WITH_ZLIB */
-}
-
-
-int killpid(pid_t pid, int sig)
-{
- int ret = -1;
- debug(D_EXIT, "Request to kill pid %d", pid);
-
- errno = 0;
- if(kill(pid, 0) == -1) {
- switch(errno) {
- case ESRCH:
- error("Request to kill pid %d, but it is not running.", pid);
- break;
-
- case EPERM:
- error("Request to kill pid %d, but I do not have enough permissions.", pid);
- break;
-
- default:
- error("Request to kill pid %d, but I received an error.", pid);
- break;
- }
- }
- else {
- errno = 0;
- ret = kill(pid, sig);
- if(ret == -1) {
- switch(errno) {
- case ESRCH:
- error("Cannot kill pid %d, but it is not running.", pid);
- break;
-
- case EPERM:
- error("Cannot kill pid %d, but I do not have enough permissions.", pid);
- break;
-
- default:
- error("Cannot kill pid %d, but I received an error.", pid);
- break;
- }
- }
- }
-
- return ret;
-}
-
-void cancel_main_threads() {
- error_log_limit_unlimited();
-
- int i, found = 0, max = 5 * USEC_PER_SEC, step = 100000;
- for (i = 0; static_threads[i].name != NULL ; i++) {
- if(static_threads[i].enabled == NETDATA_MAIN_THREAD_RUNNING) {
- info("EXIT: Stopping master thread: %s", static_threads[i].name);
- netdata_thread_cancel(*static_threads[i].thread);
- found++;
- }
- }
-
- while(found && max > 0) {
- max -= step;
- info("Waiting %d threads to finish...", found);
- sleep_usec(step);
- found = 0;
- for (i = 0; static_threads[i].name != NULL ; i++) {
- if (static_threads[i].enabled != NETDATA_MAIN_THREAD_EXITED)
- found++;
- }
- }
-
- if(found) {
- for (i = 0; static_threads[i].name != NULL ; i++) {
- if (static_threads[i].enabled != NETDATA_MAIN_THREAD_EXITED)
- error("Master thread %s takes too long to exit. Giving up...", static_threads[i].name);
- }
- }
- else
- info("All threads finished.");
-}
-
-struct option_def option_definitions[] = {
- // opt description arg name default value
- { 'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME},
- { 'D', "Do not fork. Run in the foreground.", NULL, "run in the background"},
- { 'h', "Display this help message.", NULL, NULL},
- { 'P', "File to save a pid while running.", "filename", "do not save pid to a file"},
- { 'i', "The IP address to listen to.", "IP", "all IP addresses IPv4 and IPv6"},
- { 'p', "API/Web port to use.", "port", "19999"},
- { 's', "Prefix for /proc and /sys (for containers).", "path", "no prefix"},
- { '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},
-};
-
-int help(int exitcode) {
- FILE *stream;
- if(exitcode == 0)
- stream = stdout;
- else
- stream = stderr;
-
- int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
- int i;
- int max_len_arg = 0;
-
- // Compute maximum argument length
- for( i = 0; i < num_opts; i++ ) {
- if(option_definitions[i].arg_name) {
- int len_arg = (int)strlen(option_definitions[i].arg_name);
- if(len_arg > max_len_arg) max_len_arg = len_arg;
- }
- }
-
- if(max_len_arg > 30) max_len_arg = 30;
- if(max_len_arg < 20) max_len_arg = 20;
-
- fprintf(stream, "%s", "\n"
- " ^\n"
- " |.-. .-. .-. .-. . netdata \n"
- " | '-' '-' '-' '-' real-time performance monitoring, done right! \n"
- " +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+--->\n"
- "\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"
- " Home Page : https://my-netdata.io\n"
- " Source Code: https://github.com/firehol/netdata\n"
- " Wiki / Docs: https://github.com/firehol/netdata/wiki\n"
- " Support : https://github.com/firehol/netdata/issues\n"
- " License : https://github.com/firehol/netdata/blob/master/LICENSE.md\n"
- "\n"
- " Twitter : https://twitter.com/linuxnetdata\n"
- " Facebook : https://www.facebook.com/linuxnetdata/\n"
- "\n"
- " netdata is a https://firehol.org project.\n"
- "\n"
- "\n"
- );
-
- fprintf(stream, " SYNOPSIS: netdata [options]\n");
- fprintf(stream, "\n");
- fprintf(stream, " Options:\n\n");
-
- // Output options description.
- for( i = 0; i < num_opts; i++ ) {
- fprintf(stream, " -%c %-*s %s", option_definitions[i].val, max_len_arg, option_definitions[i].arg_name ? option_definitions[i].arg_name : "", option_definitions[i].description);
- if(option_definitions[i].default_value) {
- fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", option_definitions[i].default_value);
- } else {
- fprintf(stream, "\n");
- }
- fprintf(stream, "\n");
- }
-
- fprintf(stream, "\n Advanced options:\n\n"
- " -W stacksize=N Set the stacksize (in bytes).\n\n"
- " -W debug_flags=N Set runtime tracing to debug.log.\n\n"
- " -W unittest Run internal unittests and exit.\n\n"
- " -W set section option value\n"
- " set netdata.conf option from the command line.\n\n"
- " -W simple-pattern pattern string\n"
- " Check if string matches pattern and exit.\n\n"
- );
-
- fprintf(stream, "\n Signals netdata handles:\n\n"
- " - HUP Close and reopen log files.\n"
- " - USR1 Save internal DB to disk.\n"
- " - USR2 Reload health configuration.\n"
- "\n"
- );
-
- fflush(stream);
- return exitcode;
-}
-
-// TODO: Remove this function with the nix major release.
-void remove_option(int opt_index, int *argc, char **argv) {
- int i = opt_index;
- // remove the options.
- do {
- *argc = *argc - 1;
- for(i = opt_index; i < *argc; i++) {
- argv[i] = argv[i+1];
- }
- i = opt_index;
- } while(argv[i][0] != '-' && opt_index >= *argc);
-}
-
-static const char *verify_required_directory(const char *dir) {
- if(chdir(dir) == -1)
- fatal("Cannot cd to directory '%s'", dir);
-
- DIR *d = opendir(dir);
- if(!d)
- fatal("Cannot examine the contents of directory '%s'", dir);
- closedir(d);
-
- return dir;
-}
-
-void log_init(void) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/debug.log", netdata_configured_log_dir);
- stdout_filename = config_get(CONFIG_SECTION_GLOBAL, "debug log", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s/error.log", netdata_configured_log_dir);
- stderr_filename = config_get(CONFIG_SECTION_GLOBAL, "error log", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s/access.log", netdata_configured_log_dir);
- stdaccess_filename = config_get(CONFIG_SECTION_GLOBAL, "access log", filename);
-
- error_log_throttle_period_backup =
- error_log_throttle_period = config_get_number(CONFIG_SECTION_GLOBAL, "errors flood protection period", error_log_throttle_period);
- error_log_errors_per_period = (unsigned long)config_get_number(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection", (long long int)error_log_errors_per_period);
-
- setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get(CONFIG_SECTION_GLOBAL, "errors flood protection period" , ""), 1);
- setenv("NETDATA_ERRORS_PER_PERIOD", config_get(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection", ""), 1);
-}
-
-static void backwards_compatible_config() {
- // allow existing configurations to work with the current version of netdata
-
- if(config_exists(CONFIG_SECTION_GLOBAL, "multi threaded web server")) {
- int mode = config_get_boolean(CONFIG_SECTION_GLOBAL, "multi threaded web server", 1);
- web_server_mode = (mode)?WEB_SERVER_MODE_MULTI_THREADED:WEB_SERVER_MODE_SINGLE_THREADED;
- }
-
- // move [global] options to the [web] section
- config_move(CONFIG_SECTION_GLOBAL, "http port listen backlog",
- CONFIG_SECTION_WEB, "listen backlog");
-
- config_move(CONFIG_SECTION_GLOBAL, "bind socket to IP",
- CONFIG_SECTION_WEB, "bind to");
-
- config_move(CONFIG_SECTION_GLOBAL, "bind to",
- CONFIG_SECTION_WEB, "bind to");
-
- config_move(CONFIG_SECTION_GLOBAL, "port",
- CONFIG_SECTION_WEB, "default port");
-
- config_move(CONFIG_SECTION_GLOBAL, "default port",
- CONFIG_SECTION_WEB, "default port");
-
- config_move(CONFIG_SECTION_GLOBAL, "disconnect idle web clients after seconds",
- CONFIG_SECTION_WEB, "disconnect idle clients after seconds");
-
- config_move(CONFIG_SECTION_GLOBAL, "respect web browser do not track policy",
- CONFIG_SECTION_WEB, "respect do not track policy");
-
- config_move(CONFIG_SECTION_GLOBAL, "web x-frame-options header",
- CONFIG_SECTION_WEB, "x-frame-options response header");
-
- config_move(CONFIG_SECTION_GLOBAL, "enable web responses gzip compression",
- CONFIG_SECTION_WEB, "enable gzip compression");
-
- config_move(CONFIG_SECTION_GLOBAL, "web compression strategy",
- CONFIG_SECTION_WEB, "gzip compression strategy");
-
- config_move(CONFIG_SECTION_GLOBAL, "web compression level",
- CONFIG_SECTION_WEB, "gzip compression level");
-
- config_move(CONFIG_SECTION_GLOBAL, "web files owner",
- CONFIG_SECTION_WEB, "web files owner");
-
- config_move(CONFIG_SECTION_GLOBAL, "web files group",
- CONFIG_SECTION_WEB, "web files group");
-
- config_move(CONFIG_SECTION_BACKEND, "opentsdb host tags",
- CONFIG_SECTION_BACKEND, "host tags");
-}
-
-static void get_netdata_configured_variables() {
- backwards_compatible_config();
-
- // ------------------------------------------------------------------------
- // get the hostname
-
- char buf[HOSTNAME_MAX + 1];
- if(gethostname(buf, HOSTNAME_MAX) == -1)
- error("Cannot get machine hostname.");
-
- netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf);
- debug(D_OPTIONS, "hostname set to '%s'", netdata_configured_hostname);
-
- // ------------------------------------------------------------------------
- // get default database size
-
- default_rrd_history_entries = (int) config_get_number(CONFIG_SECTION_GLOBAL, "history", align_entries_to_pagesize(default_rrd_memory_mode, RRD_DEFAULT_HISTORY_ENTRIES));
-
- long h = align_entries_to_pagesize(default_rrd_memory_mode, default_rrd_history_entries);
- if(h != default_rrd_history_entries) {
- config_set_number(CONFIG_SECTION_GLOBAL, "history", h);
- default_rrd_history_entries = (int)h;
- }
-
- if(default_rrd_history_entries < 5 || default_rrd_history_entries > RRD_HISTORY_ENTRIES_MAX) {
- error("Invalid history entries %d given. Defaulting to %d.", default_rrd_history_entries, RRD_DEFAULT_HISTORY_ENTRIES);
- default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES;
- }
-
- // ------------------------------------------------------------------------
- // get default database update frequency
-
- default_rrd_update_every = (int) config_get_number(CONFIG_SECTION_GLOBAL, "update every", UPDATE_EVERY);
- if(default_rrd_update_every < 1 || default_rrd_update_every > 600) {
- error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", default_rrd_update_every, UPDATE_EVERY_MAX);
- default_rrd_update_every = UPDATE_EVERY;
- }
-
- // ------------------------------------------------------------------------
- // get system paths
-
- netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR);
- netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR);
- netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR);
- netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR);
- netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR);
- netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR);
-
- {
- char plugins_dirs[(FILENAME_MAX * 2) + 1];
- snprintfz(plugins_dirs, FILENAME_MAX * 2, "\"%s\" \"%s/custom-plugins.d\"", PLUGINS_DIR, CONFIG_DIR);
- netdata_configured_plugins_dir_base = strdupz(config_get(CONFIG_SECTION_GLOBAL, "plugins directory", plugins_dirs));
- quoted_strings_splitter(netdata_configured_plugins_dir_base, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace);
- netdata_configured_plugins_dir = plugin_directories[0];
- }
-
- // ------------------------------------------------------------------------
- // get default memory mode for the database
-
- default_rrd_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_GLOBAL, "memory mode", rrd_memory_mode_name(default_rrd_memory_mode)));
-
- // ------------------------------------------------------------------------
-
- netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", "");
-
- // --------------------------------------------------------------------
- // get KSM settings
-
-#ifdef MADV_MERGEABLE
- enable_ksm = config_get_boolean(CONFIG_SECTION_GLOBAL, "memory deduplication (ksm)", enable_ksm);
-#endif
-
- // --------------------------------------------------------------------
- // get various system parameters
-
- get_system_HZ();
- get_system_cpus();
- get_system_pid_max();
-}
-
-static void get_system_timezone(void) {
- // avoid flood calls to stat(/etc/localtime)
- // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
- const char *tz = getenv("TZ");
- if(!tz || !*tz)
- setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0);
-
- char buffer[FILENAME_MAX + 1] = "";
- const char *timezone = NULL;
- ssize_t ret;
-
- // use the TZ variable
- if(tz && *tz && *tz != ':') {
- timezone = tz;
- // info("TIMEZONE: using TZ variable '%s'", timezone);
- }
-
- // use the contents of /etc/timezone
- if(!timezone && !read_file("/etc/timezone", buffer, FILENAME_MAX)) {
- timezone = buffer;
- // info("TIMEZONE: using the contents of /etc/timezone: '%s'", timezone);
- }
-
- // read the link /etc/localtime
- if(!timezone) {
- ret = readlink("/etc/localtime", buffer, FILENAME_MAX);
-
- if(ret > 0) {
- buffer[ret] = '\0';
-
- char *cmp = "/usr/share/zoneinfo/";
- size_t cmp_len = strlen(cmp);
-
- char *s = strstr(buffer, cmp);
- if (s && s[cmp_len]) {
- timezone = &s[cmp_len];
- // info("TIMEZONE: using the link of /etc/localtime: '%s'", timezone);
- }
- }
- else
- buffer[0] = '\0';
- }
-
- // find the timezone from strftime()
- if(!timezone) {
- time_t t;
- struct tm *tmp, tmbuf;
-
- t = now_realtime_sec();
- tmp = localtime_r(&t, &tmbuf);
-
- if (tmp != NULL) {
- if(strftime(buffer, FILENAME_MAX, "%Z", tmp) == 0)
- buffer[0] = '\0';
- else {
- buffer[FILENAME_MAX] = '\0';
- timezone = buffer;
- // info("TIMEZONE: using strftime(): '%s'", timezone);
- }
- }
- }
-
- if(timezone && *timezone) {
- // make sure it does not have illegal characters
- // info("TIMEZONE: fixing '%s'", timezone);
-
- size_t len = strlen(timezone);
- char tmp[len + 1];
- char *d = tmp;
- *d = '\0';
-
- while(*timezone) {
- if(isalnum(*timezone) || *timezone == '_' || *timezone == '/')
- *d++ = *timezone++;
- else
- timezone++;
- }
- *d = '\0';
- strncpyz(buffer, tmp, len);
- timezone = buffer;
- // info("TIMEZONE: fixed as '%s'", timezone);
- }
-
- if(!timezone || !*timezone)
- timezone = "unknown";
-
- netdata_configured_timezone = config_get(CONFIG_SECTION_GLOBAL, "timezone", timezone);
-}
-
-void set_global_environment() {
- {
- char b[16];
- snprintfz(b, 15, "%d", default_rrd_update_every);
- setenv("NETDATA_UPDATE_EVERY", b, 1);
- }
-
- setenv("NETDATA_HOSTNAME" , netdata_configured_hostname, 1);
- setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_config_dir), 1);
- setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_plugins_dir), 1);
- setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1);
- setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1);
- setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1);
- setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1);
- setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1);
- setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1);
-
- get_system_timezone();
-
- // set the path we need
- char path[1024 + 1], *p = getenv("PATH");
- if(!p) p = "/bin:/usr/bin";
- snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin");
- setenv("PATH", config_get(CONFIG_SECTION_PLUGINS, "PATH environment variable", path), 1);
-
- // python options
- p = getenv("PYTHONPATH");
- if(!p) p = "";
- setenv("PYTHONPATH", config_get(CONFIG_SECTION_PLUGINS, "PYTHONPATH environment variable", p), 1);
-
- // disable buffering for python plugins
- setenv("PYTHONUNBUFFERED", "1", 1);
-
- // switch to standard locale for plugins
- setenv("LC_ALL", "C", 1);
-}
-
-int main(int argc, char **argv) {
- int i;
- int config_loaded = 0;
- int dont_fork = 0;
- size_t default_stacksize;
-
- // set the name for logging
- program_name = "netdata";
-
- // parse depercated options
- // TODO: Remove this block with the next major release.
- {
- i = 1;
- while(i < argc) {
- if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) {
- strncpyz(pidfile, argv[i+1], FILENAME_MAX);
- fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]);
- remove_option(i, &argc, argv);
- }
- else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) {
- dont_fork = 1;
- fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]);
- remove_option(i, &argc, argv);
- }
- else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) {
- config_set(CONFIG_SECTION_GLOBAL, "host access prefix", argv[i+1]);
- fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]);
- remove_option(i, &argc, argv);
- }
- else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) {
- config_set(CONFIG_SECTION_GLOBAL, "history", argv[i+1]);
- fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]);
- remove_option(i, &argc, argv);
- }
- else i++;
- }
- }
-
- // parse options
- {
- int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
- char optstring[(num_opts * 2) + 1];
-
- int string_i = 0;
- for( i = 0; i < num_opts; i++ ) {
- optstring[string_i] = option_definitions[i].val;
- string_i++;
- if(option_definitions[i].arg_name) {
- optstring[string_i] = ':';
- string_i++;
- }
- }
- // terminate optstring
- optstring[string_i] ='\0';
- optstring[(num_opts *2)] ='\0';
-
- int opt;
- while( (opt = getopt(argc, argv, optstring)) != -1 ) {
- switch(opt) {
- case 'c':
- if(config_load(optarg, 1) != 1) {
- error("Cannot load configuration file %s.", optarg);
- return 1;
- }
- else {
- debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
- config_loaded = 1;
- }
- break;
- case 'D':
- dont_fork = 1;
- break;
- case 'h':
- return help(0);
- case 'i':
- config_set(CONFIG_SECTION_WEB, "bind to", optarg);
- break;
- case 'P':
- strncpy(pidfile, optarg, FILENAME_MAX);
- pidfile[FILENAME_MAX] = '\0';
- break;
- case 'p':
- config_set(CONFIG_SECTION_GLOBAL, "default port", optarg);
- break;
- case 's':
- config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg);
- break;
- case 't':
- config_set(CONFIG_SECTION_GLOBAL, "update every", optarg);
- break;
- case 'u':
- 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':
- {
- char* stacksize_string = "stacksize=";
- char* debug_flags_string = "debug_flags=";
-
- if(strcmp(optarg, "unittest") == 0) {
- if(unit_test_buffer()) return 1;
- if(unit_test_str2ld()) return 1;
- //default_rrd_update_every = 1;
- //default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
- //if(!config_loaded) config_load(NULL, 0);
- get_netdata_configured_variables();
- default_rrd_update_every = 1;
- default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
- default_health_enabled = 0;
- rrd_init("unittest");
- default_rrdpush_enabled = 0;
- if(run_all_mockup_tests()) return 1;
- if(unit_test_storage()) return 1;
- fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
- return 0;
- }
- else if(strcmp(optarg, "simple-pattern") == 0) {
- if(optind + 2 > argc) {
- fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n"
- " Checks if 'pattern' matches the given 'string'.\n"
- " - 'pattern' can be one or more space separated words.\n"
- " - each 'word' can contain one or more asterisks.\n"
- " - words starting with '!' give negative matches.\n"
- " - words are processed left to right\n"
- "\n"
- "Examples:\n"
- "\n"
- " > match all veth interfaces, except veth0:\n"
- "\n"
- " -W simple-pattern '!veth0 veth*' 'veth12'\n"
- "\n"
- "\n"
- " > match all *.ext files directly in /path/:\n"
- " (this will not match *.ext files in a subdir of /path/)\n"
- "\n"
- " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
- "\n"
- );
- return 1;
- }
-
- const char *heystack = argv[optind];
- const char *needle = argv[optind + 1];
- size_t len = strlen(needle) + 1;
- char wildcarded[len];
-
- SIMPLE_PATTERN *p = simple_pattern_create(heystack, NULL, SIMPLE_PATTERN_EXACT);
- int ret = simple_pattern_matches_extract(p, needle, wildcarded, len);
- simple_pattern_free(p);
-
- if(ret) {
- fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", heystack, needle, wildcarded);
- return 0;
- }
- else {
- fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", heystack, needle, wildcarded);
- return 1;
- }
- }
- else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
- optarg += strlen(stacksize_string);
- config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg);
- }
- else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
- optarg += strlen(debug_flags_string);
- config_set(CONFIG_SECTION_GLOBAL, "debug flags", optarg);
- debug_flags = strtoull(optarg, NULL, 0);
- }
- else if(strcmp(optarg, "set") == 0) {
- if(optind + 3 > argc) {
- fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n"
- " Overwrites settings of netdata.conf.\n"
- "\n"
- " These options interact with: -c netdata.conf\n"
- " If -c netdata.conf is given on the command line,\n"
- " before -W set... the user may overwrite command\n"
- " line parameters at netdata.conf\n"
- " If -c netdata.conf is given after (or missing)\n"
- " -W set... the user cannot overwrite the command line\n"
- " parameters."
- "\n"
- );
- return 1;
- }
- const char *section = argv[optind];
- const char *key = argv[optind + 1];
- const char *value = argv[optind + 2];
- optind += 3;
-
- // set this one as the default
- // only if it is not already set in the config file
- // so the caller can use -c netdata.conf before or
- // after this parameter to prevent or allow overwriting
- // variables at netdata.conf
- config_set_default(section, key, value);
-
- // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
- }
- else if(strcmp(optarg, "get") == 0) {
- if(optind + 3 > argc) {
- fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n"
- " Prints settings of netdata.conf.\n"
- "\n"
- " These options interact with: -c netdata.conf\n"
- " -c netdata.conf has to be given before -W get.\n"
- "\n"
- );
- return 1;
- }
-
- if(!config_loaded) {
- fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
- config_load(NULL, 0);
- }
-
- backwards_compatible_config();
- get_netdata_configured_variables();
-
- const char *section = argv[optind];
- const char *key = argv[optind + 1];
- const char *def = argv[optind + 2];
- const char *value = config_get(section, key, def);
- printf("%s\n", value);
- return 0;
- }
- else {
- fprintf(stderr, "Unknown -W parameter '%s'\n", optarg);
- return help(1);
- }
- }
- break;
-
- default: /* ? */
- fprintf(stderr, "Unknown parameter '%c'\n", opt);
- return help(1);
- }
- }
- }
-
-#ifdef _SC_OPEN_MAX
- // close all open file descriptors, except the standard ones
- // the caller may have left open files (lxc-attach has this issue)
- {
- int fd;
- for(fd = (int) (sysconf(_SC_OPEN_MAX) - 1); fd > 2; fd--)
- if(fd_is_valid(fd)) close(fd);
- }
-#endif
-
- if(!config_loaded)
- config_load(NULL, 0);
-
- // ------------------------------------------------------------------------
- // initialize netdata
- {
- char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1");
- if(pmax && *pmax)
- setenv("MALLOC_ARENA_MAX", pmax, 1);
-
-#if defined(HAVE_C_MALLOPT)
- i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1);
- if(i > 0)
- mallopt(M_ARENA_MAX, 1);
-#endif
-
- // prepare configuration environment variables for the plugins
-
- get_netdata_configured_variables();
- set_global_environment();
-
- // work while we are cd into config_dir
- // to allow the plugins refer to their config
- // files using relative filenames
- if(chdir(netdata_configured_config_dir) == -1)
- fatal("Cannot cd to '%s'", netdata_configured_config_dir);
- }
-
- char *user = NULL;
-
- {
- // --------------------------------------------------------------------
- // get the debugging flags from the configuration file
-
- char *flags = config_get(CONFIG_SECTION_GLOBAL, "debug flags", "0x0000000000000000");
- setenv("NETDATA_DEBUG_FLAGS", flags, 1);
-
- debug_flags = strtoull(flags, NULL, 0);
- debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags);
-
- if(debug_flags != 0) {
- struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
- if(setrlimit(RLIMIT_CORE, &rl) != 0)
- error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
-
-#ifdef HAVE_SYS_PRCTL_H
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-#endif
- }
-
-
- // --------------------------------------------------------------------
- // get log filenames and settings
-
- log_init();
- error_log_limit_unlimited();
-
-
- // --------------------------------------------------------------------
- // load stream.conf
- {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir);
- appconfig_load(&stream_config, filename, 0);
- }
-
-
- // --------------------------------------------------------------------
- // setup process signals
-
- // block signals while initializing threads.
- // this causes the threads to block signals.
- signals_block();
-
- // setup the signals we want to use
- signals_init();
-
- // setup threads configs
- default_stacksize = netdata_threads_init();
-
-
- // --------------------------------------------------------------------
- // check which threads are enabled and initialize them
-
- for (i = 0; static_threads[i].name != NULL ; i++) {
- struct netdata_static_thread *st = &static_threads[i];
-
- if(st->config_name)
- st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled);
-
- if(st->enabled && st->init_routine)
- st->init_routine();
- }
-
-
- // --------------------------------------------------------------------
- // get the user we should run
-
- // IMPORTANT: this is required before web_files_uid()
- if(getuid() == 0) {
- user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER);
- }
- else {
- struct passwd *passwd = getpwuid(getuid());
- user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:"");
- }
-
- // --------------------------------------------------------------------
- // create the listening sockets
-
- web_client_api_v1_init();
- web_server_threading_selection();
-
- if(web_server_mode != WEB_SERVER_MODE_NONE)
- api_listen_sockets_setup();
- }
-
- // initialize the log files
- open_all_log_files();
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(debug_flags != 0) {
- struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
- if(setrlimit(RLIMIT_CORE, &rl) != 0)
- error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
-#ifdef HAVE_SYS_PRCTL_H
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-#endif
- }
-#endif /* NETDATA_INTERNAL_CHECKS */
-
- // get the max file limit
- if(getrlimit(RLIMIT_NOFILE, &rlimit_nofile) != 0)
- error("getrlimit(RLIMIT_NOFILE) failed");
- else
- info("resources control: allowed file descriptors: soft = %zu, max = %zu", rlimit_nofile.rlim_cur, rlimit_nofile.rlim_max);
-
- // fork, switch user, create pid file, set process priority
- if(become_daemon(dont_fork, user) == -1)
- fatal("Cannot daemonize myself.");
-
- info("netdata started on pid %d.", getpid());
-
- // IMPORTANT: these have to run once, while single threaded
- // but after we have switched user
- web_files_uid();
- web_files_gid();
-
- netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize));
-
- // ------------------------------------------------------------------------
- // initialize rrd, registry, health, rrdpush, etc.
-
- rrd_init(netdata_configured_hostname);
-
-
- // ------------------------------------------------------------------------
- // enable log flood protection
-
- error_log_limit_reset();
-
-
- // ------------------------------------------------------------------------
- // spawn the threads
-
- web_server_config_options();
-
- for (i = 0; static_threads[i].name != NULL ; i++) {
- struct netdata_static_thread *st = &static_threads[i];
-
- if(st->enabled) {
- st->thread = mallocz(sizeof(netdata_thread_t));
- debug(D_SYSTEM, "Starting thread %s.", st->name);
- netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
- }
- else debug(D_SYSTEM, "Not starting thread %s.", st->name);
- }
-
- info("netdata initialization completed. Enjoy real-time performance monitoring!");
-
-
- // ------------------------------------------------------------------------
- // unblock signals
-
- signals_unblock();
-
- // ------------------------------------------------------------------------
- // Handle signals
-
- signals_handle();
-
- // should never reach this point
- // but we need it for rpmlint #2752
- return 1;
-}
diff --git a/src/main.h b/src/main.h
deleted file mode 100644
index d29bf74e7..000000000
--- a/src/main.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef NETDATA_MAIN_H
-#define NETDATA_MAIN_H 1
-
-#define NETDATA_MAIN_THREAD_RUNNING CONFIG_BOOLEAN_YES
-#define NETDATA_MAIN_THREAD_EXITING (CONFIG_BOOLEAN_YES + 1)
-#define NETDATA_MAIN_THREAD_EXITED CONFIG_BOOLEAN_NO
-
-/**
- * This struct contains information about command line options.
- */
-struct option_def {
- /** The option character */
- const char val;
- /** The name of the long option. */
- const char *description;
- /** Short descripton what the option does */
- /** Name of the argument displayed in SYNOPSIS */
- const char *arg_name;
- /** Default value if not set */
- const char *default_value;
-};
-
-struct netdata_static_thread {
- char *name;
-
- char *config_section;
- char *config_name;
-
- volatile sig_atomic_t enabled;
-
- netdata_thread_t *thread;
-
- void (*init_routine) (void);
- void *(*start_routine) (void *);
-};
-
-extern void cancel_main_threads(void);
-extern int killpid(pid_t pid, int signal);
-extern void netdata_cleanup_and_exit(int ret) NORETURN;
-
-#endif /* NETDATA_MAIN_H */
diff --git a/src/plugin_checks.c b/src/plugin_checks.c
deleted file mode 100644
index b99b97d40..000000000
--- a/src/plugin_checks.c
+++ /dev/null
@@ -1,127 +0,0 @@
-#include "common.h"
-
-#ifdef NETDATA_INTERNAL_CHECKS
-
-static void checks_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *checks_main(void *ptr) {
- netdata_thread_cleanup_push(checks_main_cleanup, ptr);
-
- usec_t usec = 0, susec = localhost->rrd_update_every * USEC_PER_SEC, loop_usec = 0, total_susec = 0;
- struct timeval now, last, loop;
-
- RRDSET *check1, *check2, *check3, *apps_cpu = NULL;
-
- check1 = rrdset_create_localhost(
- "netdata"
- , "check1"
- , NULL
- , "netdata"
- , NULL
- , "Caller gives microseconds"
- , "a million !"
- , "netdata"
- , "checks"
- , 99999
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(check1, "absolute", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(check1, "incremental", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- check2 = rrdset_create_localhost(
- "netdata"
- , "check2"
- , NULL
- , "netdata"
- , NULL
- , "Netdata calcs microseconds"
- , "a million !"
- , "netdata"
- , "checks"
- , 99999
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
- rrddim_add(check2, "absolute", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(check2, "incremental", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- check3 = rrdset_create_localhost(
- "netdata"
- , "checkdt"
- , NULL
- , "netdata"
- , NULL
- , "Clock difference"
- , "microseconds diff"
- , "netdata"
- , "checks"
- , 99999
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
- rrddim_add(check3, "caller", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(check3, "netdata", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- now_realtime_timeval(&last);
- while(!netdata_exit) {
- usleep(susec);
-
- // find the time to sleep in order to wait exactly update_every seconds
- now_realtime_timeval(&now);
- loop_usec = dt_usec(&now, &last);
- usec = loop_usec - susec;
- debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec);
-
- if(usec < (localhost->rrd_update_every * USEC_PER_SEC / 2ULL)) susec = (localhost->rrd_update_every * USEC_PER_SEC) - usec;
- else susec = localhost->rrd_update_every * USEC_PER_SEC / 2ULL;
-
- // --------------------------------------------------------------------
- // Calculate loop time
-
- last.tv_sec = now.tv_sec;
- last.tv_usec = now.tv_usec;
- total_susec += loop_usec;
-
- // --------------------------------------------------------------------
- // check chart 1
-
- if(check1->counter_done) rrdset_next_usec(check1, loop_usec);
- rrddim_set(check1, "absolute", 1000000);
- rrddim_set(check1, "incremental", total_susec);
- rrdset_done(check1);
-
- // --------------------------------------------------------------------
- // check chart 2
-
- if(check2->counter_done) rrdset_next(check2);
- rrddim_set(check2, "absolute", 1000000);
- rrddim_set(check2, "incremental", total_susec);
- rrdset_done(check2);
-
- // --------------------------------------------------------------------
- // check chart 3
-
- if(!apps_cpu) apps_cpu = rrdset_find_localhost("apps.cpu");
- if(check3->counter_done) rrdset_next_usec(check3, loop_usec);
- now_realtime_timeval(&loop);
- rrddim_set(check3, "caller", (long long) dt_usec(&loop, &check1->last_collected_time));
- rrddim_set(check3, "netdata", (long long) dt_usec(&loop, &check2->last_collected_time));
- if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) dt_usec(&loop, &apps_cpu->last_collected_time));
- rrdset_done(check3);
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-#endif // NETDATA_INTERNAL_CHECKS
diff --git a/src/plugin_checks.h b/src/plugin_checks.h
deleted file mode 100644
index 05a40bea0..000000000
--- a/src/plugin_checks.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef NETDATA_PLUGIN_CHECKS_H
-#define NETDATA_PLUGIN_CHECKS_H 1
-
-#ifdef NETDATA_INTERNAL_CHECKS
-void *checks_main(void *ptr);
-#endif // NETDATA_INTERNAL_CHECKS
-
-#endif /* NETDATA_PLUGIN_PROC_H */
diff --git a/src/plugin_freebsd.c b/src/plugin_freebsd.c
deleted file mode 100644
index a0d3dc2ea..000000000
--- a/src/plugin_freebsd.c
+++ /dev/null
@@ -1,173 +0,0 @@
-#include "common.h"
-
-static struct freebsd_module {
- const char *name;
- const char *dim;
-
- int enabled;
-
- int (*func)(int update_every, usec_t dt);
- usec_t duration;
-
- RRDDIM *rd;
-
-} freebsd_modules[] = {
-
- // system metrics
- { .name = "kern.cp_time", .dim = "cp_time", .enabled = 1, .func = do_kern_cp_time },
- { .name = "vm.loadavg", .dim = "loadavg", .enabled = 1, .func = do_vm_loadavg },
- { .name = "system.ram", .dim = "system_ram", .enabled = 1, .func = do_system_ram },
- { .name = "vm.swap_info", .dim = "swap", .enabled = 1, .func = do_vm_swap_info },
- { .name = "vm.stats.vm.v_swappgs", .dim = "swap_io", .enabled = 1, .func = do_vm_stats_sys_v_swappgs },
- { .name = "vm.vmtotal", .dim = "vmtotal", .enabled = 1, .func = do_vm_vmtotal },
- { .name = "vm.stats.vm.v_forks", .dim = "forks", .enabled = 1, .func = do_vm_stats_sys_v_forks },
- { .name = "vm.stats.sys.v_swtch", .dim = "context_swtch", .enabled = 1, .func = do_vm_stats_sys_v_swtch },
- { .name = "hw.intrcnt", .dim = "hw_intr", .enabled = 1, .func = do_hw_intcnt },
- { .name = "vm.stats.sys.v_intr", .dim = "dev_intr", .enabled = 1, .func = do_vm_stats_sys_v_intr },
- { .name = "vm.stats.sys.v_soft", .dim = "soft_intr", .enabled = 1, .func = do_vm_stats_sys_v_soft },
- { .name = "net.isr", .dim = "net_isr", .enabled = 1, .func = do_net_isr },
- { .name = "kern.ipc.sem", .dim = "semaphores", .enabled = 1, .func = do_kern_ipc_sem },
- { .name = "kern.ipc.shm", .dim = "shared_memory", .enabled = 1, .func = do_kern_ipc_shm },
- { .name = "kern.ipc.msq", .dim = "message_queues", .enabled = 1, .func = do_kern_ipc_msq },
- { .name = "uptime", .dim = "uptime", .enabled = 1, .func = do_uptime },
-
- // memory metrics
- { .name = "vm.stats.vm.v_pgfaults", .dim = "pgfaults", .enabled = 1, .func = do_vm_stats_sys_v_pgfaults },
-
- // CPU metrics
- { .name = "kern.cp_times", .dim = "cp_times", .enabled = 1, .func = do_kern_cp_times },
- { .name = "dev.cpu.temperature", .dim = "cpu_temperature", .enabled = 1, .func = do_dev_cpu_temperature },
- { .name = "dev.cpu.0.freq", .dim = "cpu_frequency", .enabled = 1, .func = do_dev_cpu_0_freq },
-
- // disk metrics
- { .name = "kern.devstat", .dim = "kern_devstat", .enabled = 1, .func = do_kern_devstat },
- { .name = "getmntinfo", .dim = "getmntinfo", .enabled = 1, .func = do_getmntinfo },
-
- // network metrics
- { .name = "net.inet.tcp.states", .dim = "tcp_states", .enabled = 1, .func = do_net_inet_tcp_states },
- { .name = "net.inet.tcp.stats", .dim = "tcp_stats", .enabled = 1, .func = do_net_inet_tcp_stats },
- { .name = "net.inet.udp.stats", .dim = "udp_stats", .enabled = 1, .func = do_net_inet_udp_stats },
- { .name = "net.inet.icmp.stats", .dim = "icmp_stats", .enabled = 1, .func = do_net_inet_icmp_stats },
- { .name = "net.inet.ip.stats", .dim = "ip_stats", .enabled = 1, .func = do_net_inet_ip_stats },
- { .name = "net.inet6.ip6.stats", .dim = "ip6_stats", .enabled = 1, .func = do_net_inet6_ip6_stats },
- { .name = "net.inet6.icmp6.stats", .dim = "icmp6_stats", .enabled = 1, .func = do_net_inet6_icmp6_stats },
-
- // network interfaces metrics
- { .name = "getifaddrs", .dim = "getifaddrs", .enabled = 1, .func = do_getifaddrs },
-
- // ZFS metrics
- { .name = "kstat.zfs.misc.arcstats", .dim = "arcstats", .enabled = 1, .func = do_kstat_zfs_misc_arcstats },
- { .name = "kstat.zfs.misc.zio_trim", .dim = "trim", .enabled = 1, .func = do_kstat_zfs_misc_zio_trim },
-
- // ipfw metrics
- { .name = "ipfw", .dim = "ipfw", .enabled = 1, .func = do_ipfw },
-
- // the terminator of this array
- { .name = NULL, .dim = NULL, .enabled = 0, .func = NULL }
-};
-
-static void freebsd_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *freebsd_main(void *ptr) {
- netdata_thread_cleanup_push(freebsd_main_cleanup, ptr);
-
- int vdo_cpu_netdata = config_get_boolean("plugin:freebsd", "netdata server resources", 1);
-
- // initialize FreeBSD plugin
- if (freebsd_plugin_init())
- netdata_cleanup_and_exit(1);
-
- // check the enabled status for each module
- int i;
- for(i = 0 ; freebsd_modules[i].name ;i++) {
- struct freebsd_module *pm = &freebsd_modules[i];
-
- pm->enabled = config_get_boolean("plugin:freebsd", pm->name, pm->enabled);
- pm->duration = 0ULL;
- pm->rd = NULL;
- }
-
- usec_t step = localhost->rrd_update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- while(!netdata_exit) {
- usec_t hb_dt = heartbeat_next(&hb, step);
- usec_t duration = 0ULL;
-
- if(unlikely(netdata_exit)) break;
-
- // BEGIN -- the job to be done
-
- for(i = 0 ; freebsd_modules[i].name ;i++) {
- struct freebsd_module *pm = &freebsd_modules[i];
- if(unlikely(!pm->enabled)) continue;
-
- debug(D_PROCNETDEV_LOOP, "FREEBSD calling %s.", pm->name);
-
- pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt);
- pm->duration = heartbeat_dt_usec(&hb) - duration;
- duration += pm->duration;
-
- if(unlikely(netdata_exit)) break;
- }
-
- // END -- the job is done
-
- // --------------------------------------------------------------------
-
- if(vdo_cpu_netdata) {
- static RRDSET *st = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_find_bytype_localhost("netdata", "plugin_freebsd_modules");
-
- if(!st) {
- st = rrdset_create_localhost(
- "netdata"
- , "plugin_freebsd_modules"
- , NULL
- , "freebsd"
- , NULL
- , "NetData FreeBSD Plugin Modules Durations"
- , "milliseconds/run"
- , "netdata"
- , "stats"
- , 132001
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-
- for(i = 0 ; freebsd_modules[i].name ;i++) {
- struct freebsd_module *pm = &freebsd_modules[i];
- if(unlikely(!pm->enabled)) continue;
-
- pm->rd = rrddim_add(st, pm->dim, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- }
- }
- else rrdset_next(st);
-
- for(i = 0 ; freebsd_modules[i].name ;i++) {
- struct freebsd_module *pm = &freebsd_modules[i];
- if(unlikely(!pm->enabled)) continue;
-
- rrddim_set_by_pointer(st, pm->rd, pm->duration);
- }
- rrdset_done(st);
-
- global_statistics_charts();
- registry_statistics();
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/plugin_freebsd.h b/src/plugin_freebsd.h
deleted file mode 100644
index 0a6f40c15..000000000
--- a/src/plugin_freebsd.h
+++ /dev/null
@@ -1,130 +0,0 @@
-#ifndef NETDATA_PLUGIN_FREEBSD_H
-#define NETDATA_PLUGIN_FREEBSD_H 1
-
-#include <sys/sysctl.h>
-
-#define KILO_FACTOR 1024
-#define MEGA_FACTOR 1048576 // 1024 * 1024
-#define GIGA_FACTOR 1073741824 // 1024 * 1024 * 1024
-
-#define MAX_INT_DIGITS 10 // maximum number of digits for int
-
-void *freebsd_main(void *ptr);
-
-extern int freebsd_plugin_init();
-
-extern int do_vm_loadavg(int update_every, usec_t dt);
-extern int do_vm_vmtotal(int update_every, usec_t dt);
-extern int do_kern_cp_time(int update_every, usec_t dt);
-extern int do_kern_cp_times(int update_every, usec_t dt);
-extern int do_dev_cpu_temperature(int update_every, usec_t dt);
-extern int do_dev_cpu_0_freq(int update_every, usec_t dt);
-extern int do_hw_intcnt(int update_every, usec_t dt);
-extern int do_vm_stats_sys_v_intr(int update_every, usec_t dt);
-extern int do_vm_stats_sys_v_soft(int update_every, usec_t dt);
-extern int do_vm_stats_sys_v_swtch(int update_every, usec_t dt);
-extern int do_vm_stats_sys_v_forks(int update_every, usec_t dt);
-extern int do_vm_swap_info(int update_every, usec_t dt);
-extern int do_system_ram(int update_every, usec_t dt);
-extern int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt);
-extern int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt);
-extern int do_kern_ipc_sem(int update_every, usec_t dt);
-extern int do_kern_ipc_shm(int update_every, usec_t dt);
-extern int do_kern_ipc_msq(int update_every, usec_t dt);
-extern int do_uptime(int update_every, usec_t dt);
-extern int do_net_isr(int update_every, usec_t dt);
-extern int do_net_inet_tcp_states(int update_every, usec_t dt);
-extern int do_net_inet_tcp_stats(int update_every, usec_t dt);
-extern int do_net_inet_udp_stats(int update_every, usec_t dt);
-extern int do_net_inet_icmp_stats(int update_every, usec_t dt);
-extern int do_net_inet_ip_stats(int update_every, usec_t dt);
-extern int do_net_inet6_ip6_stats(int update_every, usec_t dt);
-extern int do_net_inet6_icmp6_stats(int update_every, usec_t dt);
-extern int do_getifaddrs(int update_every, usec_t dt);
-extern int do_getmntinfo(int update_every, usec_t dt);
-extern int do_kern_devstat(int update_every, usec_t dt);
-extern int do_kstat_zfs_misc_arcstats(int update_every, usec_t dt);
-extern int do_kstat_zfs_misc_zio_trim(int update_every, usec_t dt);
-extern int do_ipfw(int update_every, usec_t dt);
-
-#define GETSYSCTL_MIB(name, mib) getsysctl_mib(name, mib, sizeof(mib)/sizeof(int))
-
-static inline int getsysctl_mib(const char *name, int *mib, size_t len)
-{
- size_t nlen = len;
-
- if (unlikely(sysctlnametomib(name, mib, &nlen) == -1)) {
- error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
- return 1;
- }
- if (unlikely(nlen != len)) {
- error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
- return 1;
- }
- return 0;
-}
-
-#define GETSYSCTL_SIMPLE(name, mib, var) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), &(var), sizeof(var))
-#define GETSYSCTL_WSIZE(name, mib, var, size) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), var, size)
-
-static inline int getsysctl_simple(const char *name, int *mib, size_t miblen, void *ptr, size_t len)
-{
- size_t nlen = len;
-
- if (unlikely(!mib[0]))
- if (unlikely(getsysctl_mib(name, mib, miblen)))
- return 1;
-
- if (unlikely(sysctl(mib, miblen, ptr, &nlen, NULL, 0) == -1)) {
- error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
- return 1;
- }
- if (unlikely(nlen != len)) {
- error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
- return 1;
- }
-
- return 0;
-}
-
-#define GETSYSCTL_SIZE(name, mib, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), NULL, &(size))
-#define GETSYSCTL(name, mib, var, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), &(var), &(size))
-
-static inline int getsysctl(const char *name, int *mib, size_t miblen, void *ptr, size_t *len)
-{
- size_t nlen = *len;
-
- if (unlikely(!mib[0]))
- if (unlikely(getsysctl_mib(name, mib, miblen)))
- return 1;
-
- if (unlikely(sysctl(mib, miblen, ptr, len, NULL, 0) == -1)) {
- error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
- return 1;
- }
- if (unlikely(ptr != NULL && nlen != *len)) {
- error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)*len, (unsigned long)nlen);
- return 1;
- }
-
- return 0;
-}
-
-#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var))
-
-static inline int getsysctl_by_name(const char *name, void *ptr, size_t len)
-{
- size_t nlen = len;
-
- if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
- error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
- return 1;
- }
- if (unlikely(nlen != len)) {
- error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
- return 1;
- }
- return 0;
-}
-
-#endif /* NETDATA_PLUGIN_FREEBSD_H */
diff --git a/src/plugin_idlejitter.c b/src/plugin_idlejitter.c
deleted file mode 100644
index 77bd95d55..000000000
--- a/src/plugin_idlejitter.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "common.h"
-
-#define CPU_IDLEJITTER_SLEEP_TIME_MS 20
-
-static void cpuidlejitter_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *cpuidlejitter_main(void *ptr) {
- netdata_thread_cleanup_push(cpuidlejitter_main_cleanup, ptr);
-
- usec_t sleep_ut = config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS) * USEC_PER_MS;
- if(sleep_ut <= 0) {
- config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
- sleep_ut = CPU_IDLEJITTER_SLEEP_TIME_MS * USEC_PER_MS;
- }
-
- RRDSET *st = rrdset_create_localhost(
- "system"
- , "idlejitter"
- , NULL
- , "idlejitter"
- , NULL
- , "CPU Idle Jitter"
- , "microseconds lost/s"
- , "idlejitter"
- , NULL
- , 800
- , localhost->rrd_update_every
- , RRDSET_TYPE_AREA
- );
- RRDDIM *rd_min = rrddim_add(st, "min", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_max = rrddim_add(st, "max", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_avg = rrddim_add(st, "average", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- usec_t update_every_ut = localhost->rrd_update_every * USEC_PER_SEC;
- struct timeval before, after;
- unsigned long long counter;
-
- for(counter = 0; 1 ;counter++) {
- int iterations = 0;
- usec_t error_total = 0,
- error_min = 0,
- error_max = 0,
- elapsed = 0;
-
- if(netdata_exit) break;
-
- while(elapsed < update_every_ut) {
- now_monotonic_timeval(&before);
- sleep_usec(sleep_ut);
- now_monotonic_timeval(&after);
-
- usec_t dt = dt_usec(&after, &before);
- elapsed += dt;
-
- usec_t error = dt - sleep_ut;
- error_total += error;
-
- if(unlikely(!iterations))
- error_min = error;
- else if(error < error_min)
- error_min = error;
-
- if(error > error_max)
- error_max = error;
-
- iterations++;
- }
-
- if(netdata_exit) break;
-
- if(iterations) {
- if (likely(counter)) rrdset_next(st);
- rrddim_set_by_pointer(st, rd_min, error_min);
- rrddim_set_by_pointer(st, rd_max, error_max);
- rrddim_set_by_pointer(st, rd_avg, error_total / iterations);
- rrdset_done(st);
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
diff --git a/src/plugin_idlejitter.h b/src/plugin_idlejitter.h
deleted file mode 100644
index dc82f052f..000000000
--- a/src/plugin_idlejitter.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef NETDATA_PLUGIN_IDLEJITTER_H
-#define NETDATA_PLUGIN_IDLEJITTER_H 1
-
-extern void *cpuidlejitter_main(void *ptr);
-
-#endif /* NETDATA_PLUGIN_IDLEJITTER_H */
diff --git a/src/plugin_macos.c b/src/plugin_macos.c
deleted file mode 100644
index 6ac3d25d1..000000000
--- a/src/plugin_macos.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "common.h"
-
-static void macos_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *macos_main(void *ptr) {
- netdata_thread_cleanup_push(macos_main_cleanup, ptr);
-
- // when ZERO, attempt to do it
- int vdo_cpu_netdata = !config_get_boolean("plugin:macos", "netdata server resources", 1);
- int vdo_macos_sysctl = !config_get_boolean("plugin:macos", "sysctl", 1);
- int vdo_macos_mach_smi = !config_get_boolean("plugin:macos", "mach system management interface", 1);
- int vdo_macos_iokit = !config_get_boolean("plugin:macos", "iokit", 1);
-
- // keep track of the time each module was called
- unsigned long long sutime_macos_sysctl = 0ULL;
- unsigned long long sutime_macos_mach_smi = 0ULL;
- unsigned long long sutime_macos_iokit = 0ULL;
-
- usec_t step = localhost->rrd_update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- while(!netdata_exit) {
- usec_t hb_dt = heartbeat_next(&hb, step);
-
- if(unlikely(netdata_exit)) break;
-
- // BEGIN -- the job to be done
-
- if(!vdo_macos_sysctl) {
- debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_sysctl().");
- vdo_macos_sysctl = do_macos_sysctl(localhost->rrd_update_every, hb_dt);
- }
- if(unlikely(netdata_exit)) break;
-
- if(!vdo_macos_mach_smi) {
- debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_mach_smi().");
- vdo_macos_mach_smi = do_macos_mach_smi(localhost->rrd_update_every, hb_dt);
- }
- if(unlikely(netdata_exit)) break;
-
- if(!vdo_macos_iokit) {
- debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_iokit().");
- vdo_macos_iokit = do_macos_iokit(localhost->rrd_update_every, hb_dt);
- }
- if(unlikely(netdata_exit)) break;
-
- // END -- the job is done
-
- // --------------------------------------------------------------------
-
- if(!vdo_cpu_netdata) {
- global_statistics_charts();
- registry_statistics();
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/plugin_macos.h b/src/plugin_macos.h
deleted file mode 100644
index 6ccf3e861..000000000
--- a/src/plugin_macos.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef NETDATA_PLUGIN_MACOS_H
-#define NETDATA_PLUGIN_MACOS_H 1
-
-void *macos_main(void *ptr);
-
-#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var))
-
-extern int getsysctl_by_name(const char *name, void *ptr, size_t len);
-
-extern int do_macos_sysctl(int update_every, usec_t dt);
-extern int do_macos_mach_smi(int update_every, usec_t dt);
-extern int do_macos_iokit(int update_every, usec_t dt);
-
-#endif /* NETDATA_PLUGIN_MACOS_H */
diff --git a/src/plugin_nfacct.c b/src/plugin_nfacct.c
deleted file mode 100644
index 02815ef04..000000000
--- a/src/plugin_nfacct.c
+++ /dev/null
@@ -1,819 +0,0 @@
-#include "common.h"
-
-#ifdef INTERNAL_PLUGIN_NFACCT
-
-#ifdef HAVE_LIBMNL
-#include <libmnl/libmnl.h>
-
-static inline size_t mnl_buffer_size() {
- long s = MNL_SOCKET_BUFFER_SIZE;
- if(s <= 0) return 8192;
- return (size_t)s;
-}
-
-// ----------------------------------------------------------------------------
-// DO_NFSTAT - collect netfilter connection tracker statistics via netlink
-// example: https://github.com/formorer/pkg-conntrack-tools/blob/master/src/conntrack.c
-
-#ifdef HAVE_LINUX_NETFILTER_NFNETLINK_CONNTRACK_H
-#define DO_NFSTAT 1
-
-#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
-#define RRD_TYPE_NET_STAT_CONNTRACK "netlink" // FIXME: should be "conntrack" when merged with the /proc plugin
-
-#include <linux/netfilter/nfnetlink_conntrack.h>
-
-static struct {
- int update_every;
- char *buf;
- size_t buf_size;
- struct mnl_socket *mnl;
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfh;
- unsigned int seq;
- uint32_t portid;
-
- struct nlattr *tb[CTA_STATS_MAX+1];
- const char *attr2name[CTA_STATS_MAX+1];
- kernel_uint_t metrics[CTA_STATS_MAX+1];
-
- struct nlattr *tb_exp[CTA_STATS_EXP_MAX+1];
- const char *attr2name_exp[CTA_STATS_EXP_MAX+1];
- kernel_uint_t metrics_exp[CTA_STATS_EXP_MAX+1];
-} nfstat_root = {
- .update_every = 1,
- .buf = NULL,
- .buf_size = 0,
- .mnl = NULL,
- .nlh = NULL,
- .nfh = NULL,
- .seq = 0,
- .portid = 0,
- .tb = {},
- .attr2name = {
- [CTA_STATS_SEARCHED] = "searched",
- [CTA_STATS_FOUND] = "found",
- [CTA_STATS_NEW] = "new",
- [CTA_STATS_INVALID] = "invalid",
- [CTA_STATS_IGNORE] = "ignore",
- [CTA_STATS_DELETE] = "delete",
- [CTA_STATS_DELETE_LIST] = "delete_list",
- [CTA_STATS_INSERT] = "insert",
- [CTA_STATS_INSERT_FAILED] = "insert_failed",
- [CTA_STATS_DROP] = "drop",
- [CTA_STATS_EARLY_DROP] = "early_drop",
- [CTA_STATS_ERROR] = "icmp_error",
- [CTA_STATS_SEARCH_RESTART] = "search_restart",
- },
- .metrics = {},
- .tb_exp = {},
- .attr2name_exp = {
- [CTA_STATS_EXP_NEW] = "new",
- [CTA_STATS_EXP_CREATE] = "created",
- [CTA_STATS_EXP_DELETE] = "deleted",
- },
- .metrics_exp = {}
-};
-
-
-static int nfstat_init(int update_every) {
- nfstat_root.update_every = update_every;
-
- nfstat_root.buf_size = mnl_buffer_size();
- nfstat_root.buf = mallocz(nfstat_root.buf_size);
-
- nfstat_root.mnl = mnl_socket_open(NETLINK_NETFILTER);
- if(!nfstat_root.mnl) {
- error("NFSTAT: mnl_socket_open() failed");
- return 1;
- }
-
- nfstat_root.seq = (unsigned int)now_realtime_sec() - 1;
-
- if(mnl_socket_bind(nfstat_root.mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
- error("NFSTAT: mnl_socket_bind() failed");
- return 1;
- }
- nfstat_root.portid = mnl_socket_get_portid(nfstat_root.mnl);
-
- return 0;
-}
-
-static void nfstat_cleanup() {
- if(nfstat_root.mnl) {
- mnl_socket_close(nfstat_root.mnl);
- nfstat_root.mnl = NULL;
- }
-
- freez(nfstat_root.buf);
- nfstat_root.buf = NULL;
- nfstat_root.buf_size = 0;
-}
-
-static struct nlmsghdr * nfct_mnl_nlmsghdr_put(char *buf, uint16_t subsys, uint16_t type, uint8_t family, uint32_t seq) {
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfh;
-
- nlh = mnl_nlmsg_put_header(buf);
- nlh->nlmsg_type = (subsys << 8) | type;
- nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
- nlh->nlmsg_seq = seq;
-
- nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
- nfh->nfgen_family = family;
- nfh->version = NFNETLINK_V0;
- nfh->res_id = 0;
-
- return nlh;
-}
-
-static int nfct_stats_attr_cb(const struct nlattr *attr, void *data) {
- const struct nlattr **tb = data;
- int type = mnl_attr_get_type(attr);
-
- if (mnl_attr_type_valid(attr, CTA_STATS_MAX) < 0)
- return MNL_CB_OK;
-
- if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
- error("NFSTAT: mnl_attr_validate() failed");
- return MNL_CB_ERROR;
- }
-
- tb[type] = attr;
- return MNL_CB_OK;
-}
-
-static int nfstat_callback(const struct nlmsghdr *nlh, void *data) {
- (void)data;
-
- struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
-
- mnl_attr_parse(nlh, sizeof(*nfg), nfct_stats_attr_cb, nfstat_root.tb);
-
- // printf("cpu=%-4u\t", ntohs(nfg->res_id));
-
- int i;
- // add the metrics of this CPU into the metrics
- for (i = 0; i < CTA_STATS_MAX+1; i++) {
- if (nfstat_root.tb[i]) {
- // printf("%s=%u ", nfstat_root.attr2name[i], ntohl(mnl_attr_get_u32(nfstat_root.tb[i])));
- nfstat_root.metrics[i] += ntohl(mnl_attr_get_u32(nfstat_root.tb[i]));
- }
- }
- // printf("\n");
-
- return MNL_CB_OK;
-}
-
-static int nfstat_collect_conntrack() {
- // zero all metrics - we will sum the metrics of all CPUs later
- int i;
- for (i = 0; i < CTA_STATS_MAX+1; i++)
- nfstat_root.metrics[i] = 0;
-
- // prepare the request
- nfstat_root.nlh = nfct_mnl_nlmsghdr_put(nfstat_root.buf, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS_CPU, AF_UNSPEC, nfstat_root.seq);
-
- // send the request
- if(mnl_socket_sendto(nfstat_root.mnl, nfstat_root.nlh, nfstat_root.nlh->nlmsg_len) < 0) {
- error("NFSTAT: mnl_socket_sendto() failed");
- return 1;
- }
-
- // get the reply
- ssize_t ret;
- while ((ret = mnl_socket_recvfrom(nfstat_root.mnl, nfstat_root.buf, nfstat_root.buf_size)) > 0) {
- if(mnl_cb_run(
- nfstat_root.buf
- , (size_t)ret
- , nfstat_root.nlh->nlmsg_seq
- , nfstat_root.portid
- , nfstat_callback
- , NULL
- ) <= MNL_CB_STOP)
- break;
- }
-
- // verify we run without issues
- if (ret == -1) {
- error("NFSTAT: error communicating with kernel. This plugin can only work when netdata runs as root.");
- return 1;
- }
-
- return 0;
-}
-
-static int nfexp_stats_attr_cb(const struct nlattr *attr, void *data)
-{
- const struct nlattr **tb = data;
- int type = mnl_attr_get_type(attr);
-
- if (mnl_attr_type_valid(attr, CTA_STATS_EXP_MAX) < 0)
- return MNL_CB_OK;
-
- if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
- error("NFSTAT EXP: mnl_attr_validate() failed");
- return MNL_CB_ERROR;
- }
-
- tb[type] = attr;
- return MNL_CB_OK;
-}
-
-static int nfstat_callback_exp(const struct nlmsghdr *nlh, void *data) {
- (void)data;
-
- struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
-
- mnl_attr_parse(nlh, sizeof(*nfg), nfexp_stats_attr_cb, nfstat_root.tb_exp);
-
- int i;
- for (i = 0; i < CTA_STATS_EXP_MAX+1; i++) {
- if (nfstat_root.tb_exp[i]) {
- nfstat_root.metrics_exp[i] += ntohl(mnl_attr_get_u32(nfstat_root.tb_exp[i]));
- }
- }
-
- return MNL_CB_OK;
-}
-
-static int nfstat_collect_conntrack_expectations() {
- // zero all metrics - we will sum the metrics of all CPUs later
- int i;
- for (i = 0; i < CTA_STATS_EXP_MAX+1; i++)
- nfstat_root.metrics_exp[i] = 0;
-
- // prepare the request
- nfstat_root.nlh = nfct_mnl_nlmsghdr_put(nfstat_root.buf, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET_STATS_CPU, AF_UNSPEC, nfstat_root.seq);
-
- // send the request
- if(mnl_socket_sendto(nfstat_root.mnl, nfstat_root.nlh, nfstat_root.nlh->nlmsg_len) < 0) {
- error("NFSTAT: mnl_socket_sendto() failed");
- return 1;
- }
-
- // get the reply
- ssize_t ret;
- while ((ret = mnl_socket_recvfrom(nfstat_root.mnl, nfstat_root.buf, nfstat_root.buf_size)) > 0) {
- if(mnl_cb_run(
- nfstat_root.buf
- , (size_t)ret
- , nfstat_root.nlh->nlmsg_seq
- , nfstat_root.portid
- , nfstat_callback_exp
- , NULL
- ) <= MNL_CB_STOP)
- break;
- }
-
- // verify we run without issues
- if (ret == -1) {
- error("NFSTAT: error communicating with kernel. This plugin can only work when netdata runs as root.");
- return 1;
- }
-
- return 0;
-}
-
-static int nfstat_collect() {
- nfstat_root.seq++;
-
- if(nfstat_collect_conntrack())
- return 1;
-
- if(nfstat_collect_conntrack_expectations())
- return 1;
-
- return 0;
-}
-
-static void nfstat_send_metrics() {
-
- {
- static RRDSET *st_new = NULL;
- static RRDDIM *rd_new = NULL, *rd_ignore = NULL, *rd_invalid = NULL;
-
- if(!st_new) {
- st_new = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_new"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker New Connections"
- , "connections/s"
- , "nfacct"
- , NULL
- , 3001
- , nfstat_root.update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_new = rrddim_add(st_new, nfstat_root.attr2name[CTA_STATS_NEW], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ignore = rrddim_add(st_new, nfstat_root.attr2name[CTA_STATS_IGNORE], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_invalid = rrddim_add(st_new, nfstat_root.attr2name[CTA_STATS_INVALID], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_new);
-
- rrddim_set_by_pointer(st_new, rd_new, (collected_number) nfstat_root.metrics[CTA_STATS_NEW]);
- rrddim_set_by_pointer(st_new, rd_ignore, (collected_number) nfstat_root.metrics[CTA_STATS_IGNORE]);
- rrddim_set_by_pointer(st_new, rd_invalid, (collected_number) nfstat_root.metrics[CTA_STATS_INVALID]);
-
- rrdset_done(st_new);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_changes = NULL;
- static RRDDIM *rd_inserted = NULL, *rd_deleted = NULL, *rd_delete_list = NULL;
-
- if(!st_changes) {
- st_changes = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_changes"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Changes"
- , "changes/s"
- , "nfacct"
- , NULL
- , 3002
- , nfstat_root.update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_changes, RRDSET_FLAG_DETAIL);
-
- rd_inserted = rrddim_add(st_changes, nfstat_root.attr2name[CTA_STATS_INSERT], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_deleted = rrddim_add(st_changes, nfstat_root.attr2name[CTA_STATS_DELETE], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_delete_list = rrddim_add(st_changes, nfstat_root.attr2name[CTA_STATS_DELETE_LIST], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_changes);
-
- rrddim_set_by_pointer(st_changes, rd_inserted, (collected_number) nfstat_root.metrics[CTA_STATS_INSERT]);
- rrddim_set_by_pointer(st_changes, rd_deleted, (collected_number) nfstat_root.metrics[CTA_STATS_DELETE]);
- rrddim_set_by_pointer(st_changes, rd_delete_list, (collected_number) nfstat_root.metrics[CTA_STATS_DELETE_LIST]);
-
- rrdset_done(st_changes);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_search = NULL;
- static RRDDIM *rd_searched = NULL, *rd_restarted = NULL, *rd_found = NULL;
-
- if(!st_search) {
- st_search = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_search"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Searches"
- , "searches/s"
- , "nfacct"
- , NULL
- , 3010
- , nfstat_root.update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_search, RRDSET_FLAG_DETAIL);
-
- rd_searched = rrddim_add(st_search, nfstat_root.attr2name[CTA_STATS_SEARCHED], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_restarted = rrddim_add(st_search, nfstat_root.attr2name[CTA_STATS_SEARCH_RESTART], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_found = rrddim_add(st_search, nfstat_root.attr2name[CTA_STATS_FOUND], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_search);
-
- rrddim_set_by_pointer(st_search, rd_searched, (collected_number) nfstat_root.metrics[CTA_STATS_SEARCHED]);
- rrddim_set_by_pointer(st_search, rd_restarted, (collected_number) nfstat_root.metrics[CTA_STATS_SEARCH_RESTART]);
- rrddim_set_by_pointer(st_search, rd_found, (collected_number) nfstat_root.metrics[CTA_STATS_FOUND]);
-
- rrdset_done(st_search);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_errors = NULL;
- static RRDDIM *rd_error = NULL, *rd_insert_failed = NULL, *rd_drop = NULL, *rd_early_drop = NULL;
-
- if(!st_errors) {
- st_errors = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_errors"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Errors"
- , "events/s"
- , "nfacct"
- , NULL
- , 3005
- , nfstat_root.update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_errors, RRDSET_FLAG_DETAIL);
-
- rd_error = rrddim_add(st_errors, nfstat_root.attr2name[CTA_STATS_ERROR], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_insert_failed = rrddim_add(st_errors, nfstat_root.attr2name[CTA_STATS_INSERT_FAILED], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_drop = rrddim_add(st_errors, nfstat_root.attr2name[CTA_STATS_DROP], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_early_drop = rrddim_add(st_errors, nfstat_root.attr2name[CTA_STATS_EARLY_DROP], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_errors);
-
- rrddim_set_by_pointer(st_errors, rd_error, (collected_number) nfstat_root.metrics[CTA_STATS_ERROR]);
- rrddim_set_by_pointer(st_errors, rd_insert_failed, (collected_number) nfstat_root.metrics[CTA_STATS_INSERT_FAILED]);
- rrddim_set_by_pointer(st_errors, rd_drop, (collected_number) nfstat_root.metrics[CTA_STATS_DROP]);
- rrddim_set_by_pointer(st_errors, rd_early_drop, (collected_number) nfstat_root.metrics[CTA_STATS_EARLY_DROP]);
-
- rrdset_done(st_errors);
- }
-
- // ----------------------------------------------------------------
-
- {
- static RRDSET *st_expect = NULL;
- static RRDDIM *rd_new = NULL, *rd_created = NULL, *rd_deleted = NULL;
-
- if(!st_expect) {
- st_expect = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_expect"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Expectations"
- , "expectations/s"
- , "nfacct"
- , NULL
- , 3003
- , nfstat_root.update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_expect, RRDSET_FLAG_DETAIL);
-
- rd_created = rrddim_add(st_expect, nfstat_root.attr2name_exp[CTA_STATS_EXP_CREATE], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_deleted = rrddim_add(st_expect, nfstat_root.attr2name_exp[CTA_STATS_EXP_DELETE], NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_new = rrddim_add(st_expect, nfstat_root.attr2name_exp[CTA_STATS_EXP_NEW], NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_expect);
-
- rrddim_set_by_pointer(st_expect, rd_created, (collected_number) nfstat_root.metrics_exp[CTA_STATS_EXP_CREATE]);
- rrddim_set_by_pointer(st_expect, rd_deleted, (collected_number) nfstat_root.metrics_exp[CTA_STATS_EXP_DELETE]);
- rrddim_set_by_pointer(st_expect, rd_new, (collected_number) nfstat_root.metrics_exp[CTA_STATS_EXP_NEW]);
-
- rrdset_done(st_expect);
- }
-
-}
-
-#endif // HAVE_LINUX_NETFILTER_NFNETLINK_CONNTRACK_H
-
-
-// ----------------------------------------------------------------------------
-// DO_NFACCT - collect netfilter accounting statistics via netlink
-
-#ifdef HAVE_LIBNETFILTER_ACCT
-#define DO_NFACCT 1
-
-#include <libnetfilter_acct/libnetfilter_acct.h>
-
-struct nfacct_data {
- char *name;
- uint32_t hash;
-
- uint64_t pkts;
- uint64_t bytes;
-
- RRDDIM *rd_bytes;
- RRDDIM *rd_packets;
-
- int updated;
-
- struct nfacct_data *next;
-};
-
-static struct {
- int update_every;
- char *buf;
- size_t buf_size;
- struct mnl_socket *mnl;
- struct nlmsghdr *nlh;
- unsigned int seq;
- uint32_t portid;
- struct nfacct *nfacct_buffer;
- struct nfacct_data *nfacct_metrics;
-} nfacct_root = {
- .update_every = 1,
- .buf = NULL,
- .buf_size = 0,
- .mnl = NULL,
- .nlh = NULL,
- .seq = 0,
- .portid = 0,
- .nfacct_buffer = NULL,
- .nfacct_metrics = NULL
-};
-
-static inline struct nfacct_data *nfacct_data_get(const char *name, uint32_t hash) {
- struct nfacct_data *d = NULL, *last = NULL;
- for(d = nfacct_root.nfacct_metrics; d ; last = d, d = d->next) {
- if(unlikely(d->hash == hash && !strcmp(d->name, name)))
- return d;
- }
-
- d = callocz(1, sizeof(struct nfacct_data));
- d->name = strdupz(name);
- d->hash = hash;
-
- if(!last) {
- d->next = nfacct_root.nfacct_metrics;
- nfacct_root.nfacct_metrics = d;
- }
- else {
- d->next = last->next;
- last->next = d;
- }
-
- return d;
-}
-
-static int nfacct_init(int update_every) {
- nfacct_root.update_every = update_every;
-
- nfacct_root.buf_size = mnl_buffer_size();
- nfacct_root.buf = mallocz(nfacct_root.buf_size);
-
- nfacct_root.nfacct_buffer = nfacct_alloc();
- if(!nfacct_root.nfacct_buffer) {
- error("nfacct.plugin: nfacct_alloc() failed.");
- return 0;
- }
-
- nfacct_root.seq = (unsigned int)now_realtime_sec() - 1;
-
- nfacct_root.mnl = mnl_socket_open(NETLINK_NETFILTER);
- if(!nfacct_root.mnl) {
- error("nfacct.plugin: mnl_socket_open() failed");
- return 1;
- }
-
- if(mnl_socket_bind(nfacct_root.mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
- error("nfacct.plugin: mnl_socket_bind() failed");
- return 1;
- }
- nfacct_root.portid = mnl_socket_get_portid(nfacct_root.mnl);
-
- return 0;
-}
-
-static void nfacct_cleanup() {
- if(nfacct_root.mnl) {
- mnl_socket_close(nfacct_root.mnl);
- nfacct_root.mnl = NULL;
- }
-
- if(nfacct_root.nfacct_buffer) {
- nfacct_free(nfacct_root.nfacct_buffer);
- nfacct_root.nfacct_buffer = NULL;
- }
-
- freez(nfacct_root.buf);
- nfacct_root.buf = NULL;
- nfacct_root.buf_size = 0;
-
- // FIXME: cleanup the metrics linked list
-}
-
-static int nfacct_callback(const struct nlmsghdr *nlh, void *data) {
- (void)data;
-
- if(nfacct_nlmsg_parse_payload(nlh, nfacct_root.nfacct_buffer) < 0) {
- error("NFACCT: nfacct_nlmsg_parse_payload() failed.");
- return MNL_CB_OK;
- }
-
- const char *name = nfacct_attr_get_str(nfacct_root.nfacct_buffer, NFACCT_ATTR_NAME);
- uint32_t hash = simple_hash(name);
-
- struct nfacct_data *d = nfacct_data_get(name, hash);
-
- d->pkts = nfacct_attr_get_u64(nfacct_root.nfacct_buffer, NFACCT_ATTR_PKTS);
- d->bytes = nfacct_attr_get_u64(nfacct_root.nfacct_buffer, NFACCT_ATTR_BYTES);
- d->updated = 1;
-
- return MNL_CB_OK;
-}
-
-static int nfacct_collect() {
- // mark all old metrics as not-updated
- struct nfacct_data *d;
- for(d = nfacct_root.nfacct_metrics; d ; d = d->next)
- d->updated = 0;
-
- // prepare the request
- nfacct_root.seq++;
- nfacct_root.nlh = nfacct_nlmsg_build_hdr(nfacct_root.buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, (uint32_t)nfacct_root.seq);
- if(!nfacct_root.nlh) {
- error("NFACCT: nfacct_nlmsg_build_hdr() failed");
- return 1;
- }
-
- // send the request
- if(mnl_socket_sendto(nfacct_root.mnl, nfacct_root.nlh, nfacct_root.nlh->nlmsg_len) < 0) {
- error("NFACCT: mnl_socket_sendto() failed");
- return 1;
- }
-
- // get the reply
- ssize_t ret;
- while((ret = mnl_socket_recvfrom(nfacct_root.mnl, nfacct_root.buf, nfacct_root.buf_size)) > 0) {
- if(mnl_cb_run(
- nfacct_root.buf
- , (size_t)ret
- , nfacct_root.seq
- , nfacct_root.portid
- , nfacct_callback
- , NULL
- ) <= 0)
- break;
- }
-
- // verify we run without issues
- if (ret == -1) {
- error("NFACCT: error communicating with kernel. This plugin can only work when netdata runs as root.");
- return 1;
- }
-
- return 0;
-}
-
-static void nfacct_send_metrics() {
- static RRDSET *st_bytes = NULL, *st_packets = NULL;
-
- if(!nfacct_root.nfacct_metrics) return;
- struct nfacct_data *d;
-
- if(!st_packets) {
- st_packets = rrdset_create_localhost(
- "netfilter"
- , "nfacct_packets"
- , NULL
- , "nfacct"
- , NULL
- , "Netfilter Accounting Packets"
- , "packets/s"
- , "nfacct"
- , NULL
- , 3206
- , nfacct_root.update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st_packets);
-
- for(d = nfacct_root.nfacct_metrics; d ; d = d->next) {
- if(likely(d->updated)) {
- if(unlikely(!d->rd_packets))
- d->rd_packets = rrddim_add(
- st_packets
- , d->name
- , NULL
- , 1
- , nfacct_root.update_every
- , RRD_ALGORITHM_INCREMENTAL
- );
-
- rrddim_set_by_pointer(
- st_packets
- , d->rd_packets
- , (collected_number)d->pkts
- );
- }
- }
-
- rrdset_done(st_packets);
-
- // ----------------------------------------------------------------
-
- st_bytes = rrdset_find_bytype_localhost("netfilter", "nfacct_bytes");
- if(!st_bytes) {
- st_bytes = rrdset_create_localhost(
- "netfilter"
- , "nfacct_bytes"
- , NULL
- , "nfacct"
- , NULL
- , "Netfilter Accounting Bandwidth"
- , "kilobytes/s"
- , "nfacct"
- , NULL
- , 3207
- , nfacct_root.update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st_bytes);
-
- for(d = nfacct_root.nfacct_metrics; d ; d = d->next) {
- if(likely(d->updated)) {
- if(unlikely(!d->rd_bytes))
- d->rd_bytes = rrddim_add(
- st_bytes
- , d->name
- , NULL
- , 1
- , 1000 * nfacct_root.update_every
- , RRD_ALGORITHM_INCREMENTAL
- );
-
- rrddim_set_by_pointer(
- st_bytes
- , d->rd_bytes
- , (collected_number)d->bytes
- );
- }
- }
-
- rrdset_done(st_bytes);
-}
-
-#endif // HAVE_LIBNETFILTER_ACCT
-#endif // HAVE_LIBMNL
-
-// ----------------------------------------------------------------------------
-
-static void nfacct_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
- info("cleaning up...");
-
-#ifdef DO_NFACCT
- nfacct_cleanup();
-#endif
-
-#ifdef DO_NFSTAT
- nfstat_cleanup();
-#endif
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *nfacct_main(void *ptr) {
- netdata_thread_cleanup_push(nfacct_main_cleanup, ptr);
-
- int update_every = (int)config_get_number("plugin:netfilter", "update every", localhost->rrd_update_every);
- if(update_every < localhost->rrd_update_every)
- update_every = localhost->rrd_update_every;
-
-#ifdef DO_NFACCT
- int nfacct = !nfacct_init(update_every);
-#endif
-
-#ifdef DO_NFSTAT
- int nfstat = !nfstat_init(update_every);
-#endif
-
- // ------------------------------------------------------------------------
-
- usec_t step = update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
- for(;;) {
- heartbeat_dt_usec(&hb);
- heartbeat_next(&hb, step);
-
- if(unlikely(netdata_exit)) break;
-
-#ifdef DO_NFACCT
- if(likely(nfacct)) {
- nfacct = !nfacct_collect();
-
- if(likely(nfacct))
- nfacct_send_metrics();
- }
-#endif
-
-#ifdef DO_NFSTAT
- if(likely(nfstat)) {
- nfstat = !nfstat_collect();
-
- if(likely(nfstat))
- nfstat_send_metrics();
- }
-#endif
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-#endif // INTERNAL_PLUGIN_NFACCT
diff --git a/src/plugin_nfacct.h b/src/plugin_nfacct.h
deleted file mode 100644
index 88a3a9230..000000000
--- a/src/plugin_nfacct.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef NETDATA_NFACCT_H
-#define NETDATA_NFACCT_H 1
-
-extern void *nfacct_main(void *ptr);
-
-#endif /* NETDATA_NFACCT_H */
-
diff --git a/src/plugin_proc.c b/src/plugin_proc.c
deleted file mode 100644
index e0afb0d6d..000000000
--- a/src/plugin_proc.c
+++ /dev/null
@@ -1,201 +0,0 @@
-#include "common.h"
-
-static struct proc_module {
- const char *name;
- const char *dim;
-
- int enabled;
-
- int (*func)(int update_every, usec_t dt);
- usec_t duration;
-
- RRDDIM *rd;
-
-} proc_modules[] = {
-
- // system metrics
- { .name = "/proc/stat", .dim = "stat", .func = do_proc_stat },
- { .name = "/proc/uptime", .dim = "uptime", .func = do_proc_uptime },
- { .name = "/proc/loadavg", .dim = "loadavg", .func = do_proc_loadavg },
- { .name = "/proc/sys/kernel/random/entropy_avail", .dim = "entropy", .func = do_proc_sys_kernel_random_entropy_avail },
-
- // CPU metrics
- { .name = "/proc/interrupts", .dim = "interrupts", .func = do_proc_interrupts },
- { .name = "/proc/softirqs", .dim = "softirqs", .func = do_proc_softirqs },
-
- // memory metrics
- { .name = "/proc/vmstat", .dim = "vmstat", .func = do_proc_vmstat },
- { .name = "/proc/meminfo", .dim = "meminfo", .func = do_proc_meminfo },
- { .name = "/sys/kernel/mm/ksm", .dim = "ksm", .func = do_sys_kernel_mm_ksm },
- { .name = "/sys/devices/system/edac/mc", .dim = "ecc", .func = do_proc_sys_devices_system_edac_mc },
- { .name = "/sys/devices/system/node", .dim = "numa", .func = do_proc_sys_devices_system_node },
-
- // network metrics
- { .name = "/proc/net/dev", .dim = "netdev", .func = do_proc_net_dev },
- { .name = "/proc/net/sockstat", .dim = "sockstat", .func = do_proc_net_sockstat },
- { .name = "/proc/net/sockstat6", .dim = "sockstat6", .func = do_proc_net_sockstat6 },
- { .name = "/proc/net/netstat", .dim = "netstat", .func = do_proc_net_netstat }, // this has to be before /proc/net/snmp, because there is a shared metric
- { .name = "/proc/net/snmp", .dim = "snmp", .func = do_proc_net_snmp },
- { .name = "/proc/net/snmp6", .dim = "snmp6", .func = do_proc_net_snmp6 },
- { .name = "/proc/net/softnet_stat", .dim = "softnet", .func = do_proc_net_softnet_stat },
- { .name = "/proc/net/ip_vs/stats", .dim = "ipvs", .func = do_proc_net_ip_vs_stats },
-
- // firewall metrics
- { .name = "/proc/net/stat/conntrack", .dim = "conntrack", .func = do_proc_net_stat_conntrack },
- { .name = "/proc/net/stat/synproxy", .dim = "synproxy", .func = do_proc_net_stat_synproxy },
-
- // disk metrics
- { .name = "/proc/diskstats", .dim = "diskstats", .func = do_proc_diskstats },
-
- // NFS metrics
- { .name = "/proc/net/rpc/nfsd", .dim = "nfsd", .func = do_proc_net_rpc_nfsd },
- { .name = "/proc/net/rpc/nfs", .dim = "nfs", .func = do_proc_net_rpc_nfs },
-
- // ZFS metrics
- { .name = "/proc/spl/kstat/zfs/arcstats", .dim = "zfs_arcstats", .func = do_proc_spl_kstat_zfs_arcstats },
-
- // BTRFS metrics
- { .name = "/sys/fs/btrfs", .dim = "btrfs", .func = do_sys_fs_btrfs },
-
- // IPC metrics
- { .name = "ipc", .dim = "ipc", .func = do_ipc },
-
- // the terminator of this array
- { .name = NULL, .dim = NULL, .func = NULL }
-};
-
-static void proc_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *proc_main(void *ptr) {
- netdata_thread_cleanup_push(proc_main_cleanup, ptr);
-
- int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1);
-
- // check the enabled status for each module
- int i;
- for(i = 0 ; proc_modules[i].name ;i++) {
- struct proc_module *pm = &proc_modules[i];
-
- pm->enabled = config_get_boolean("plugin:proc", pm->name, 1);
- pm->duration = 0ULL;
- pm->rd = NULL;
- }
-
- usec_t step = localhost->rrd_update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- while(!netdata_exit) {
- usec_t hb_dt = heartbeat_next(&hb, step);
- usec_t duration = 0ULL;
-
- if(unlikely(netdata_exit)) break;
-
- // BEGIN -- the job to be done
-
- for(i = 0 ; proc_modules[i].name ;i++) {
- struct proc_module *pm = &proc_modules[i];
- if(unlikely(!pm->enabled)) continue;
-
- debug(D_PROCNETDEV_LOOP, "PROC calling %s.", pm->name);
-
- pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt);
- pm->duration = heartbeat_dt_usec(&hb) - duration;
- duration += pm->duration;
-
- if(unlikely(netdata_exit)) break;
- }
-
- // END -- the job is done
-
- // --------------------------------------------------------------------
-
- if(vdo_cpu_netdata) {
- static RRDSET *st = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_find_bytype_localhost("netdata", "plugin_proc_modules");
-
- if(!st) {
- st = rrdset_create_localhost(
- "netdata"
- , "plugin_proc_modules"
- , NULL
- , "proc"
- , NULL
- , "NetData Proc Plugin Modules Durations"
- , "milliseconds/run"
- , "netdata"
- , "stats"
- , 132001
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-
- for(i = 0 ; proc_modules[i].name ;i++) {
- struct proc_module *pm = &proc_modules[i];
- if(unlikely(!pm->enabled)) continue;
-
- pm->rd = rrddim_add(st, pm->dim, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- }
- }
- else rrdset_next(st);
-
- for(i = 0 ; proc_modules[i].name ;i++) {
- struct proc_module *pm = &proc_modules[i];
- if(unlikely(!pm->enabled)) continue;
-
- rrddim_set_by_pointer(st, pm->rd, pm->duration);
- }
- rrdset_done(st);
-
- global_statistics_charts();
- registry_statistics();
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-int get_numa_node_count(void)
-{
- static int numa_node_count = -1;
-
- if (numa_node_count != -1)
- return numa_node_count;
-
- numa_node_count = 0;
-
- char name[FILENAME_MAX + 1];
- snprintfz(name, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/node");
- char *dirname = config_get("plugin:proc:/sys/devices/system/node", "directory to monitor", name);
-
- DIR *dir = opendir(dirname);
- if(dir) {
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type != DT_DIR)
- continue;
-
- if(strncmp(de->d_name, "node", 4) != 0)
- continue;
-
- if(!isdigit(de->d_name[4]))
- continue;
-
- numa_node_count++;
- }
- closedir(dir);
- }
-
- return numa_node_count;
-}
diff --git a/src/plugin_proc.h b/src/plugin_proc.h
deleted file mode 100644
index a7f9b4e38..000000000
--- a/src/plugin_proc.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef NETDATA_PLUGIN_PROC_H
-#define NETDATA_PLUGIN_PROC_H 1
-
-void *proc_main(void *ptr);
-
-extern int do_proc_net_dev(int update_every, usec_t dt);
-extern int do_proc_diskstats(int update_every, usec_t dt);
-extern int do_proc_net_snmp(int update_every, usec_t dt);
-extern int do_proc_net_snmp6(int update_every, usec_t dt);
-extern int do_proc_net_netstat(int update_every, usec_t dt);
-extern int do_proc_net_stat_conntrack(int update_every, usec_t dt);
-extern int do_proc_net_ip_vs_stats(int update_every, usec_t dt);
-extern int do_proc_stat(int update_every, usec_t dt);
-extern int do_proc_meminfo(int update_every, usec_t dt);
-extern int do_proc_vmstat(int update_every, usec_t dt);
-extern int do_proc_net_rpc_nfs(int update_every, usec_t dt);
-extern int do_proc_net_rpc_nfsd(int update_every, usec_t dt);
-extern int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt);
-extern int do_proc_interrupts(int update_every, usec_t dt);
-extern int do_proc_softirqs(int update_every, usec_t dt);
-extern int do_sys_kernel_mm_ksm(int update_every, usec_t dt);
-extern int do_proc_loadavg(int update_every, usec_t dt);
-extern int do_proc_net_stat_synproxy(int update_every, usec_t dt);
-extern int do_proc_net_softnet_stat(int update_every, usec_t dt);
-extern int do_proc_uptime(int update_every, usec_t dt);
-extern int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt);
-extern int do_proc_sys_devices_system_node(int update_every, usec_t dt);
-extern int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt);
-extern int do_sys_fs_btrfs(int update_every, usec_t dt);
-extern int do_proc_net_sockstat(int update_every, usec_t dt);
-extern int do_proc_net_sockstat6(int update_every, usec_t dt);
-
-extern int get_numa_node_count(void);
-
-// metrics that need to be shared among data collectors
-extern unsigned long long tcpext_TCPSynRetrans;
-
-// netdev renames
-extern void netdev_rename_device_add(const char *host_device, const char *container_device, const char *container_name);
-extern void netdev_rename_device_del(const char *host_device);
-
-#endif /* NETDATA_PLUGIN_PROC_H */
diff --git a/src/plugin_proc_diskspace.c b/src/plugin_proc_diskspace.c
deleted file mode 100644
index 0a229f38e..000000000
--- a/src/plugin_proc_diskspace.c
+++ /dev/null
@@ -1,460 +0,0 @@
-#include "common.h"
-
-#define DELAULT_EXCLUDED_PATHS "/proc/* /sys/* /var/run/user/* /run/user/* /snap/* /var/lib/docker/*"
-#define DEFAULT_EXCLUDED_FILESYSTEMS ""
-#define CONFIG_SECTION_DISKSPACE "plugin:proc:diskspace"
-
-static struct mountinfo *disk_mountinfo_root = NULL;
-static int check_for_new_mountpoints_every = 15;
-static int cleanup_mount_points = 1;
-
-static inline void mountinfo_reload(int force) {
- static time_t last_loaded = 0;
- time_t now = now_realtime_sec();
-
- if(force || now - last_loaded >= check_for_new_mountpoints_every) {
- // mountinfo_free_all() can be called with NULL disk_mountinfo_root
- mountinfo_free_all(disk_mountinfo_root);
-
- // re-read mountinfo in case something changed
- disk_mountinfo_root = mountinfo_read(0);
-
- last_loaded = now;
- }
-}
-
-// Data to be stored in DICTIONARY dict_mountpoints used by do_disk_space_stats().
-// This DICTIONARY is used to lookup the settings of the mount point on each iteration.
-struct mount_point_metadata {
- int do_space;
- int do_inodes;
- int shown_error;
- int updated;
-
- size_t collected; // the number of times this has been collected
-
- RRDSET *st_space;
- RRDDIM *rd_space_used;
- RRDDIM *rd_space_avail;
- RRDDIM *rd_space_reserved;
-
- RRDSET *st_inodes;
- RRDDIM *rd_inodes_used;
- RRDDIM *rd_inodes_avail;
- RRDDIM *rd_inodes_reserved;
-};
-
-static DICTIONARY *dict_mountpoints = NULL;
-
-#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_is_obsolete(st); (st) = NULL; } } while(st)
-
-int mount_point_cleanup(void *entry, void *data) {
- (void)data;
-
- struct mount_point_metadata *mp = (struct mount_point_metadata *)entry;
- if(!mp) return 0;
-
- if(likely(mp->updated)) {
- mp->updated = 0;
- return 0;
- }
-
- if(likely(cleanup_mount_points && mp->collected)) {
- mp->collected = 0;
- mp->updated = 0;
- mp->shown_error = 0;
-
- mp->rd_space_avail = NULL;
- mp->rd_space_used = NULL;
- mp->rd_space_reserved = NULL;
-
- mp->rd_inodes_avail = NULL;
- mp->rd_inodes_used = NULL;
- mp->rd_inodes_reserved = NULL;
-
- rrdset_obsolete_and_pointer_null(mp->st_space);
- rrdset_obsolete_and_pointer_null(mp->st_inodes);
- }
-
- return 0;
-}
-
-static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
- const char *family = mi->mount_point;
- const char *disk = mi->persistent_id;
-
- static SIMPLE_PATTERN *excluded_mountpoints = NULL;
- static SIMPLE_PATTERN *excluded_filesystems = NULL;
- int do_space, do_inodes;
-
- if(unlikely(!dict_mountpoints)) {
- SIMPLE_PREFIX_MODE mode = SIMPLE_PATTERN_EXACT;
-
- if(config_move("plugin:proc:/proc/diskstats", "exclude space metrics on paths", CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths") != -1) {
- // old configuration, enable backwards compatibility
- mode = SIMPLE_PATTERN_PREFIX;
- }
-
- excluded_mountpoints = simple_pattern_create(
- config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths", DELAULT_EXCLUDED_PATHS)
- , NULL
- , mode
- );
-
- excluded_filesystems = simple_pattern_create(
- config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on filesystems", DEFAULT_EXCLUDED_FILESYSTEMS)
- , NULL
- , SIMPLE_PATTERN_EXACT
- );
-
- dict_mountpoints = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
- }
-
- struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point);
- if(unlikely(!m)) {
- char var_name[4096 + 1];
- snprintfz(var_name, 4096, "plugin:proc:diskspace:%s", mi->mount_point);
-
- int def_space = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "space usage for all disks", CONFIG_BOOLEAN_AUTO);
- int def_inodes = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO);
-
- if(unlikely(simple_pattern_matches(excluded_mountpoints, mi->mount_point))) {
- def_space = CONFIG_BOOLEAN_NO;
- def_inodes = CONFIG_BOOLEAN_NO;
- }
-
- if(unlikely(simple_pattern_matches(excluded_filesystems, mi->filesystem))) {
- def_space = CONFIG_BOOLEAN_NO;
- def_inodes = CONFIG_BOOLEAN_NO;
- }
-
- // check if the mount point is a directory #2407
- {
- struct stat bs;
- if(stat(mi->mount_point, &bs) == -1) {
- error("DISKSPACE: Cannot stat() mount point '%s' (disk '%s', filesystem '%s', root '%s')."
- , mi->mount_point
- , disk
- , mi->filesystem?mi->filesystem:""
- , mi->root?mi->root:""
- );
- def_space = CONFIG_BOOLEAN_NO;
- def_inodes = CONFIG_BOOLEAN_NO;
- }
- else {
- if((bs.st_mode & S_IFMT) != S_IFDIR) {
- error("DISKSPACE: Mount point '%s' (disk '%s', filesystem '%s', root '%s') is not a directory."
- , mi->mount_point
- , disk
- , mi->filesystem?mi->filesystem:""
- , mi->root?mi->root:""
- );
- def_space = CONFIG_BOOLEAN_NO;
- def_inodes = CONFIG_BOOLEAN_NO;
- }
- }
- }
-
- do_space = config_get_boolean_ondemand(var_name, "space usage", def_space);
- do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
-
- struct mount_point_metadata mp = {
- .do_space = do_space,
- .do_inodes = do_inodes,
- .shown_error = 0,
- .updated = 0,
-
- .collected = 0,
-
- .st_space = NULL,
- .rd_space_avail = NULL,
- .rd_space_used = NULL,
- .rd_space_reserved = NULL,
-
- .st_inodes = NULL,
- .rd_inodes_avail = NULL,
- .rd_inodes_used = NULL,
- .rd_inodes_reserved = NULL
- };
-
- m = dictionary_set(dict_mountpoints, mi->mount_point, &mp, sizeof(struct mount_point_metadata));
- }
-
- m->updated = 1;
-
- if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO))
- return;
-
- if(unlikely(mi->flags & MOUNTINFO_READONLY && !m->collected))
- return;
-
- struct statvfs buff_statvfs;
- if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
- if(!m->shown_error) {
- error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
- , mi->mount_point
- , disk
- , mi->filesystem?mi->filesystem:""
- , mi->root?mi->root:""
- );
- m->shown_error = 1;
- }
- return;
- }
- m->shown_error = 0;
-
- // logic found at get_fs_usage() in coreutils
- unsigned long bsize = (buff_statvfs.f_frsize) ? buff_statvfs.f_frsize : buff_statvfs.f_bsize;
-
- fsblkcnt_t bavail = buff_statvfs.f_bavail;
- fsblkcnt_t btotal = buff_statvfs.f_blocks;
- fsblkcnt_t bavail_root = buff_statvfs.f_bfree;
- fsblkcnt_t breserved_root = bavail_root - bavail;
- fsblkcnt_t bused;
- if(likely(btotal >= bavail_root))
- bused = btotal - bavail_root;
- else
- bused = bavail_root - btotal;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(btotal != bavail + breserved_root + bused))
- error("DISKSPACE: disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused);
-#endif
-
- // --------------------------------------------------------------------------
-
- fsfilcnt_t favail = buff_statvfs.f_favail;
- fsfilcnt_t ftotal = buff_statvfs.f_files;
- fsfilcnt_t favail_root = buff_statvfs.f_ffree;
- fsfilcnt_t freserved_root = favail_root - favail;
- fsfilcnt_t fused = ftotal - favail_root;
-
- if(m->do_inodes == CONFIG_BOOLEAN_AUTO && favail == (fsfilcnt_t)-1) {
- // this file system does not support inodes reporting
- // eg. cephfs
- m->do_inodes = CONFIG_BOOLEAN_NO;
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(btotal != bavail + breserved_root + bused))
- error("DISKSPACE: disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused);
-#endif
-
- // --------------------------------------------------------------------------
-
- int rendered = 0;
-
- if(m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (bavail || breserved_root || bused))) {
- if(unlikely(!m->st_space)) {
- m->do_space = CONFIG_BOOLEAN_YES;
- m->st_space = rrdset_find_bytype_localhost("disk_space", disk);
- if(unlikely(!m->st_space)) {
- char title[4096 + 1];
- snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mi->mount_source);
- m->st_space = rrdset_create_localhost(
- "disk_space"
- , disk
- , NULL
- , family
- , "disk.space"
- , title
- , "GB"
- , "diskspace"
- , NULL
- , 2023
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
-
- m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- m->rd_space_used = rrddim_add(m->st_space, "used", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(m->st_space);
-
- rrddim_set_by_pointer(m->st_space, m->rd_space_avail, (collected_number)bavail);
- rrddim_set_by_pointer(m->st_space, m->rd_space_used, (collected_number)bused);
- rrddim_set_by_pointer(m->st_space, m->rd_space_reserved, (collected_number)breserved_root);
- rrdset_done(m->st_space);
-
- rendered++;
- }
-
- // --------------------------------------------------------------------------
-
- if(m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (favail || freserved_root || fused))) {
- if(unlikely(!m->st_inodes)) {
- m->do_inodes = CONFIG_BOOLEAN_YES;
- m->st_inodes = rrdset_find_bytype_localhost("disk_inodes", disk);
- if(unlikely(!m->st_inodes)) {
- char title[4096 + 1];
- snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mi->mount_source);
- m->st_inodes = rrdset_create_localhost(
- "disk_inodes"
- , disk
- , NULL
- , family
- , "disk.inodes"
- , title
- , "Inodes"
- , "diskspace"
- , NULL
- , 2024
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
-
- m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(m->st_inodes);
-
- rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number)favail);
- rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used, (collected_number)fused);
- rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_reserved, (collected_number)freserved_root);
- rrdset_done(m->st_inodes);
-
- rendered++;
- }
-
- // --------------------------------------------------------------------------
-
- if(likely(rendered))
- m->collected++;
-}
-
-static void diskspace_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *proc_diskspace_main(void *ptr) {
- netdata_thread_cleanup_push(diskspace_main_cleanup, ptr);
-
- int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1);
-
- cleanup_mount_points = config_get_boolean(CONFIG_SECTION_DISKSPACE, "remove charts of unmounted disks" , cleanup_mount_points);
-
- int update_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "update every", localhost->rrd_update_every);
- if(update_every < localhost->rrd_update_every)
- update_every = localhost->rrd_update_every;
-
- check_for_new_mountpoints_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "check for new mount points every", check_for_new_mountpoints_every);
- if(check_for_new_mountpoints_every < update_every)
- check_for_new_mountpoints_every = update_every;
-
- struct rusage thread;
-
- usec_t duration = 0;
- usec_t step = update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
- while(!netdata_exit) {
- duration = heartbeat_dt_usec(&hb);
- /* usec_t hb_dt = */ heartbeat_next(&hb, step);
-
- if(unlikely(netdata_exit)) break;
-
-
- // --------------------------------------------------------------------------
- // this is smart enough not to reload it every time
-
- mountinfo_reload(0);
-
-
- // --------------------------------------------------------------------------
- // disk space metrics
-
- struct mountinfo *mi;
- for(mi = disk_mountinfo_root; mi; mi = mi->next) {
-
- if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY | MOUNTINFO_IS_BIND)))
- continue;
-
- do_disk_space_stats(mi, update_every);
- if(unlikely(netdata_exit)) break;
- }
-
- if(unlikely(netdata_exit)) break;
-
- if(dict_mountpoints)
- dictionary_get_all(dict_mountpoints, mount_point_cleanup, NULL);
-
- if(vdo_cpu_netdata) {
- static RRDSET *stcpu_thread = NULL, *st_duration = NULL;
- static RRDDIM *rd_user = NULL, *rd_system = NULL, *rd_duration = NULL;
-
- // ----------------------------------------------------------------
-
- getrusage(RUSAGE_THREAD, &thread);
-
- if(unlikely(!stcpu_thread)) {
- stcpu_thread = rrdset_create_localhost(
- "netdata"
- , "plugin_diskspace"
- , NULL
- , "diskspace"
- , NULL
- , "NetData Disk Space Plugin CPU usage"
- , "milliseconds/s"
- , "diskspace"
- , NULL
- , 132020
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(stcpu_thread);
-
- rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
- rrddim_set_by_pointer(stcpu_thread, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
- rrdset_done(stcpu_thread);
-
- // ----------------------------------------------------------------
-
- if(unlikely(!st_duration)) {
- st_duration = rrdset_create_localhost(
- "netdata"
- , "plugin_diskspace_dt"
- , NULL
- , "diskspace"
- , NULL
- , "NetData Disk Space Plugin Duration"
- , "milliseconds/run"
- , "diskspace"
- , NULL
- , 132021
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_duration);
-
- rrddim_set_by_pointer(st_duration, rd_duration, duration);
- rrdset_done(st_duration);
-
- // ----------------------------------------------------------------
-
- if(unlikely(netdata_exit)) break;
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/plugin_proc_diskspace.h b/src/plugin_proc_diskspace.h
deleted file mode 100644
index dcec28f75..000000000
--- a/src/plugin_proc_diskspace.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef NETDATA_PLUGIN_PROC_DISKSPACE_H
-#define NETDATA_PLUGIN_PROC_DISKSPACE_H
-
-extern void *proc_diskspace_main(void *ptr);
-
-#endif //NETDATA_PLUGIN_PROC_DISKSPACE_H
diff --git a/src/plugin_tc.c b/src/plugin_tc.c
deleted file mode 100644
index 4b6d84e11..000000000
--- a/src/plugin_tc.c
+++ /dev/null
@@ -1,1164 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_TC "tc"
-
-// ----------------------------------------------------------------------------
-// /sbin/tc processor
-// this requires the script plugins.d/tc-qos-helper.sh
-
-#define TC_LINE_MAX 1024
-
-struct tc_class {
- avl avl;
-
- char *id;
- uint32_t hash;
-
- char *name;
-
- char *leafid;
- uint32_t leaf_hash;
-
- char *parentid;
- uint32_t parent_hash;
-
- char hasparent;
- char isleaf;
- char isqdisc;
- char render;
-
- unsigned long long bytes;
- unsigned long long packets;
- unsigned long long dropped;
- unsigned long long overlimits;
- unsigned long long requeues;
- unsigned long long lended;
- unsigned long long borrowed;
- unsigned long long giants;
- unsigned long long tokens;
- unsigned long long ctokens;
-
- RRDDIM *rd_bytes;
- RRDDIM *rd_packets;
- RRDDIM *rd_dropped;
- RRDDIM *rd_tokens;
- RRDDIM *rd_ctokens;
-
- char name_updated;
- char updated; // updated bytes
- int unupdated; // the number of times, this has been found un-updated
-
- struct tc_class *next;
- struct tc_class *prev;
-};
-
-struct tc_device {
- avl avl;
-
- char *id;
- uint32_t hash;
-
- char *name;
- char *family;
-
- char name_updated;
- char family_updated;
-
- char enabled;
- char enabled_bytes;
- char enabled_packets;
- char enabled_dropped;
- char enabled_tokens;
- char enabled_ctokens;
- char enabled_all_classes_qdiscs;
-
- RRDSET *st_bytes;
- RRDSET *st_packets;
- RRDSET *st_dropped;
- RRDSET *st_tokens;
- RRDSET *st_ctokens;
-
- avl_tree classes_index;
-
- struct tc_class *classes;
- struct tc_class *last_class;
-
- struct tc_device *next;
- struct tc_device *prev;
-};
-
-
-struct tc_device *tc_device_root = NULL;
-
-// ----------------------------------------------------------------------------
-// tc_device index
-
-static int tc_device_compare(void* a, void* b) {
- if(((struct tc_device *)a)->hash < ((struct tc_device *)b)->hash) return -1;
- else if(((struct tc_device *)a)->hash > ((struct tc_device *)b)->hash) return 1;
- else return strcmp(((struct tc_device *)a)->id, ((struct tc_device *)b)->id);
-}
-
-avl_tree tc_device_root_index = {
- NULL,
- tc_device_compare
-};
-
-#define tc_device_index_add(st) (struct tc_device *)avl_insert(&tc_device_root_index, (avl *)(st))
-#define tc_device_index_del(st) (struct tc_device *)avl_remove(&tc_device_root_index, (avl *)(st))
-
-static inline struct tc_device *tc_device_index_find(const char *id, uint32_t hash) {
- struct tc_device tmp;
- tmp.id = (char *)id;
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
-
- return (struct tc_device *)avl_search(&(tc_device_root_index), (avl *)&tmp);
-}
-
-
-// ----------------------------------------------------------------------------
-// tc_class index
-
-static int tc_class_compare(void* a, void* b) {
- if(((struct tc_class *)a)->hash < ((struct tc_class *)b)->hash) return -1;
- else if(((struct tc_class *)a)->hash > ((struct tc_class *)b)->hash) return 1;
- else return strcmp(((struct tc_class *)a)->id, ((struct tc_class *)b)->id);
-}
-
-#define tc_class_index_add(st, rd) (struct tc_class *)avl_insert(&((st)->classes_index), (avl *)(rd))
-#define tc_class_index_del(st, rd) (struct tc_class *)avl_remove(&((st)->classes_index), (avl *)(rd))
-
-static inline struct tc_class *tc_class_index_find(struct tc_device *st, const char *id, uint32_t hash) {
- struct tc_class tmp;
- tmp.id = (char *)id;
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
-
- return (struct tc_class *)avl_search(&(st->classes_index), (avl *) &tmp);
-}
-
-// ----------------------------------------------------------------------------
-
-static inline void tc_class_free(struct tc_device *n, struct tc_class *c) {
- if(c == n->classes) {
- if(likely(c->next))
- n->classes = c->next;
- else
- n->classes = c->prev;
- }
-
- if(c == n->last_class) {
- if(unlikely(c->next))
- n->last_class = c->next;
- else
- n->last_class = c->prev;
- }
-
- if(c->next) c->next->prev = c->prev;
- if(c->prev) c->prev->next = c->next;
-
- debug(D_TC_LOOP, "Removing from device '%s' class '%s', parentid '%s', leafid '%s', unused=%d", n->id, c->id, c->parentid?c->parentid:"", c->leafid?c->leafid:"", c->unupdated);
-
- if(unlikely(tc_class_index_del(n, c) != c))
- error("plugin_tc: INTERNAL ERROR: attempt remove class '%s' from device '%s': removed a different calls", c->id, n->id);
-
- freez(c->id);
- freez(c->name);
- freez(c->leafid);
- freez(c->parentid);
- freez(c);
-}
-
-static inline void tc_device_classes_cleanup(struct tc_device *d) {
- static int cleanup_every = 999;
-
- if(unlikely(cleanup_every > 0)) {
- cleanup_every = (int) config_get_number("plugin:tc", "cleanup unused classes every", 120);
- if(cleanup_every < 0) cleanup_every = -cleanup_every;
- }
-
- d->name_updated = 0;
- d->family_updated = 0;
-
- struct tc_class *c = d->classes;
- while(c) {
- if(unlikely(cleanup_every && c->unupdated >= cleanup_every)) {
- struct tc_class *nc = c->next;
- tc_class_free(d, c);
- c = nc;
- }
- else {
- c->updated = 0;
- c->name_updated = 0;
-
- c = c->next;
- }
- }
-}
-
-static inline void tc_device_commit(struct tc_device *d) {
- static int enable_new_interfaces = -1, enable_bytes = -1, enable_packets = -1, enable_dropped = -1, enable_tokens = -1, enable_ctokens = -1, enabled_all_classes_qdiscs = -1;
-
- if(unlikely(enable_new_interfaces == -1)) {
- enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_YES);
- enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_BOOLEAN_AUTO);
- enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_BOOLEAN_AUTO);
- enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_BOOLEAN_AUTO);
- enable_tokens = config_get_boolean_ondemand("plugin:tc", "enable tokens charts for all interfaces", CONFIG_BOOLEAN_NO);
- enable_ctokens = config_get_boolean_ondemand("plugin:tc", "enable ctokens charts for all interfaces", CONFIG_BOOLEAN_NO);
- enabled_all_classes_qdiscs = config_get_boolean_ondemand("plugin:tc", "enable show all classes and qdiscs for all interfaces", CONFIG_BOOLEAN_NO);
- }
-
- if(unlikely(d->enabled == (char)-1)) {
- char var_name[CONFIG_MAX_NAME + 1];
- snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id);
-
- d->enabled = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_new_interfaces);
-
- snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", d->id);
- d->enabled_bytes = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_bytes);
-
- snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", d->id);
- d->enabled_packets = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_packets);
-
- snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", d->id);
- d->enabled_dropped = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_dropped);
-
- snprintfz(var_name, CONFIG_MAX_NAME, "tokens chart for %s", d->id);
- d->enabled_tokens = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_tokens);
-
- snprintfz(var_name, CONFIG_MAX_NAME, "ctokens chart for %s", d->id);
- d->enabled_ctokens = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_ctokens);
-
- snprintfz(var_name, CONFIG_MAX_NAME, "show all classes for %s", d->id);
- d->enabled_all_classes_qdiscs = (char)config_get_boolean_ondemand("plugin:tc", var_name, enabled_all_classes_qdiscs);
- }
-
- // we only need to add leaf classes
- struct tc_class *c, *x /*, *root = NULL */;
- unsigned long long bytes_sum = 0, packets_sum = 0, dropped_sum = 0, tokens_sum = 0, ctokens_sum = 0;
- int active_nodes = 0, updated_classes = 0, updated_qdiscs = 0;
-
- // prepare all classes
- // we set reasonable defaults for the rest of the code below
-
- for(c = d->classes ; c ; c = c->next) {
- c->render = 0; // do not render this class
-
- c->isleaf = 1; // this is a leaf class
- c->hasparent = 0; // without a parent
-
- if(unlikely(!c->updated))
- c->unupdated++; // increase its unupdated counter
- else {
- c->unupdated = 0; // reset its unupdated counter
-
- // count how many of each kind
- if(c->isqdisc)
- updated_qdiscs++;
- else
- updated_classes++;
- }
- }
-
- if(unlikely(!d->enabled || (!updated_classes && !updated_qdiscs))) {
- debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. It is not enabled/updated.", d->name?d->name:d->id);
- tc_device_classes_cleanup(d);
- return;
- }
-
- if(unlikely(updated_classes && updated_qdiscs)) {
- error("TC: device '%s' has active both classes (%d) and qdiscs (%d). Will render only qdiscs.", d->id, updated_classes, updated_qdiscs);
-
- // set all classes to !updated
- for(c = d->classes ; c ; c = c->next)
- if(unlikely(!c->isqdisc && c->updated))
- c->updated = 0;
-
- updated_classes = 0;
- }
-
- // mark the classes as leafs and parents
- //
- // TC is hierarchical:
- // - classes can have other classes in them
- // - the same is true for qdiscs (i.e. qdiscs have classes, that have other qdiscs)
- //
- // we need to present a chart with leaf nodes only, so that the sum
- // of all dimensions of the chart, will be the total utilization
- // of the interface.
- //
- // here we try to find the ones we need to report
- // by default all nodes are marked with: isleaf = 1 (see above)
- //
- // so, here we remove the isleaf flag from nodes in the middle
- // and we add the hasparent flag to leaf nodes we found their parent
- if(likely(!d->enabled_all_classes_qdiscs)) {
- for(c = d->classes; c; c = c->next) {
- if(unlikely(!c->updated)) continue;
-
- //debug(D_TC_LOOP, "TC: In device '%s', %s '%s' has leafid: '%s' and parentid '%s'.",
- // d->id,
- // c->isqdisc?"qdisc":"class",
- // c->id,
- // c->leafid?c->leafid:"NULL",
- // c->parentid?c->parentid:"NULL");
-
- // find if c is leaf or not
- for(x = d->classes; x; x = x->next) {
- if(unlikely(!x->updated || c == x || !x->parentid)) continue;
-
- // classes have both parentid and leafid
- // qdiscs have only parentid
- // the following works for both (it is an OR)
-
- if((c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
- (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0)) {
- // debug(D_TC_LOOP, "TC: In device '%s', %s '%s' (leafid: '%s') has as leaf %s '%s' (parentid: '%s').", d->name?d->name:d->id, c->isqdisc?"qdisc":"class", c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->isqdisc?"qdisc":"class", x->name?x->name:x->id, x->parentid?x->parentid:x->id);
- c->isleaf = 0;
- x->hasparent = 1;
- }
- }
- }
- }
-
- for(c = d->classes ; c ; c = c->next) {
- if(unlikely(!c->updated)) continue;
-
- // debug(D_TC_LOOP, "TC: device '%s', %s '%s' isleaf=%d, hasparent=%d", d->id, (c->isqdisc)?"qdisc":"class", c->id, c->isleaf, c->hasparent);
-
- if(unlikely((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs)) {
- c->render = 1;
- active_nodes++;
- bytes_sum += c->bytes;
- packets_sum += c->packets;
- dropped_sum += c->dropped;
- tokens_sum += c->tokens;
- ctokens_sum += c->ctokens;
- }
-
- //if(unlikely(!c->hasparent)) {
- // if(root) error("TC: multiple root class/qdisc for device '%s' (old: '%s', new: '%s')", d->id, root->id, c->id);
- // root = c;
- // debug(D_TC_LOOP, "TC: found root class/qdisc '%s'", root->id);
- //}
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- // dump all the list to see what we know
-
- if(unlikely(debug_flags & D_TC_LOOP)) {
- for(c = d->classes ; c ; c = c->next) {
- if(c->render) debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, OK", d->name, c->id);
- else debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, IGNORE (updated: %d, isleaf: %d, hasparent: %d, parent: %s)", d->name?d->name:d->id, c->id, c->updated, c->isleaf, c->hasparent, c->parentid?c->parentid:"(unset)");
- }
- }
-#endif
-
- if(unlikely(!active_nodes)) {
- debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No useful classes/qdiscs.", d->name?d->name:d->id);
- tc_device_classes_cleanup(d);
- return;
- }
-
- debug(D_TC_LOOP, "TC: evaluating TC device '%s'. enabled = %d/%d (bytes: %d/%d, packets: %d/%d, dropped: %d/%d, tokens: %d/%d, ctokens: %d/%d, all_classes_qdiscs: %d/%d), classes: (bytes = %llu, packets = %llu, dropped = %llu, tokens = %llu, ctokens = %llu).",
- d->name?d->name:d->id,
- d->enabled, enable_new_interfaces,
- d->enabled_bytes, enable_bytes,
- d->enabled_packets, enable_packets,
- d->enabled_dropped, enable_dropped,
- d->enabled_tokens, enable_tokens,
- d->enabled_ctokens, enable_ctokens,
- d->enabled_all_classes_qdiscs, enabled_all_classes_qdiscs,
- bytes_sum,
- packets_sum,
- dropped_sum,
- tokens_sum,
- ctokens_sum
- );
-
- // --------------------------------------------------------------------
- // bytes
-
- if(d->enabled_bytes == CONFIG_BOOLEAN_YES || (d->enabled_bytes == CONFIG_BOOLEAN_AUTO && bytes_sum)) {
- d->enabled_bytes = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_bytes))
- d->st_bytes = rrdset_create_localhost(
- RRD_TYPE_TC
- , d->id
- , d->name ? d->name : d->id
- , d->family ? d->family : d->id
- , RRD_TYPE_TC ".qos"
- , "Class Usage"
- , "kilobits/s"
- , "tc"
- , NULL
- , 7000
- , localhost->rrd_update_every
- , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED
- );
-
- else {
- rrdset_next(d->st_bytes);
- if(unlikely(d->name_updated)) rrdset_set_name(d->st_bytes, d->name);
-
- // FIXME
- // update the family
- }
-
- for(c = d->classes ; c ; c = c->next) {
- if(unlikely(!c->render)) continue;
-
- if(unlikely(!c->rd_bytes))
- c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- else if(unlikely(c->name_updated))
- rrddim_set_name(d->st_bytes, c->rd_bytes, c->name);
-
- rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes);
- }
- rrdset_done(d->st_bytes);
- }
-
- // --------------------------------------------------------------------
- // packets
-
- if(d->enabled_packets == CONFIG_BOOLEAN_YES || (d->enabled_packets == CONFIG_BOOLEAN_AUTO && packets_sum)) {
- d->enabled_packets = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_packets)) {
- char id[RRD_ID_LENGTH_MAX + 1];
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id);
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id);
-
- d->st_packets = rrdset_create_localhost(
- RRD_TYPE_TC
- , id
- , name
- , d->family ? d->family : d->id
- , RRD_TYPE_TC ".qos_packets"
- , "Class Packets"
- , "packets/s"
- , "tc"
- , NULL
- , 7010
- , localhost->rrd_update_every
- , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED
- );
- }
- else {
- rrdset_next(d->st_packets);
-
- if(unlikely(d->name_updated)) {
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id);
- rrdset_set_name(d->st_packets, name);
- }
-
- // FIXME
- // update the family
- }
-
- for(c = d->classes ; c ; c = c->next) {
- if(unlikely(!c->render)) continue;
-
- if(unlikely(!c->rd_packets))
- c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- else if(unlikely(c->name_updated))
- rrddim_set_name(d->st_packets, c->rd_packets, c->name);
-
- rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets);
- }
- rrdset_done(d->st_packets);
- }
-
- // --------------------------------------------------------------------
- // dropped
-
- if(d->enabled_dropped == CONFIG_BOOLEAN_YES || (d->enabled_dropped == CONFIG_BOOLEAN_AUTO && dropped_sum)) {
- d->enabled_dropped = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_dropped)) {
- char id[RRD_ID_LENGTH_MAX + 1];
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id);
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id);
-
- d->st_dropped = rrdset_create_localhost(
- RRD_TYPE_TC
- , id
- , name
- , d->family ? d->family : d->id
- , RRD_TYPE_TC ".qos_dropped"
- , "Class Dropped Packets"
- , "packets/s"
- , "tc"
- , NULL
- , 7020
- , localhost->rrd_update_every
- , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED
- );
- }
- else {
- rrdset_next(d->st_dropped);
-
- if(unlikely(d->name_updated)) {
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id);
- rrdset_set_name(d->st_dropped, name);
- }
-
- // FIXME
- // update the family
- }
-
- for(c = d->classes ; c ; c = c->next) {
- if(unlikely(!c->render)) continue;
-
- if(unlikely(!c->rd_dropped))
- c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- else if(unlikely(c->name_updated))
- rrddim_set_name(d->st_dropped, c->rd_dropped, c->name);
-
- rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped);
- }
- rrdset_done(d->st_dropped);
- }
-
- // --------------------------------------------------------------------
- // tokens
-
- if(d->enabled_tokens == CONFIG_BOOLEAN_YES || (d->enabled_tokens == CONFIG_BOOLEAN_AUTO && tokens_sum)) {
- d->enabled_tokens = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_tokens)) {
- char id[RRD_ID_LENGTH_MAX + 1];
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(id, RRD_ID_LENGTH_MAX, "%s_tokens", d->id);
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id);
-
- d->st_tokens = rrdset_create_localhost(
- RRD_TYPE_TC
- , id
- , name
- , d->family ? d->family : d->id
- , RRD_TYPE_TC ".qos_tokens"
- , "Class Tokens"
- , "tokens"
- , "tc"
- , NULL
- , 7030
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
- }
- else {
- rrdset_next(d->st_tokens);
-
- if(unlikely(d->name_updated)) {
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id);
- rrdset_set_name(d->st_tokens, name);
- }
-
- // FIXME
- // update the family
- }
-
- for(c = d->classes ; c ; c = c->next) {
- if(unlikely(!c->render)) continue;
-
- if(unlikely(!c->rd_tokens)) {
- c->rd_tokens = rrddim_add(d->st_tokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else if(unlikely(c->name_updated))
- rrddim_set_name(d->st_tokens, c->rd_tokens, c->name);
-
- rrddim_set_by_pointer(d->st_tokens, c->rd_tokens, c->tokens);
- }
- rrdset_done(d->st_tokens);
- }
-
- // --------------------------------------------------------------------
- // ctokens
-
- if(d->enabled_ctokens == CONFIG_BOOLEAN_YES || (d->enabled_ctokens == CONFIG_BOOLEAN_AUTO && ctokens_sum)) {
- d->enabled_ctokens = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_ctokens)) {
- char id[RRD_ID_LENGTH_MAX + 1];
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(id, RRD_ID_LENGTH_MAX, "%s_ctokens", d->id);
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id);
-
- d->st_ctokens = rrdset_create_localhost(
- RRD_TYPE_TC
- , id
- , name
- , d->family ? d->family : d->id
- , RRD_TYPE_TC ".qos_ctokens"
- , "Class cTokens"
- , "ctokens"
- , "tc"
- , NULL
- , 7040
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
- }
- else {
- debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", d->name?d->name:d->id);
- rrdset_next(d->st_ctokens);
-
- if(unlikely(d->name_updated)) {
- char name[RRD_ID_LENGTH_MAX + 1];
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id);
- rrdset_set_name(d->st_ctokens, name);
- }
-
- // FIXME
- // update the family
- }
-
- for(c = d->classes ; c ; c = c->next) {
- if(unlikely(!c->render)) continue;
-
- if(unlikely(!c->rd_ctokens))
- c->rd_ctokens = rrddim_add(d->st_ctokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- else if(unlikely(c->name_updated))
- rrddim_set_name(d->st_ctokens, c->rd_ctokens, c->name);
-
- rrddim_set_by_pointer(d->st_ctokens, c->rd_ctokens, c->ctokens);
- }
- rrdset_done(d->st_ctokens);
- }
-
- tc_device_classes_cleanup(d);
-}
-
-static inline void tc_device_set_class_name(struct tc_device *d, char *id, char *name) {
- if(unlikely(!name || !*name)) return;
-
- struct tc_class *c = tc_class_index_find(d, id, 0);
- if(likely(c)) {
- if(likely(c->name)) {
- if(!strcmp(c->name, name)) return;
- freez(c->name);
- c->name = NULL;
- }
-
- if(likely(name && *name && strcmp(c->id, name) != 0)) {
- debug(D_TC_LOOP, "TC: Setting device '%s', class '%s' name to '%s'", d->id, id, name);
- c->name = strdupz(name);
- c->name_updated = 1;
- }
- }
-}
-
-static inline void tc_device_set_device_name(struct tc_device *d, char *name) {
- if(unlikely(!name || !*name)) return;
-
- if(d->name) {
- if(!strcmp(d->name, name)) return;
- freez(d->name);
- d->name = NULL;
- }
-
- if(likely(name && *name && strcmp(d->id, name) != 0)) {
- debug(D_TC_LOOP, "TC: Setting device '%s' name to '%s'", d->id, name);
- d->name = strdupz(name);
- d->name_updated = 1;
- }
-}
-
-static inline void tc_device_set_device_family(struct tc_device *d, char *family) {
- freez(d->family);
- d->family = NULL;
-
- if(likely(family && *family && strcmp(d->id, family) != 0)) {
- debug(D_TC_LOOP, "TC: Setting device '%s' family to '%s'", d->id, family);
- d->family = strdupz(family);
- d->family_updated = 1;
- }
- // no need for null termination - it is already null
-}
-
-static inline struct tc_device *tc_device_create(char *id)
-{
- struct tc_device *d = tc_device_index_find(id, 0);
-
- if(!d) {
- debug(D_TC_LOOP, "TC: Creating device '%s'", id);
-
- d = callocz(1, sizeof(struct tc_device));
-
- d->id = strdupz(id);
- d->hash = simple_hash(d->id);
- d->enabled = (char)-1;
-
- avl_init(&d->classes_index, tc_class_compare);
- if(unlikely(tc_device_index_add(d) != d))
- error("plugin_tc: INTERNAL ERROR: removing device '%s' removed a different device.", d->id);
-
- if(!tc_device_root) {
- tc_device_root = d;
- }
- else {
- d->next = tc_device_root;
- tc_device_root->prev = d;
- tc_device_root = d;
- }
- }
-
- return(d);
-}
-
-static inline struct tc_class *tc_class_add(struct tc_device *n, char *id, char qdisc, char *parentid, char *leafid)
-{
- struct tc_class *c = tc_class_index_find(n, id, 0);
-
- if(!c) {
- debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", n->id, id, parentid?parentid:"", leafid?leafid:"");
-
- c = callocz(1, sizeof(struct tc_class));
-
- if(unlikely(!n->classes))
- n->classes = c;
-
- else if(likely(n->last_class)) {
- n->last_class->next = c;
- c->prev = n->last_class;
- }
-
- n->last_class = c;
-
- c->id = strdupz(id);
- c->hash = simple_hash(c->id);
-
- c->isqdisc = qdisc;
- if(parentid && *parentid) {
- c->parentid = strdupz(parentid);
- c->parent_hash = simple_hash(c->parentid);
- }
-
- if(leafid && *leafid) {
- c->leafid = strdupz(leafid);
- c->leaf_hash = simple_hash(c->leafid);
- }
-
- if(unlikely(tc_class_index_add(n, c) != c))
- error("plugin_tc: INTERNAL ERROR: attempt index class '%s' on device '%s': already exists", c->id, n->id);
- }
- return(c);
-}
-
-static inline void tc_device_free(struct tc_device *n)
-{
- if(n->next) n->next->prev = n->prev;
- if(n->prev) n->prev->next = n->next;
- if(tc_device_root == n) {
- if(n->next) tc_device_root = n->next;
- else tc_device_root = n->prev;
- }
-
- if(unlikely(tc_device_index_del(n) != n))
- error("plugin_tc: INTERNAL ERROR: removing device '%s' removed a different device.", n->id);
-
- while(n->classes) tc_class_free(n, n->classes);
-
- freez(n->id);
- freez(n->name);
- freez(n->family);
- freez(n);
-}
-
-static inline void tc_device_free_all()
-{
- while(tc_device_root)
- tc_device_free(tc_device_root);
-}
-
-#define PLUGINSD_MAX_WORDS 20
-
-static inline int tc_space(char c) {
- switch(c) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- return 1;
-
- default:
- return 0;
- }
-}
-
-static inline void tc_split_words(char *str, char **words, int max_words) {
- char *s = str;
- int i = 0;
-
- // skip all white space
- while(tc_space(*s)) s++;
-
- // store the first word
- words[i++] = s;
-
- // while we have something
- while(*s) {
- // if it is a space
- if(unlikely(tc_space(*s))) {
-
- // terminate the word
- *s++ = '\0';
-
- // skip all white space
- while(tc_space(*s)) s++;
-
- // if we reached the end, stop
- if(!*s) break;
-
- // store the next word
- if(i < max_words) words[i++] = s;
- else break;
- }
- else s++;
- }
-
- // terminate the words
- while(i < max_words) words[i++] = NULL;
-}
-
-static pid_t tc_child_pid = 0;
-
-static void tc_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- if(tc_child_pid) {
- info("TC: killing with SIGTERM tc-qos-helper process %d", tc_child_pid);
- if(killpid(tc_child_pid, SIGTERM) != -1) {
- siginfo_t info;
-
- info("TC: waiting for tc plugin child process pid %d to exit...", tc_child_pid);
- waitid(P_PID, (id_t) tc_child_pid, &info, WEXITED);
- // info("TC: finished tc plugin child process pid %d.", tc_child_pid);
- }
-
- tc_child_pid = 0;
- }
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *tc_main(void *ptr) {
- netdata_thread_cleanup_push(tc_main_cleanup, ptr);
-
- struct rusage thread;
-
- char buffer[TC_LINE_MAX+1] = "";
- char *words[PLUGINSD_MAX_WORDS] = { NULL };
-
- uint32_t BEGIN_HASH = simple_hash("BEGIN");
- uint32_t END_HASH = simple_hash("END");
- uint32_t QDISC_HASH = simple_hash("qdisc");
- uint32_t CLASS_HASH = simple_hash("class");
- uint32_t SENT_HASH = simple_hash("Sent");
- uint32_t LENDED_HASH = simple_hash("lended:");
- uint32_t TOKENS_HASH = simple_hash("tokens:");
- uint32_t SETDEVICENAME_HASH = simple_hash("SETDEVICENAME");
- uint32_t SETDEVICEGROUP_HASH = simple_hash("SETDEVICEGROUP");
- uint32_t SETCLASSNAME_HASH = simple_hash("SETCLASSNAME");
- uint32_t WORKTIME_HASH = simple_hash("WORKTIME");
-#ifdef DETACH_PLUGINS_FROM_NETDATA
- uint32_t MYPID_HASH = simple_hash("MYPID");
-#endif
- uint32_t first_hash;
-
- snprintfz(buffer, TC_LINE_MAX, "%s/tc-qos-helper.sh", netdata_configured_plugins_dir);
- char *tc_script = config_get("plugin:tc", "script to run to get tc values", buffer);
-
- while(!netdata_exit) {
- FILE *fp;
- struct tc_device *device = NULL;
- struct tc_class *class = NULL;
-
- snprintfz(buffer, TC_LINE_MAX, "exec %s %d", tc_script, localhost->rrd_update_every);
- debug(D_TC_LOOP, "executing '%s'", buffer);
-
- fp = mypopen(buffer, (pid_t *)&tc_child_pid);
- if(unlikely(!fp)) {
- error("TC: Cannot popen(\"%s\", \"r\").", buffer);
- goto cleanup;
- }
-
- while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
- if(unlikely(netdata_exit)) break;
-
- buffer[TC_LINE_MAX] = '\0';
- // debug(D_TC_LOOP, "TC: read '%s'", buffer);
-
- tc_split_words(buffer, words, PLUGINSD_MAX_WORDS);
-
- if(unlikely(!words[0] || !*words[0])) {
- // debug(D_TC_LOOP, "empty line");
- continue;
- }
- // else debug(D_TC_LOOP, "First word is '%s'", words[0]);
-
- first_hash = simple_hash(words[0]);
-
- if(unlikely(device && ((first_hash == CLASS_HASH && strcmp(words[0], "class") == 0) || (first_hash == QDISC_HASH && strcmp(words[0], "qdisc") == 0)))) {
- // debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);
-
- char *type = words[1]; // the class/qdisc type: htb, fq_codel, etc
- char *id = words[2]; // the class/qdisc major:minor
- char *parent = words[3]; // the word 'parent' or 'root'
- char *parentid = words[4]; // parentid
- char *leaf = words[5]; // the word 'leaf'
- char *leafid = words[6]; // leafid
-
- int parent_is_root = 0;
- int parent_is_parent = 0;
- if(likely(parent)) {
- parent_is_parent = !strcmp(parent, "parent");
-
- if(!parent_is_parent)
- parent_is_root = !strcmp(parent, "root");
- }
-
- if(likely(type && id && (parent_is_root || parent_is_parent))) {
- char qdisc = 0;
-
- if(first_hash == QDISC_HASH) {
- qdisc = 1;
-
- if(!strcmp(type, "ingress")) {
- // we don't want to get the ingress qdisc
- // there should be an IFB interface for this
-
- class = NULL;
- continue;
- }
-
- if(parent_is_parent && parentid) {
- // eliminate the minor number from parentid
- // why: parentid is the id of the parent class
- // but major: is also the id of the parent qdisc
-
- char *s = parentid;
- while(*s && *s != ':') s++;
- if(*s == ':') s[1] = '\0';
- }
- }
-
- if(parent_is_root) {
- parentid = NULL;
- leafid = NULL;
- }
- else if(!leaf || strcmp(leaf, "leaf") != 0)
- leafid = NULL;
-
- char leafbuf[20 + 1] = "";
- if(leafid && leafid[strlen(leafid) - 1] == ':') {
- strncpyz(leafbuf, leafid, 20 - 1);
- strcat(leafbuf, "1");
- leafid = leafbuf;
- }
-
- class = tc_class_add(device, id, qdisc, parentid, leafid);
- }
- else {
- // clear the last class
- class = NULL;
- }
- }
- else if(unlikely(first_hash == END_HASH && strcmp(words[0], "END") == 0)) {
- // debug(D_TC_LOOP, "END line");
-
- if(likely(device)) {
- netdata_thread_disable_cancelability();
- tc_device_commit(device);
- // tc_device_free(device);
- netdata_thread_enable_cancelability();
- }
-
- device = NULL;
- class = NULL;
- }
- else if(unlikely(first_hash == BEGIN_HASH && strcmp(words[0], "BEGIN") == 0)) {
- // debug(D_TC_LOOP, "BEGIN line on device '%s'", words[1]);
-
- if(likely(words[1] && *words[1])) {
- device = tc_device_create(words[1]);
- }
- else {
- // tc_device_free(device);
- device = NULL;
- }
-
- class = NULL;
- }
- else if(unlikely(device && class && first_hash == SENT_HASH && strcmp(words[0], "Sent") == 0)) {
- // debug(D_TC_LOOP, "SENT line '%s'", words[1]);
- if(likely(words[1] && *words[1])) {
- class->bytes = str2ull(words[1]);
- class->updated = 1;
- }
- else {
- class->updated = 0;
- }
-
- if(likely(words[3] && *words[3]))
- class->packets = str2ull(words[3]);
-
- if(likely(words[6] && *words[6]))
- class->dropped = str2ull(words[6]);
-
- if(likely(words[8] && *words[8]))
- class->overlimits = str2ull(words[8]);
-
- if(likely(words[10] && *words[10]))
- class->requeues = str2ull(words[8]);
- }
- else if(unlikely(device && class && class->updated && first_hash == LENDED_HASH && strcmp(words[0], "lended:") == 0)) {
- // debug(D_TC_LOOP, "LENDED line '%s'", words[1]);
- if(likely(words[1] && *words[1]))
- class->lended = str2ull(words[1]);
-
- if(likely(words[3] && *words[3]))
- class->borrowed = str2ull(words[3]);
-
- if(likely(words[5] && *words[5]))
- class->giants = str2ull(words[5]);
- }
- else if(unlikely(device && class && class->updated && first_hash == TOKENS_HASH && strcmp(words[0], "tokens:") == 0)) {
- // debug(D_TC_LOOP, "TOKENS line '%s'", words[1]);
- if(likely(words[1] && *words[1]))
- class->tokens = str2ull(words[1]);
-
- if(likely(words[3] && *words[3]))
- class->ctokens = str2ull(words[3]);
- }
- else if(unlikely(device && first_hash == SETDEVICENAME_HASH && strcmp(words[0], "SETDEVICENAME") == 0)) {
- // debug(D_TC_LOOP, "SETDEVICENAME line '%s'", words[1]);
- if(likely(words[1] && *words[1]))
- tc_device_set_device_name(device, words[1]);
- }
- else if(unlikely(device && first_hash == SETDEVICEGROUP_HASH && strcmp(words[0], "SETDEVICEGROUP") == 0)) {
- // debug(D_TC_LOOP, "SETDEVICEGROUP line '%s'", words[1]);
- if(likely(words[1] && *words[1]))
- tc_device_set_device_family(device, words[1]);
- }
- else if(unlikely(device && first_hash == SETCLASSNAME_HASH && strcmp(words[0], "SETCLASSNAME") == 0)) {
- // debug(D_TC_LOOP, "SETCLASSNAME line '%s' '%s'", words[1], words[2]);
- char *id = words[1];
- char *path = words[2];
- if(likely(id && *id && path && *path))
- tc_device_set_class_name(device, id, path);
- }
- else if(unlikely(first_hash == WORKTIME_HASH && strcmp(words[0], "WORKTIME") == 0)) {
- // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]);
- getrusage(RUSAGE_THREAD, &thread);
-
- static RRDSET *stcpu = NULL;
- static RRDDIM *rd_user = NULL, *rd_system = NULL;
-
- if(unlikely(!stcpu)) {
- stcpu = rrdset_create_localhost(
- "netdata"
- , "plugin_tc_cpu"
- , NULL
- , "tc.helper"
- , NULL
- , "NetData TC CPU usage"
- , "milliseconds/s"
- , "tc"
- , NULL
- , 135000
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
- rd_user = rrddim_add(stcpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rd_system = rrddim_add(stcpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(stcpu);
-
- rrddim_set_by_pointer(stcpu, rd_user , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
- rrddim_set_by_pointer(stcpu, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
- rrdset_done(stcpu);
-
- static RRDSET *sttime = NULL;
- static RRDDIM *rd_run_time = NULL;
-
- if(unlikely(!sttime)) {
- sttime = rrdset_create_localhost(
- "netdata"
- , "plugin_tc_time"
- , NULL
- , "tc.helper"
- , NULL
- , "NetData TC script execution"
- , "milliseconds/run"
- , "tc"
- , NULL
- , 135001
- , localhost->rrd_update_every
- , RRDSET_TYPE_AREA
- );
- rd_run_time = rrddim_add(sttime, "run_time", "run time", 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(sttime);
-
- rrddim_set_by_pointer(sttime, rd_run_time, str2ll(words[1], NULL));
- rrdset_done(sttime);
-
- }
-#ifdef DETACH_PLUGINS_FROM_NETDATA
- else if(unlikely(first_hash == MYPID_HASH && (strcmp(words[0], "MYPID") == 0))) {
- // debug(D_TC_LOOP, "MYPID line '%s'", words[1]);
- char *id = words[1];
- pid_t pid = atol(id);
-
- if(likely(pid)) tc_child_pid = pid;
-
- debug(D_TC_LOOP, "TC: Child PID is %d.", tc_child_pid);
- }
-#endif
- //else {
- // debug(D_TC_LOOP, "IGNORED line");
- //}
- }
-
- // fgets() failed or loop broke
- int code = mypclose(fp, (pid_t)tc_child_pid);
- tc_child_pid = 0;
-
- if(unlikely(device)) {
- // tc_device_free(device);
- device = NULL;
- class = NULL;
- }
-
- if(unlikely(netdata_exit)) {
- tc_device_free_all();
- goto cleanup;
- }
-
- if(code == 1 || code == 127) {
- // 1 = DISABLE
- // 127 = cannot even run it
- error("TC: tc-qos-helper.sh exited with code %d. Disabling it.", code);
-
- tc_device_free_all();
- goto cleanup;
- }
-
- sleep((unsigned int) localhost->rrd_update_every);
- }
-
-cleanup: ; // added semi-colon to prevent older gcc error: label at end of compound statement
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/plugin_tc.h b/src/plugin_tc.h
deleted file mode 100644
index 792c6496f..000000000
--- a/src/plugin_tc.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef NETDATA_PLUGIN_TC_H
-#define NETDATA_PLUGIN_TC_H 1
-
-extern void *tc_main(void *ptr);
-
-#endif /* NETDATA_PLUGIN_TC_H */
-
diff --git a/src/plugins_d.c b/src/plugins_d.c
deleted file mode 100644
index 5693dda06..000000000
--- a/src/plugins_d.c
+++ /dev/null
@@ -1,694 +0,0 @@
-#include "common.h"
-
-char *plugin_directories[PLUGINSD_MAX_DIRECTORIES] = { NULL };
-char *netdata_configured_plugins_dir_base;
-
-struct plugind *pluginsd_root = NULL;
-
-static inline int pluginsd_space(char c) {
- switch(c) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case '=':
- return 1;
-
- default:
- return 0;
- }
-}
-
-inline int config_isspace(char c) {
- switch(c) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case ',':
- return 1;
-
- default:
- return 0;
- }
-}
-
-// split a text into words, respecting quotes
-inline int quoted_strings_splitter(char *str, char **words, int max_words, int (*custom_isspace)(char)) {
- char *s = str, quote = 0;
- int i = 0, j;
-
- // skip all white space
- while(unlikely(custom_isspace(*s))) s++;
-
- // check for quote
- if(unlikely(*s == '\'' || *s == '"')) {
- quote = *s; // remember the quote
- s++; // skip the quote
- }
-
- // store the first word
- words[i++] = s;
-
- // while we have something
- while(likely(*s)) {
- // if it is escape
- if(unlikely(*s == '\\' && s[1])) {
- s += 2;
- continue;
- }
-
- // if it is quote
- else if(unlikely(*s == quote)) {
- quote = 0;
- *s = ' ';
- continue;
- }
-
- // if it is a space
- else if(unlikely(quote == 0 && custom_isspace(*s))) {
-
- // terminate the word
- *s++ = '\0';
-
- // skip all white space
- while(likely(custom_isspace(*s))) s++;
-
- // check for quote
- if(unlikely(*s == '\'' || *s == '"')) {
- quote = *s; // remember the quote
- s++; // skip the quote
- }
-
- // if we reached the end, stop
- if(unlikely(!*s)) break;
-
- // store the next word
- if(likely(i < max_words)) words[i++] = s;
- else break;
- }
-
- // anything else
- else s++;
- }
-
- // terminate the words
- j = i;
- while(likely(j < max_words)) words[j++] = NULL;
-
- return i;
-}
-
-inline int pluginsd_split_words(char *str, char **words, int max_words) {
- return quoted_strings_splitter(str, words, max_words, pluginsd_space);
-}
-
-inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations) {
- int enabled = cd->enabled;
-
- if(!fp || !enabled) {
- cd->enabled = 0;
- return 0;
- }
-
- size_t count = 0;
-
- char line[PLUGINSD_LINE_MAX + 1];
-
- char *words[PLUGINSD_MAX_WORDS] = { NULL };
- uint32_t BEGIN_HASH = simple_hash(PLUGINSD_KEYWORD_BEGIN);
- uint32_t END_HASH = simple_hash(PLUGINSD_KEYWORD_END);
- uint32_t FLUSH_HASH = simple_hash(PLUGINSD_KEYWORD_FLUSH);
- uint32_t CHART_HASH = simple_hash(PLUGINSD_KEYWORD_CHART);
- uint32_t DIMENSION_HASH = simple_hash(PLUGINSD_KEYWORD_DIMENSION);
- uint32_t DISABLE_HASH = simple_hash(PLUGINSD_KEYWORD_DISABLE);
- uint32_t VARIABLE_HASH = simple_hash(PLUGINSD_KEYWORD_VARIABLE);
-
- RRDSET *st = NULL;
- uint32_t hash;
-
- errno = 0;
- clearerr(fp);
-
- if(unlikely(fileno(fp) == -1)) {
- error("file descriptor given is not a valid stream");
- goto cleanup;
- }
-
- while(!ferror(fp)) {
- if(unlikely(netdata_exit)) break;
-
- char *r = fgets(line, PLUGINSD_LINE_MAX, fp);
- if(unlikely(!r)) {
- error("read failed");
- break;
- }
-
- if(unlikely(netdata_exit)) break;
-
- line[PLUGINSD_LINE_MAX] = '\0';
-
- int w = pluginsd_split_words(line, words, PLUGINSD_MAX_WORDS);
- char *s = words[0];
- if(unlikely(!s || !*s || !w)) {
- continue;
- }
-
- // debug(D_PLUGINSD, "PLUGINSD: words 0='%s' 1='%s' 2='%s' 3='%s' 4='%s' 5='%s' 6='%s' 7='%s' 8='%s' 9='%s'", words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]);
-
- if(likely(!simple_hash_strcmp(s, "SET", &hash))) {
- char *dimension = words[1];
- char *value = words[2];
-
- if(unlikely(!dimension || !*dimension)) {
- error("requested a SET on chart '%s' of host '%s', without a dimension. Disabling it.", st->id, host->hostname);
- enabled = 0;
- break;
- }
-
- if(unlikely(!value || !*value)) value = NULL;
-
- if(unlikely(!st)) {
- error("requested a SET on dimension %s with value %s on host '%s', without a BEGIN. Disabling it.", dimension, value?value:"<nothing>", host->hostname);
- enabled = 0;
- break;
- }
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
- debug(D_PLUGINSD, "is setting dimension %s/%s to %s", st->id, dimension, value?value:"<nothing>");
-
- if(value) {
- RRDDIM *rd = rrddim_find(st, dimension);
- if(unlikely(!rd)) {
- error("requested a SET to dimension with id '%s' on stats '%s' (%s) on host '%s', which does not exist. Disabling it.", dimension, st->name, st->id, st->rrdhost->hostname);
- enabled = 0;
- break;
- }
- else
- rrddim_set_by_pointer(st, rd, strtoll(value, NULL, 0));
- }
- }
- else if(likely(hash == BEGIN_HASH && !strcmp(s, PLUGINSD_KEYWORD_BEGIN))) {
- char *id = words[1];
- char *microseconds_txt = words[2];
-
- if(unlikely(!id)) {
- error("requested a BEGIN without a chart id for host '%s'. Disabling it.", host->hostname);
- enabled = 0;
- break;
- }
-
- st = rrdset_find(host, id);
- if(unlikely(!st)) {
- error("requested a BEGIN on chart '%s', which does not exist on host '%s'. Disabling it.", id, host->hostname);
- enabled = 0;
- break;
- }
-
- if(likely(st->counter_done)) {
- usec_t microseconds = 0;
- if(microseconds_txt && *microseconds_txt) microseconds = str2ull(microseconds_txt);
-
- if(likely(microseconds)) {
- if(trust_durations)
- rrdset_next_usec_unfiltered(st, microseconds);
- else
- rrdset_next_usec(st, microseconds);
- }
- else rrdset_next(st);
- }
- }
- else if(likely(hash == END_HASH && !strcmp(s, PLUGINSD_KEYWORD_END))) {
- if(unlikely(!st)) {
- error("requested an END, without a BEGIN on host '%s'. Disabling it.", host->hostname);
- enabled = 0;
- break;
- }
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
- debug(D_PLUGINSD, "requested an END on chart %s", st->id);
-
- rrdset_done(st);
- st = NULL;
-
- count++;
- }
- else if(likely(hash == CHART_HASH && !strcmp(s, PLUGINSD_KEYWORD_CHART))) {
- st = NULL;
-
- char *type = words[1];
- char *name = words[2];
- char *title = words[3];
- char *units = words[4];
- char *family = words[5];
- char *context = words[6];
- char *chart = words[7];
- char *priority_s = words[8];
- char *update_every_s = words[9];
- char *options = words[10];
- char *plugin = words[11];
- char *module = words[12];
-
- // parse the id from type
- char *id = NULL;
- if(likely(type && (id = strchr(type, '.')))) {
- *id = '\0';
- id++;
- }
-
- // make sure we have the required variables
- if(unlikely(!type || !*type || !id || !*id)) {
- error("requested a CHART, without a type.id, on host '%s'. Disabling it.", host->hostname);
- enabled = 0;
- break;
- }
-
- // parse the name, and make sure it does not include 'type.'
- if(unlikely(name && *name)) {
- // when data are coming from slaves
- // name will be type.name
- // so we have to remove 'type.' from name too
- size_t len = strlen(type);
- if(strncmp(type, name, len) == 0 && name[len] == '.')
- name = &name[len + 1];
-
- // if the name is the same with the id,
- // or is just 'NULL', clear it.
- if(unlikely(strcmp(name, id) == 0 || strcasecmp(name, "NULL") == 0 || strcasecmp(name, "(NULL)") == 0))
- name = NULL;
- }
-
- int priority = 1000;
- if(likely(priority_s && *priority_s)) priority = str2i(priority_s);
-
- int update_every = cd->update_every;
- if(likely(update_every_s && *update_every_s)) update_every = str2i(update_every_s);
- if(unlikely(!update_every)) update_every = cd->update_every;
-
- RRDSET_TYPE chart_type = RRDSET_TYPE_LINE;
- if(unlikely(chart)) chart_type = rrdset_type_id(chart);
-
- if(unlikely(name && !*name)) name = NULL;
- if(unlikely(family && !*family)) family = NULL;
- if(unlikely(context && !*context)) context = NULL;
- if(unlikely(!title)) title = "";
- if(unlikely(!units)) units = "unknown";
-
- debug(D_PLUGINSD, "creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d"
- , type, id
- , name?name:""
- , family?family:""
- , context?context:""
- , rrdset_type_name(chart_type)
- , priority
- , update_every
- );
-
- st = rrdset_create(
- host
- , type
- , id
- , name
- , family
- , context
- , title
- , units
- , (plugin && *plugin)?plugin:cd->filename
- , module
- , priority
- , update_every
- , chart_type
- );
-
- if(options && *options) {
- if(strstr(options, "obsolete"))
- rrdset_is_obsolete(st);
- else
- rrdset_isnot_obsolete(st);
-
- if(strstr(options, "detail"))
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
- else
- rrdset_flag_clear(st, RRDSET_FLAG_DETAIL);
-
- if(strstr(options, "hidden"))
- rrdset_flag_set(st, RRDSET_FLAG_HIDDEN);
- else
- rrdset_flag_clear(st, RRDSET_FLAG_HIDDEN);
-
- if(strstr(options, "store_first"))
- rrdset_flag_set(st, RRDSET_FLAG_STORE_FIRST);
- else
- rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
- }
- else {
- rrdset_isnot_obsolete(st);
- rrdset_flag_clear(st, RRDSET_FLAG_DETAIL);
- rrdset_flag_clear(st, RRDSET_FLAG_STORE_FIRST);
- }
- }
- else if(likely(hash == DIMENSION_HASH && !strcmp(s, PLUGINSD_KEYWORD_DIMENSION))) {
- char *id = words[1];
- char *name = words[2];
- char *algorithm = words[3];
- char *multiplier_s = words[4];
- char *divisor_s = words[5];
- char *options = words[6];
-
- if(unlikely(!id || !*id)) {
- error("requested a DIMENSION, without an id, host '%s' and chart '%s'. Disabling it.", host->hostname, st?st->id:"UNSET");
- enabled = 0;
- break;
- }
-
- if(unlikely(!st)) {
- error("requested a DIMENSION, without a CHART, on host '%s'. Disabling it.", host->hostname);
- enabled = 0;
- break;
- }
-
- long multiplier = 1;
- if(multiplier_s && *multiplier_s) multiplier = strtol(multiplier_s, NULL, 0);
- if(unlikely(!multiplier)) multiplier = 1;
-
- long divisor = 1;
- if(likely(divisor_s && *divisor_s)) divisor = strtol(divisor_s, NULL, 0);
- if(unlikely(!divisor)) divisor = 1;
-
- if(unlikely(!algorithm || !*algorithm)) algorithm = "absolute";
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
- debug(D_PLUGINSD, "creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'"
- , st->id
- , id
- , name?name:""
- , rrd_algorithm_name(rrd_algorithm_id(algorithm))
- , multiplier
- , divisor
- , options?options:""
- );
-
- RRDDIM *rd = rrddim_add(st, id, name, multiplier, divisor, rrd_algorithm_id(algorithm));
- rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN);
- rrddim_flag_clear(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
- if(options && *options) {
- if(strstr(options, "hidden") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN);
- if(strstr(options, "noreset") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
- if(strstr(options, "nooverflow") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS);
- }
- }
- else if(likely(hash == VARIABLE_HASH && !strcmp(s, PLUGINSD_KEYWORD_VARIABLE))) {
- char *name = words[1];
- char *value = words[2];
- int global = (st)?0:1;
-
- if(name && *name) {
- if((strcmp(name, "GLOBAL") == 0 || strcmp(name, "HOST") == 0)) {
- global = 1;
- name = words[2];
- value = words[3];
- }
- else if((strcmp(name, "LOCAL") == 0 || strcmp(name, "CHART") == 0)) {
- global = 0;
- name = words[2];
- value = words[3];
- }
- }
-
- if(unlikely(!name || !*name)) {
- error("requested a VARIABLE on host '%s', without a variable name. Disabling it.", host->hostname);
- enabled = 0;
- break;
- }
-
- if(unlikely(!value || !*value))
- value = NULL;
-
- if(value) {
- char *endptr = NULL;
- calculated_number v = (calculated_number)str2ld(value, &endptr);
-
- if(unlikely(endptr && *endptr)) {
- if(endptr == value)
- error("the value '%s' of VARIABLE '%s' on host '%s' cannot be parsed as a number", value, name, host->hostname);
- else
- error("the value '%s' of VARIABLE '%s' on host '%s' has leftovers: '%s'", value, name, host->hostname, endptr);
- }
-
- if(global) {
- RRDVAR *rv = rrdvar_custom_host_variable_create(host, name);
- if (rv) rrdvar_custom_host_variable_set(host, rv, v);
- else error("cannot find/create HOST VARIABLE '%s' on host '%s'", name, host->hostname);
- }
- else if(st) {
- RRDSETVAR *rs = rrdsetvar_custom_chart_variable_create(st, name);
- if (rs) rrdsetvar_custom_chart_variable_set(rs, v);
- else error("cannot find/create CHART VARIABLE '%s' on host '%s', chart '%s'", name, host->hostname, st->id);
- }
- else
- error("cannot find/create CHART VARIABLE '%s' on host '%s' without a chart", name, host->hostname);
- }
- else
- error("cannot set %s VARIABLE '%s' on host '%s' to an empty value", (global)?"HOST":"CHART", name, host->hostname);
- }
- else if(likely(hash == FLUSH_HASH && !strcmp(s, PLUGINSD_KEYWORD_FLUSH))) {
- debug(D_PLUGINSD, "requested a FLUSH");
- st = NULL;
- }
- else if(unlikely(hash == DISABLE_HASH && !strcmp(s, PLUGINSD_KEYWORD_DISABLE))) {
- info("called DISABLE. Disabling it.");
- enabled = 0;
- break;
- }
- else {
- error("sent command '%s' which is not known by netdata, for host '%s'. Disabling it.", s, host->hostname);
- enabled = 0;
- break;
- }
- }
-
-cleanup:
- cd->enabled = enabled;
-
- if(likely(count)) {
- cd->successful_collections += count;
- cd->serial_failures = 0;
- }
- else
- cd->serial_failures++;
-
- return count;
-}
-
-static void pluginsd_worker_thread_cleanup(void *arg) {
- struct plugind *cd = (struct plugind *)arg;
-
- if(cd->enabled && !cd->obsolete) {
- cd->obsolete = 1;
-
- info("data collection thread exiting");
-
- if (cd->pid) {
- siginfo_t info;
- info("killing child process pid %d", cd->pid);
- if (killpid(cd->pid, SIGTERM) != -1) {
- info("waiting for child process pid %d to exit...", cd->pid);
- waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
- }
- cd->pid = 0;
- }
- }
-}
-
-void *pluginsd_worker_thread(void *arg) {
- netdata_thread_cleanup_push(pluginsd_worker_thread_cleanup, arg);
-
- struct plugind *cd = (struct plugind *)arg;
-
- cd->obsolete = 0;
- size_t count = 0;
-
- while(!netdata_exit) {
- FILE *fp = mypopen(cd->cmd, &cd->pid);
- if(unlikely(!fp)) {
- error("Cannot popen(\"%s\", \"r\").", cd->cmd);
- break;
- }
-
- info("connected to '%s' running on pid %d", cd->fullfilename, cd->pid);
- count = pluginsd_process(localhost, cd, fp, 0);
- error("'%s' (pid %d) disconnected after %zu successful data collections (ENDs).", cd->fullfilename, cd->pid, count);
- killpid(cd->pid, SIGTERM);
-
- // get the return code
- int code = mypclose(fp, cd->pid);
-
- if(code != 0) {
- // the plugin reports failure
-
- if(likely(!cd->successful_collections)) {
- // nothing collected - disable it
- error("'%s' (pid %d) exited with error code %d. Disabling it.", cd->fullfilename, cd->pid, code);
- cd->enabled = 0;
- }
- else {
- // we have collected something
-
- if(likely(cd->serial_failures <= 10)) {
- error("'%s' (pid %d) exited with error code %d, but has given useful output in the past (%zu times). %s", cd->fullfilename, cd->pid, code, cd->successful_collections, cd->enabled?"Waiting a bit before starting it again.":"Will not start it again - it is disabled.");
- sleep((unsigned int) (cd->update_every * 10));
- }
- else {
- error("'%s' (pid %d) exited with error code %d, but has given useful output in the past (%zu times). We tried %zu times to restart it, but it failed to generate data. Disabling it.", cd->fullfilename, cd->pid, code, cd->successful_collections, cd->serial_failures);
- cd->enabled = 0;
- }
- }
- }
- else {
- // the plugin reports success
-
- if(unlikely(!cd->successful_collections)) {
- // we have collected nothing so far
-
- if(likely(cd->serial_failures <= 10)) {
- error("'%s' (pid %d) does not generate useful output but it reports success (exits with 0). %s.", cd->fullfilename, cd->pid, cd->enabled?"Waiting a bit before starting it again.":"Will not start it again - it is now disabled.");
- sleep((unsigned int) (cd->update_every * 10));
- }
- else {
- error("'%s' (pid %d) does not generate useful output, although it reports success (exits with 0), but we have tried %zu times to collect something. Disabling it.", cd->fullfilename, cd->pid, cd->serial_failures);
- cd->enabled = 0;
- }
- }
- else
- sleep((unsigned int) cd->update_every);
- }
- cd->pid = 0;
-
- if(unlikely(!cd->enabled)) break;
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-static void pluginsd_main_cleanup(void *data) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)data;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
- info("cleaning up...");
-
- struct plugind *cd;
- for (cd = pluginsd_root; cd; cd = cd->next) {
- if (cd->enabled && !cd->obsolete) {
- info("stopping plugin thread: %s", cd->id);
- netdata_thread_cancel(cd->thread);
- }
- }
-
- info("cleanup completed.");
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *pluginsd_main(void *ptr) {
- netdata_thread_cleanup_push(pluginsd_main_cleanup, ptr);
-
- int automatic_run = config_get_boolean(CONFIG_SECTION_PLUGINS, "enable running new plugins", 1);
- int scan_frequency = (int) config_get_number(CONFIG_SECTION_PLUGINS, "check for new plugins every", 60);
- if(scan_frequency < 1) scan_frequency = 1;
-
- // store the errno for each plugins directory
- // so that we don't log broken directories on each loop
- int directory_errors[PLUGINSD_MAX_DIRECTORIES] = { 0 };
-
- while(!netdata_exit) {
- int idx;
- const char *directory_name;
-
- for( idx = 0; idx < PLUGINSD_MAX_DIRECTORIES && (directory_name = plugin_directories[idx]) ; idx++ ) {
- if(unlikely(netdata_exit)) break;
-
- errno = 0;
- DIR *dir = opendir(directory_name);
- if(unlikely(!dir)) {
- if(directory_errors[idx] != errno) {
- directory_errors[idx] = errno;
- error("cannot open plugins directory '%s'", directory_name);
- }
- continue;
- }
-
- struct dirent *file = NULL;
- while(likely((file = readdir(dir)))) {
- if(unlikely(netdata_exit)) break;
-
- debug(D_PLUGINSD, "examining file '%s'", file->d_name);
-
- if(unlikely(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)) continue;
-
- int len = (int) strlen(file->d_name);
- if(unlikely(len <= (int)PLUGINSD_FILE_SUFFIX_LEN)) continue;
- if(unlikely(strcmp(PLUGINSD_FILE_SUFFIX, &file->d_name[len - (int)PLUGINSD_FILE_SUFFIX_LEN]) != 0)) {
- debug(D_PLUGINSD, "file '%s' does not end in '%s'", file->d_name, PLUGINSD_FILE_SUFFIX);
- continue;
- }
-
- char pluginname[CONFIG_MAX_NAME + 1];
- snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name);
- int enabled = config_get_boolean(CONFIG_SECTION_PLUGINS, pluginname, automatic_run);
-
- if(unlikely(!enabled)) {
- debug(D_PLUGINSD, "plugin '%s' is not enabled", file->d_name);
- continue;
- }
-
- // check if it runs already
- struct plugind *cd;
- for(cd = pluginsd_root ; cd ; cd = cd->next)
- if(unlikely(strcmp(cd->filename, file->d_name) == 0)) break;
-
- if(likely(cd && !cd->obsolete)) {
- debug(D_PLUGINSD, "plugin '%s' is already running", cd->filename);
- continue;
- }
-
- // it is not running
- // allocate a new one, or use the obsolete one
- if(unlikely(!cd)) {
- cd = callocz(sizeof(struct plugind), 1);
-
- snprintfz(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname);
-
- strncpyz(cd->filename, file->d_name, FILENAME_MAX);
- snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", directory_name, cd->filename);
-
- cd->enabled = enabled;
- cd->update_every = (int) config_get_number(cd->id, "update every", localhost->rrd_update_every);
- cd->started_t = now_realtime_sec();
-
- char *def = "";
- snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
-
- // link it
- if(likely(pluginsd_root)) cd->next = pluginsd_root;
- pluginsd_root = cd;
-
- // it is not currently running
- cd->obsolete = 1;
-
- if(cd->enabled) {
- char tag[NETDATA_THREAD_TAG_MAX + 1];
- snprintfz(tag, NETDATA_THREAD_TAG_MAX, "PLUGINSD[%s]", pluginname);
- // spawn a new thread for it
- netdata_thread_create(&cd->thread, tag, NETDATA_THREAD_OPTION_DEFAULT, pluginsd_worker_thread, cd);
- }
- }
- }
-
- closedir(dir);
- }
-
- sleep((unsigned int) scan_frequency);
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/plugins_d.h b/src/plugins_d.h
deleted file mode 100644
index 692d7cae1..000000000
--- a/src/plugins_d.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef NETDATA_PLUGINS_D_H
-#define NETDATA_PLUGINS_D_H 1
-
-#define PLUGINSD_FILE_SUFFIX ".plugin"
-#define PLUGINSD_FILE_SUFFIX_LEN strlen(PLUGINSD_FILE_SUFFIX)
-#define PLUGINSD_CMD_MAX (FILENAME_MAX*2)
-
-#define PLUGINSD_KEYWORD_CHART "CHART"
-#define PLUGINSD_KEYWORD_DIMENSION "DIMENSION"
-#define PLUGINSD_KEYWORD_BEGIN "BEGIN"
-#define PLUGINSD_KEYWORD_END "END"
-#define PLUGINSD_KEYWORD_FLUSH "FLUSH"
-#define PLUGINSD_KEYWORD_DISABLE "DISABLE"
-#define PLUGINSD_KEYWORD_VARIABLE "VARIABLE"
-
-#define PLUGINSD_LINE_MAX 1024
-#define PLUGINSD_MAX_WORDS 20
-
-#define PLUGINSD_MAX_DIRECTORIES 20
-extern char *plugin_directories[PLUGINSD_MAX_DIRECTORIES];
-
-struct plugind {
- char id[CONFIG_MAX_NAME+1]; // config node id
-
- char filename[FILENAME_MAX+1]; // just the filename
- char fullfilename[FILENAME_MAX+1]; // with path
- char cmd[PLUGINSD_CMD_MAX+1]; // the command that it executes
-
- volatile pid_t pid;
- netdata_thread_t thread;
-
- size_t successful_collections; // the number of times we have seen
- // values collected from this plugin
-
- size_t serial_failures; // the number of times the plugin started
- // without collecting values
-
- int update_every; // the plugin default data collection frequency
- volatile sig_atomic_t obsolete; // do not touch this structure after setting this to 1
- volatile sig_atomic_t enabled; // if this is enabled or not
-
- time_t started_t;
-
- struct plugind *next;
-};
-
-extern struct plugind *pluginsd_root;
-
-extern void *pluginsd_main(void *ptr);
-
-extern size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations);
-extern int pluginsd_split_words(char *str, char **words, int max_words);
-
-extern int quoted_strings_splitter(char *str, char **words, int max_words, int (*custom_isspace)(char));
-extern int config_isspace(char c);
-
-#endif /* NETDATA_PLUGINS_D_H */
diff --git a/src/popen.c b/src/popen.c
deleted file mode 100644
index eda1c05b9..000000000
--- a/src/popen.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#include "common.h"
-
-/*
-struct mypopen {
- pid_t pid;
- FILE *fp;
- struct mypopen *next;
- struct mypopen *prev;
-};
-
-static struct mypopen *mypopen_root = NULL;
-
-static void mypopen_add(FILE *fp, pid_t *pid) {
- struct mypopen *mp = malloc(sizeof(struct mypopen));
- if(!mp) {
- fatal("Cannot allocate %zu bytes", sizeof(struct mypopen))
- return;
- }
-
- mp->fp = fp;
- mp->pid = pid;
- mp->next = popen_root;
- mp->prev = NULL;
- if(mypopen_root) mypopen_root->prev = mp;
- mypopen_root = mp;
-}
-
-static void mypopen_del(FILE *fp) {
- struct mypopen *mp;
-
- for(mp = mypopen_root; mp; mp = mp->next)
- if(mp->fd == fp) break;
-
- if(!mp) error("Cannot find mypopen() file pointer in open childs.");
- else {
- if(mp->next) mp->next->prev = mp->prev;
- if(mp->prev) mp->prev->next = mp->next;
- if(mypopen_root == mp) mypopen_root = mp->next;
- free(mp);
- }
-}
-*/
-#define PIPE_READ 0
-#define PIPE_WRITE 1
-
-FILE *mypopen(const char *command, volatile pid_t *pidptr)
-{
- int pipefd[2];
-
- if(pipe(pipefd) == -1) return NULL;
-
- int pid = fork();
- if(pid == -1) {
- close(pipefd[PIPE_READ]);
- close(pipefd[PIPE_WRITE]);
- return NULL;
- }
- if(pid != 0) {
- // the parent
- *pidptr = pid;
- close(pipefd[PIPE_WRITE]);
- FILE *fp = fdopen(pipefd[PIPE_READ], "r");
- /*mypopen_add(fp, pid);*/
- return(fp);
- }
- // the child
-
- // close all files
- int i;
- for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
- if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
-
- // move the pipe to stdout
- if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
- dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
- close(pipefd[PIPE_WRITE]);
- }
-
-#ifdef DETACH_PLUGINS_FROM_NETDATA
- // this was an attempt to detach the child and use the suspend mode charts.d
- // unfortunatelly it does not work as expected.
-
- // fork again to become session leader
- pid = fork();
- if(pid == -1)
- error("pre-execution of command '%s' on pid %d: Cannot fork 2nd time.", command, getpid());
-
- if(pid != 0) {
- // the parent
- exit(0);
- }
-
- // set a new process group id for just this child
- if( setpgid(0, 0) != 0 )
- error("pre-execution of command '%s' on pid %d: Cannot set a new process group.", command, getpid());
-
- if( getpgid(0) != getpid() )
- error("pre-execution of command '%s' on pid %d: Cannot set a new process group. Process group set is incorrect. Expected %d, found %d", command, getpid(), getpid(), getpgid(0));
-
- if( setsid() != 0 )
- error("pre-execution of command '%s' on pid %d: Cannot set session id.", command, getpid());
-
- fprintf(stdout, "MYPID %d\n", getpid());
- fflush(NULL);
-#endif
-
- // reset all signals
- signals_unblock();
- signals_reset();
-
- debug(D_CHILDS, "executing command: '%s' on pid %d.", command, getpid());
- execl("/bin/sh", "sh", "-c", command, NULL);
- exit(1);
-}
-
-FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env) {
- int pipefd[2];
-
- if(pipe(pipefd) == -1)
- return NULL;
-
- int pid = fork();
- if(pid == -1) {
- close(pipefd[PIPE_READ]);
- close(pipefd[PIPE_WRITE]);
- return NULL;
- }
- if(pid != 0) {
- // the parent
- *pidptr = pid;
- close(pipefd[PIPE_WRITE]);
- FILE *fp = fdopen(pipefd[PIPE_READ], "r");
- return(fp);
- }
- // the child
-
- // close all files
- int i;
- for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
- if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
-
- // move the pipe to stdout
- if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
- dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
- close(pipefd[PIPE_WRITE]);
- }
-
- execle("/bin/sh", "sh", "-c", command, NULL, env);
- exit(1);
-}
-
-int mypclose(FILE *fp, pid_t pid) {
- debug(D_EXIT, "Request to mypclose() on pid %d", pid);
-
- /*mypopen_del(fp);*/
-
- // close the pipe fd
- // this is required in musl
- // without it the childs do not exit
- close(fileno(fp));
-
- // close the pipe file pointer
- fclose(fp);
-
- errno = 0;
-
- siginfo_t info;
- if(waitid(P_PID, (id_t) pid, &info, WEXITED) != -1) {
- switch(info.si_code) {
- case CLD_EXITED:
- if(info.si_status)
- error("child pid %d exited with code %d.", info.si_pid, info.si_status);
- return(info.si_status);
-
- case CLD_KILLED:
- error("child pid %d killed by signal %d.", info.si_pid, info.si_status);
- return(-1);
-
- case CLD_DUMPED:
- error("child pid %d core dumped by signal %d.", info.si_pid, info.si_status);
- return(-2);
-
- case CLD_STOPPED:
- error("child pid %d stopped by signal %d.", info.si_pid, info.si_status);
- return(0);
-
- case CLD_TRAPPED:
- error("child pid %d trapped by signal %d.", info.si_pid, info.si_status);
- return(-4);
-
- case CLD_CONTINUED:
- error("child pid %d continued by signal %d.", info.si_pid, info.si_status);
- return(0);
-
- default:
- error("child pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status);
- return(-5);
- }
- }
- else
- error("Cannot waitid() for pid %d", pid);
-
- return 0;
-}
diff --git a/src/popen.h b/src/popen.h
deleted file mode 100644
index 3dd79bb4d..000000000
--- a/src/popen.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef NETDATA_POPEN_H
-#define NETDATA_POPEN_H 1
-
-#define PIPE_READ 0
-#define PIPE_WRITE 1
-
-extern FILE *mypopen(const char *command, volatile pid_t *pidptr);
-extern FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env);
-extern int mypclose(FILE *fp, pid_t pid);
-
-#endif /* NETDATA_POPEN_H */
diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c
deleted file mode 100644
index 8cde3334b..000000000
--- a/src/proc_diskstats.c
+++ /dev/null
@@ -1,1438 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_DISK "disk"
-
-#define DISK_TYPE_UNKNOWN 0
-#define DISK_TYPE_PHYSICAL 1
-#define DISK_TYPE_PARTITION 2
-#define DISK_TYPE_VIRTUAL 3
-
-#define CONFIG_SECTION_DISKSTATS "plugin:proc:/proc/diskstats"
-#define DEFAULT_EXCLUDED_DISKS "loop* ram*"
-
-static struct disk {
- char *disk; // the name of the disk (sda, sdb, etc, after being looked up)
- char *device; // the device of the disk (before being looked up)
- unsigned long major;
- unsigned long minor;
- int sector_size;
- int type;
-
- char *mount_point;
-
- // disk options caching
- int do_io;
- int do_ops;
- int do_mops;
- int do_iotime;
- int do_qops;
- int do_util;
- int do_backlog;
- int do_bcache;
-
- int updated;
-
- int device_is_bcache;
-
- char *bcache_filename_dirty_data;
- char *bcache_filename_writeback_rate;
- char *bcache_filename_cache_congested;
- char *bcache_filename_cache_available_percent;
- char *bcache_filename_stats_five_minute_cache_hit_ratio;
- char *bcache_filename_stats_hour_cache_hit_ratio;
- char *bcache_filename_stats_day_cache_hit_ratio;
- char *bcache_filename_stats_total_cache_hit_ratio;
- char *bcache_filename_stats_total_cache_hits;
- char *bcache_filename_stats_total_cache_misses;
- char *bcache_filename_stats_total_cache_miss_collisions;
- char *bcache_filename_stats_total_cache_bypass_hits;
- char *bcache_filename_stats_total_cache_bypass_misses;
- char *bcache_filename_stats_total_cache_readaheads;
-
- RRDSET *st_io;
- RRDDIM *rd_io_reads;
- RRDDIM *rd_io_writes;
-
- RRDSET *st_ops;
- RRDDIM *rd_ops_reads;
- RRDDIM *rd_ops_writes;
-
- RRDSET *st_qops;
- RRDDIM *rd_qops_operations;
-
- RRDSET *st_backlog;
- RRDDIM *rd_backlog_backlog;
-
- RRDSET *st_util;
- RRDDIM *rd_util_utilization;
-
- RRDSET *st_mops;
- RRDDIM *rd_mops_reads;
- RRDDIM *rd_mops_writes;
-
- RRDSET *st_iotime;
- RRDDIM *rd_iotime_reads;
- RRDDIM *rd_iotime_writes;
-
- RRDSET *st_await;
- RRDDIM *rd_await_reads;
- RRDDIM *rd_await_writes;
-
- RRDSET *st_avgsz;
- RRDDIM *rd_avgsz_reads;
- RRDDIM *rd_avgsz_writes;
-
- RRDSET *st_svctm;
- RRDDIM *rd_svctm_svctm;
-
- RRDSET *st_bcache_size;
- RRDDIM *rd_bcache_dirty_size;
-
- RRDSET *st_bcache_usage;
- RRDDIM *rd_bcache_available_percent;
-
- RRDSET *st_bcache_hit_ratio;
- RRDDIM *rd_bcache_hit_ratio_5min;
- RRDDIM *rd_bcache_hit_ratio_1hour;
- RRDDIM *rd_bcache_hit_ratio_1day;
- RRDDIM *rd_bcache_hit_ratio_total;
-
- RRDSET *st_bcache;
- RRDDIM *rd_bcache_hits;
- RRDDIM *rd_bcache_misses;
- RRDDIM *rd_bcache_miss_collisions;
-
- RRDSET *st_bcache_bypass;
- RRDDIM *rd_bcache_bypass_hits;
- RRDDIM *rd_bcache_bypass_misses;
-
- RRDSET *st_bcache_rates;
- RRDDIM *rd_bcache_rate_congested;
- RRDDIM *rd_bcache_readaheads;
- RRDDIM *rd_bcache_rate_writeback;
-
- struct disk *next;
-} *disk_root = NULL;
-
-#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_is_obsolete(st); (st) = NULL; } } while(st)
-
-// static char *path_to_get_hw_sector_size = NULL;
-// static char *path_to_get_hw_sector_size_partitions = NULL;
-static char *path_to_sys_dev_block_major_minor_string = NULL;
-static char *path_to_sys_block_device = NULL;
-static char *path_to_sys_block_device_bcache = NULL;
-static char *path_to_sys_devices_virtual_block_device = NULL;
-static char *path_to_device_mapper = NULL;
-static char *path_to_device_label = NULL;
-static char *path_to_device_id = NULL;
-static int name_disks_by_id = CONFIG_BOOLEAN_NO;
-
-static int global_enable_new_disks_detected_at_runtime = CONFIG_BOOLEAN_YES,
- global_enable_performance_for_physical_disks = CONFIG_BOOLEAN_AUTO,
- global_enable_performance_for_virtual_disks = CONFIG_BOOLEAN_AUTO,
- global_enable_performance_for_partitions = CONFIG_BOOLEAN_NO,
- global_do_io = CONFIG_BOOLEAN_AUTO,
- global_do_ops = CONFIG_BOOLEAN_AUTO,
- global_do_mops = CONFIG_BOOLEAN_AUTO,
- global_do_iotime = CONFIG_BOOLEAN_AUTO,
- global_do_qops = CONFIG_BOOLEAN_AUTO,
- global_do_util = CONFIG_BOOLEAN_AUTO,
- global_do_backlog = CONFIG_BOOLEAN_AUTO,
- global_do_bcache = CONFIG_BOOLEAN_AUTO,
- globals_initialized = 0,
- global_cleanup_removed_disks = 1;
-
-static SIMPLE_PATTERN *excluded_disks = NULL;
-
-static unsigned long long int bcache_read_number_with_units(const char *filename) {
- char buffer[50 + 1];
- if(read_file(filename, buffer, 50) == 0) {
- static int unknown_units_error = 10;
-
- char *end = NULL;
- long double value = str2ld(buffer, &end);
- if(end && *end) {
- if(*end == 'k')
- return (unsigned long long int)(value * 1024.0);
- else if(*end == 'M')
- return (unsigned long long int)(value * 1024.0 * 1024.0);
- else if(*end == 'G')
- return (unsigned long long int)(value * 1024.0 * 1024.0 * 1024.0);
- else if(unknown_units_error > 0) {
- error("bcache file '%s' provides value '%s' with unknown units '%s'", filename, buffer, end);
- unknown_units_error--;
- }
- }
-
- return (unsigned long long int)value;
- }
-
- return 0;
-}
-
-static inline int is_major_enabled(int major) {
- static int8_t *major_configs = NULL;
- static size_t major_size = 0;
-
- if(major < 0) return 1;
-
- size_t wanted_size = (size_t)major + 1;
-
- if(major_size < wanted_size) {
- major_configs = reallocz(major_configs, wanted_size * sizeof(int8_t));
-
- size_t i;
- for(i = major_size; i < wanted_size ; i++)
- major_configs[i] = -1;
-
- major_size = wanted_size;
- }
-
- if(major_configs[major] == -1) {
- char buffer[CONFIG_MAX_NAME + 1];
- snprintfz(buffer, CONFIG_MAX_NAME, "performance metrics for disks with major %d", major);
- major_configs[major] = (char)config_get_boolean(CONFIG_SECTION_DISKSTATS, buffer, 1);
- }
-
- return (int)major_configs[major];
-}
-
-static inline int get_disk_name_from_path(const char *path, char *result, size_t result_size, unsigned long major, unsigned long minor, char *disk) {
- char filename[FILENAME_MAX + 1];
- int found = 0;
-
- result_size--;
-
- DIR *dir = opendir(path);
- if (!dir) {
- error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot open directory '%s'. Disabling device-mapper support.", disk, major, minor, path);
- goto cleanup;
- }
-
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- if(de->d_type != DT_LNK) continue;
-
- snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name);
- ssize_t len = readlink(filename, result, result_size);
- if(len <= 0) {
- error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot read link '%s'.", disk, major, minor, filename);
- continue;
- }
-
- result[len] = '\0';
- if(result[0] != '/')
- snprintfz(filename, FILENAME_MAX, "%s/%s", path, result);
- else
- strncpyz(filename, result, FILENAME_MAX);
-
- struct stat sb;
- if(stat(filename, &sb) == -1) {
- error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot stat() file '%s'.", disk, major, minor, filename);
- continue;
- }
-
- if((sb.st_mode & S_IFMT) != S_IFBLK) {
- // info("DEVICE-MAPPER ('%s', %lu:%lu): file '%s' is not a block device.", disk, major, minor, filename);
- continue;
- }
-
- if(major(sb.st_rdev) != major || minor(sb.st_rdev) != minor) {
- // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' does not match %lu:%lu.", disk, major, minor, filename, (unsigned long)major(sb.st_rdev), (unsigned long)minor(sb.st_rdev));
- continue;
- }
-
- // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' matches.", disk, major, minor, filename);
-
- strncpy(result, de->d_name, result_size);
- found = 1;
- break;
- }
- closedir(dir);
-
-
-cleanup:
-
- if(!found)
- result[0] = '\0';
-
- return found;
-}
-
-static inline char *get_disk_name(unsigned long major, unsigned long minor, char *disk) {
- char result[FILENAME_MAX + 1] = "";
-
- if(!path_to_device_mapper || !*path_to_device_mapper || !get_disk_name_from_path(path_to_device_mapper, result, FILENAME_MAX + 1, major, minor, disk))
- if(!path_to_device_label || !*path_to_device_label || !get_disk_name_from_path(path_to_device_label, result, FILENAME_MAX + 1, major, minor, disk))
- if(name_disks_by_id != CONFIG_BOOLEAN_YES || !path_to_device_id || !*path_to_device_id || !get_disk_name_from_path(path_to_device_id, result, FILENAME_MAX + 1, major, minor, disk))
- strncpy(result, disk, FILENAME_MAX);
-
- if(!result[0])
- strncpy(result, disk, FILENAME_MAX);
-
- netdata_fix_chart_name(result);
- return strdup(result);
-}
-
-static void get_disk_config(struct disk *d) {
- int def_enable = global_enable_new_disks_detected_at_runtime;
-
- if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk)))
- def_enable = CONFIG_BOOLEAN_NO;
-
- char var_name[4096 + 1];
- snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", d->disk);
-
- def_enable = config_get_boolean_ondemand(var_name, "enable", def_enable);
- if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) {
- // the user does not want any metrics for this disk
- d->do_io = CONFIG_BOOLEAN_NO;
- d->do_ops = CONFIG_BOOLEAN_NO;
- d->do_mops = CONFIG_BOOLEAN_NO;
- d->do_iotime = CONFIG_BOOLEAN_NO;
- d->do_qops = CONFIG_BOOLEAN_NO;
- d->do_util = CONFIG_BOOLEAN_NO;
- d->do_backlog = CONFIG_BOOLEAN_NO;
- d->do_bcache = CONFIG_BOOLEAN_NO;
- }
- else {
- // this disk is enabled
- // check its direct settings
-
- int def_performance = CONFIG_BOOLEAN_AUTO;
-
- // since this is 'on demand' we can figure the performance settings
- // based on the type of disk
-
- if(!d->device_is_bcache) {
- switch(d->type) {
- default:
- case DISK_TYPE_UNKNOWN:
- break;
-
- case DISK_TYPE_PHYSICAL:
- def_performance = global_enable_performance_for_physical_disks;
- break;
-
- case DISK_TYPE_PARTITION:
- def_performance = global_enable_performance_for_partitions;
- break;
-
- case DISK_TYPE_VIRTUAL:
- def_performance = global_enable_performance_for_virtual_disks;
- break;
- }
- }
-
- // check if we have to disable performance for this disk
- if(def_performance)
- def_performance = is_major_enabled((int)d->major);
-
- // ------------------------------------------------------------
- // now we have def_performance and def_space
- // to work further
-
- // def_performance
- // check the user configuration (this will also show our 'on demand' decision)
- def_performance = config_get_boolean_ondemand(var_name, "enable performance metrics", def_performance);
-
- int ddo_io = CONFIG_BOOLEAN_NO,
- ddo_ops = CONFIG_BOOLEAN_NO,
- ddo_mops = CONFIG_BOOLEAN_NO,
- ddo_iotime = CONFIG_BOOLEAN_NO,
- ddo_qops = CONFIG_BOOLEAN_NO,
- ddo_util = CONFIG_BOOLEAN_NO,
- ddo_backlog = CONFIG_BOOLEAN_NO,
- ddo_bcache = CONFIG_BOOLEAN_NO;
-
- // we enable individual performance charts only when def_performance is not disabled
- if(unlikely(def_performance != CONFIG_BOOLEAN_NO)) {
- ddo_io = global_do_io,
- ddo_ops = global_do_ops,
- ddo_mops = global_do_mops,
- ddo_iotime = global_do_iotime,
- ddo_qops = global_do_qops,
- ddo_util = global_do_util,
- ddo_backlog = global_do_backlog,
- ddo_bcache = global_do_bcache;
- }
-
- d->do_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
- d->do_ops = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
- d->do_mops = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
- d->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
- d->do_qops = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
- d->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
- d->do_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
-
- if(d->device_is_bcache)
- d->do_bcache = config_get_boolean_ondemand(var_name, "bcache", ddo_bcache);
- else
- d->do_bcache = 0;
- }
-}
-
-static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) {
- static struct mountinfo *disk_mountinfo_root = NULL;
-
- struct disk *d;
-
- // search for it in our RAM list.
- // this is sequential, but since we just walk through
- // and the number of disks / partitions in a system
- // should not be that many, it should be acceptable
- for(d = disk_root; d ; d = d->next)
- if(unlikely(d->major == major && d->minor == minor))
- return d;
-
- // not found
- // create a new disk structure
- d = (struct disk *)callocz(1, sizeof(struct disk));
-
- d->disk = get_disk_name(major, minor, disk);
- d->device = strdupz(disk);
- d->major = major;
- d->minor = minor;
- d->type = DISK_TYPE_UNKNOWN; // Default type. Changed later if not correct.
- d->sector_size = 512; // the default, will be changed below
- d->next = NULL;
-
- // append it to the list
- if(unlikely(!disk_root))
- disk_root = d;
- else {
- struct disk *last;
- for(last = disk_root; last->next ;last = last->next);
- last->next = d;
- }
-
- char buffer[FILENAME_MAX + 1];
-
- // find if it is a physical disk
- // by checking if /sys/block/DISK is readable.
- snprintfz(buffer, FILENAME_MAX, path_to_sys_block_device, disk);
- if(likely(access(buffer, R_OK) == 0)) {
- // assign it here, but it will be overwritten if it is not a physical disk
- d->type = DISK_TYPE_PHYSICAL;
- }
-
- // find if it is a partition
- // by checking if /sys/dev/block/MAJOR:MINOR/partition is readable.
- snprintfz(buffer, FILENAME_MAX, path_to_sys_dev_block_major_minor_string, major, minor, "partition");
- if(likely(access(buffer, R_OK) == 0)) {
- d->type = DISK_TYPE_PARTITION;
- }
- else {
- // find if it is a virtual disk
- // by checking if /sys/devices/virtual/block/DISK is readable.
- snprintfz(buffer, FILENAME_MAX, path_to_sys_devices_virtual_block_device, disk);
- if(likely(access(buffer, R_OK) == 0)) {
- d->type = DISK_TYPE_VIRTUAL;
- }
- else {
- // find if it is a virtual device
- // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries
- snprintfz(buffer, FILENAME_MAX, path_to_sys_dev_block_major_minor_string, major, minor, "slaves/");
- DIR *dirp = opendir(buffer);
- if (likely(dirp != NULL)) {
- struct dirent *dp;
- while ((dp = readdir(dirp))) {
- // . and .. are also files in empty folders.
- if (unlikely(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) {
- continue;
- }
-
- d->type = DISK_TYPE_VIRTUAL;
-
- // Stop the loop after we found one file.
- break;
- }
- if (unlikely(closedir(dirp) == -1))
- error("Unable to close dir %s", buffer);
- }
- }
- }
-
- // ------------------------------------------------------------------------
- // check if we can find its mount point
-
- // mountinfo_find() can be called with NULL disk_mountinfo_root
- struct mountinfo *mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor);
- if(unlikely(!mi)) {
- // mountinfo_free_all can be called with NULL
- mountinfo_free_all(disk_mountinfo_root);
- disk_mountinfo_root = mountinfo_read(0);
- mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor);
- }
-
- if(unlikely(mi))
- d->mount_point = strdupz(mi->mount_point);
- else
- d->mount_point = NULL;
-
- // ------------------------------------------------------------------------
- // find the disk sector size
-
- /*
- * sector size is always 512 bytes inside the kernel #3481
- *
- {
- char tf[FILENAME_MAX + 1], *t;
- strncpyz(tf, d->device, FILENAME_MAX);
-
- // replace all / with !
- for(t = tf; *t ;t++)
- if(unlikely(*t == '/')) *t = '!';
-
- if(likely(d->type == DISK_TYPE_PARTITION))
- snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size_partitions, d->major, d->minor, tf);
- else
- snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size, tf);
-
- FILE *fpss = fopen(buffer, "r");
- if(likely(fpss)) {
- char buffer2[1024 + 1];
- char *tmp = fgets(buffer2, 1024, fpss);
-
- if(likely(tmp)) {
- d->sector_size = str2i(tmp);
- if(unlikely(d->sector_size <= 0)) {
- error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->device, buffer);
- d->sector_size = 512;
- }
- }
- else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->device, buffer);
-
- fclose(fpss);
- }
- else error("Cannot read sector size for device %s from %s. Assuming 512.", d->device, buffer);
- }
- */
-
- // ------------------------------------------------------------------------
- // check if the device is a bcache
-
- struct stat bcache;
- snprintfz(buffer, FILENAME_MAX, path_to_sys_block_device_bcache, disk);
- if(unlikely(stat(buffer, &bcache) == 0 && (bcache.st_mode & S_IFMT) == S_IFDIR)) {
- // we have the 'bcache' directory
- d->device_is_bcache = 1;
-
- char buffer2[FILENAME_MAX + 1];
-
- snprintfz(buffer2, FILENAME_MAX, "%s/cache/congested", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_cache_congested = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/readahead", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_readaheads = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/dirty_data", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_dirty_data = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/writeback_rate", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_writeback_rate = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/cache/cache_available_percent", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_cache_available_percent = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_hits", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_hits = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_five_minute/cache_hit_ratio", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_five_minute_cache_hit_ratio = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_hour/cache_hit_ratio", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_hour_cache_hit_ratio = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_day/cache_hit_ratio", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_day_cache_hit_ratio = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_hit_ratio", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_hit_ratio = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_misses", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_misses = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_bypass_hits", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_bypass_hits = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_bypass_misses", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_bypass_misses = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
-
- snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_miss_collisions", buffer);
- if(access(buffer2, R_OK) == 0)
- d->bcache_filename_stats_total_cache_miss_collisions = strdupz(buffer2);
- else
- error("bcache file '%s' cannot be read.", buffer2);
- }
-
- get_disk_config(d);
- return d;
-}
-
-int do_proc_diskstats(int update_every, usec_t dt) {
- static procfile *ff = NULL;
-
- if(unlikely(!globals_initialized)) {
- globals_initialized = 1;
-
- global_enable_new_disks_detected_at_runtime = config_get_boolean(CONFIG_SECTION_DISKSTATS, "enable new disks detected at runtime", global_enable_new_disks_detected_at_runtime);
- global_enable_performance_for_physical_disks = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for physical disks", global_enable_performance_for_physical_disks);
- global_enable_performance_for_virtual_disks = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for virtual disks", global_enable_performance_for_virtual_disks);
- global_enable_performance_for_partitions = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for partitions", global_enable_performance_for_partitions);
-
- global_do_io = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "bandwidth for all disks", global_do_io);
- global_do_ops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "operations for all disks", global_do_ops);
- global_do_mops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "merged operations for all disks", global_do_mops);
- global_do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "i/o time for all disks", global_do_iotime);
- global_do_qops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "queued operations for all disks", global_do_qops);
- global_do_util = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "utilization percentage for all disks", global_do_util);
- global_do_backlog = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "backlog for all disks", global_do_backlog);
- global_do_bcache = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "bcache for all disks", global_do_bcache);
-
- global_cleanup_removed_disks = config_get_boolean(CONFIG_SECTION_DISKSTATS, "remove charts of removed disks" , global_cleanup_removed_disks);
-
- char buffer[FILENAME_MAX + 1];
-
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s");
- path_to_sys_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device", buffer);
-
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/bcache");
- path_to_sys_block_device_bcache = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device bcache", buffer);
-
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/block/%s");
- path_to_sys_devices_virtual_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get virtual block device", buffer);
-
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s");
- path_to_sys_dev_block_major_minor_string = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer);
-
- //snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
- //path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer);
-
- //snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
- //path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer);
-
- snprintfz(buffer, FILENAME_MAX, "%s/dev/mapper", netdata_configured_host_prefix);
- path_to_device_mapper = config_get(CONFIG_SECTION_DISKSTATS, "path to device mapper", buffer);
-
- snprintfz(buffer, FILENAME_MAX, "%s/dev/disk/by-label", netdata_configured_host_prefix);
- path_to_device_label = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-label", buffer);
-
- snprintfz(buffer, FILENAME_MAX, "%s/dev/disk/by-id", netdata_configured_host_prefix);
- path_to_device_id = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-id", buffer);
-
- name_disks_by_id = config_get_boolean(CONFIG_SECTION_DISKSTATS, "name disks by id", name_disks_by_id);
-
- excluded_disks = simple_pattern_create(
- config_get(CONFIG_SECTION_DISKSTATS, "exclude disks", DEFAULT_EXCLUDED_DISKS)
- , NULL
- , SIMPLE_PATTERN_EXACT
- );
- }
-
- // --------------------------------------------------------------------------
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/diskstats");
- ff = procfile_open(config_get(CONFIG_SECTION_DISKSTATS, "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- }
- if(unlikely(!ff)) return 0;
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- collected_number system_read_kb = 0, system_write_kb = 0;
-
- for(l = 0; l < lines ;l++) {
- // --------------------------------------------------------------------------
- // Read parameters
-
- char *disk;
- unsigned long major = 0, minor = 0;
-
- collected_number reads = 0, mreads = 0, readsectors = 0, readms = 0,
- writes = 0, mwrites = 0, writesectors = 0, writems = 0,
- queued_ios = 0, busy_ms = 0, backlog_ms = 0;
-
- collected_number last_reads = 0, last_readsectors = 0, last_readms = 0,
- last_writes = 0, last_writesectors = 0, last_writems = 0,
- last_busy_ms = 0;
-
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 14)) continue;
-
- major = str2ul(procfile_lineword(ff, l, 0));
- minor = str2ul(procfile_lineword(ff, l, 1));
- disk = procfile_lineword(ff, l, 2);
-
- // # of reads completed # of writes completed
- // This is the total number of reads or writes completed successfully.
- reads = str2ull(procfile_lineword(ff, l, 3)); // rd_ios
- writes = str2ull(procfile_lineword(ff, l, 7)); // wr_ios
-
- // # of reads merged # of writes merged
- // Reads and writes which are adjacent to each other may be merged for
- // efficiency. Thus two 4K reads may become one 8K read before it is
- // ultimately handed to the disk, and so it will be counted (and queued)
- mreads = str2ull(procfile_lineword(ff, l, 4)); // rd_merges_or_rd_sec
- mwrites = str2ull(procfile_lineword(ff, l, 8)); // wr_merges
-
- // # of sectors read # of sectors written
- // This is the total number of sectors read or written successfully.
- readsectors = str2ull(procfile_lineword(ff, l, 5)); // rd_sec_or_wr_ios
- writesectors = str2ull(procfile_lineword(ff, l, 9)); // wr_sec
-
- // # of milliseconds spent reading # of milliseconds spent writing
- // This is the total number of milliseconds spent by all reads or writes (as
- // measured from __make_request() to end_that_request_last()).
- readms = str2ull(procfile_lineword(ff, l, 6)); // rd_ticks_or_wr_sec
- writems = str2ull(procfile_lineword(ff, l, 10)); // wr_ticks
-
- // # of I/Os currently in progress
- // The only field that should go to zero. Incremented as requests are
- // given to appropriate struct request_queue and decremented as they finish.
- queued_ios = str2ull(procfile_lineword(ff, l, 11)); // ios_pgr
-
- // # of milliseconds spent doing I/Os
- // This field increases so long as field queued_ios is nonzero.
- busy_ms = str2ull(procfile_lineword(ff, l, 12)); // tot_ticks
-
- // weighted # of milliseconds spent doing I/Os
- // This field is incremented at each I/O start, I/O completion, I/O
- // merge, or read of these stats by the number of I/Os in progress
- // (field queued_ios) times the number of milliseconds spent doing I/O since the
- // last update of this field. This can provide an easy measure of both
- // I/O completion time and the backlog that may be accumulating.
- backlog_ms = str2ull(procfile_lineword(ff, l, 13)); // rq_ticks
-
-
- // --------------------------------------------------------------------------
- // remove slashes from disk names
- char *s;
- for(s = disk; *s ;s++)
- if(*s == '/') *s = '_';
-
- // --------------------------------------------------------------------------
- // get a disk structure for the disk
-
- struct disk *d = get_disk(major, minor, disk);
- d->updated = 1;
-
- // --------------------------------------------------------------------------
- // count the global system disk I/O of physical disks
-
- if(unlikely(d->type == DISK_TYPE_PHYSICAL)) {
- system_read_kb += readsectors * d->sector_size / 1024;
- system_write_kb += writesectors * d->sector_size / 1024;
- }
-
- // --------------------------------------------------------------------------
- // Set its family based on mount point
-
- char *family = d->mount_point;
- if(!family) family = d->disk;
-
-
- // --------------------------------------------------------------------------
- // Do performance metrics
-
- if(d->do_io == CONFIG_BOOLEAN_YES || (d->do_io == CONFIG_BOOLEAN_AUTO && (readsectors || writesectors))) {
- d->do_io = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_io)) {
- d->st_io = rrdset_create_localhost(
- RRD_TYPE_DISK
- , d->device
- , d->disk
- , family
- , "disk.io"
- , "Disk I/O Bandwidth"
- , "kilobytes/s"
- , "proc"
- , "diskstats"
- , 2000
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- d->rd_io_reads = rrddim_add(d->st_io, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_INCREMENTAL);
- d->rd_io_writes = rrddim_add(d->st_io, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_io);
-
- last_readsectors = rrddim_set_by_pointer(d->st_io, d->rd_io_reads, readsectors);
- last_writesectors = rrddim_set_by_pointer(d->st_io, d->rd_io_writes, writesectors);
- rrdset_done(d->st_io);
- }
-
- // --------------------------------------------------------------------
-
- if(d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes))) {
- d->do_ops = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_ops)) {
- d->st_ops = rrdset_create_localhost(
- "disk_ops"
- , d->device
- , d->disk
- , family
- , "disk.ops"
- , "Disk Completed I/O Operations"
- , "operations/s"
- , "proc"
- , "diskstats"
- , 2001
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_ops, RRDSET_FLAG_DETAIL);
-
- d->rd_ops_reads = rrddim_add(d->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_ops_writes = rrddim_add(d->st_ops, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_ops);
-
- last_reads = rrddim_set_by_pointer(d->st_ops, d->rd_ops_reads, reads);
- last_writes = rrddim_set_by_pointer(d->st_ops, d->rd_ops_writes, writes);
- rrdset_done(d->st_ops);
- }
-
- // --------------------------------------------------------------------
-
- if(d->do_qops == CONFIG_BOOLEAN_YES || (d->do_qops == CONFIG_BOOLEAN_AUTO && queued_ios)) {
- d->do_qops = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_qops)) {
- d->st_qops = rrdset_create_localhost(
- "disk_qops"
- , d->device
- , d->disk
- , family
- , "disk.qops"
- , "Disk Current I/O Operations"
- , "operations"
- , "proc"
- , "diskstats"
- , 2002
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_qops, RRDSET_FLAG_DETAIL);
-
- d->rd_qops_operations = rrddim_add(d->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_qops);
-
- rrddim_set_by_pointer(d->st_qops, d->rd_qops_operations, queued_ios);
- rrdset_done(d->st_qops);
- }
-
- // --------------------------------------------------------------------
-
- if(d->do_backlog == CONFIG_BOOLEAN_YES || (d->do_backlog == CONFIG_BOOLEAN_AUTO && backlog_ms)) {
- d->do_backlog = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_backlog)) {
- d->st_backlog = rrdset_create_localhost(
- "disk_backlog"
- , d->device
- , d->disk
- , family
- , "disk.backlog"
- , "Disk Backlog"
- , "backlog (ms)"
- , "proc"
- , "diskstats"
- , 2003
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(d->st_backlog, RRDSET_FLAG_DETAIL);
-
- d->rd_backlog_backlog = rrddim_add(d->st_backlog, "backlog", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_backlog);
-
- rrddim_set_by_pointer(d->st_backlog, d->rd_backlog_backlog, backlog_ms);
- rrdset_done(d->st_backlog);
- }
-
- // --------------------------------------------------------------------
-
- if(d->do_util == CONFIG_BOOLEAN_YES || (d->do_util == CONFIG_BOOLEAN_AUTO && busy_ms)) {
- d->do_util = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_util)) {
- d->st_util = rrdset_create_localhost(
- "disk_util"
- , d->device
- , d->disk
- , family
- , "disk.util"
- , "Disk Utilization Time"
- , "% of time working"
- , "proc"
- , "diskstats"
- , 2004
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(d->st_util, RRDSET_FLAG_DETAIL);
-
- d->rd_util_utilization = rrddim_add(d->st_util, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_util);
-
- last_busy_ms = rrddim_set_by_pointer(d->st_util, d->rd_util_utilization, busy_ms);
- rrdset_done(d->st_util);
- }
-
- // --------------------------------------------------------------------
-
- if(d->do_mops == CONFIG_BOOLEAN_YES || (d->do_mops == CONFIG_BOOLEAN_AUTO && (mreads || mwrites))) {
- d->do_mops = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_mops)) {
- d->st_mops = rrdset_create_localhost(
- "disk_mops"
- , d->device
- , d->disk
- , family
- , "disk.mops"
- , "Disk Merged Operations"
- , "merged operations/s"
- , "proc"
- , "diskstats"
- , 2021
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_mops, RRDSET_FLAG_DETAIL);
-
- d->rd_mops_reads = rrddim_add(d->st_mops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_mops_writes = rrddim_add(d->st_mops, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_mops);
-
- rrddim_set_by_pointer(d->st_mops, d->rd_mops_reads, mreads);
- rrddim_set_by_pointer(d->st_mops, d->rd_mops_writes, mwrites);
- rrdset_done(d->st_mops);
- }
-
- // --------------------------------------------------------------------
-
- if(d->do_iotime == CONFIG_BOOLEAN_YES || (d->do_iotime == CONFIG_BOOLEAN_AUTO && (readms || writems))) {
- d->do_iotime = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!d->st_iotime)) {
- d->st_iotime = rrdset_create_localhost(
- "disk_iotime"
- , d->device
- , d->disk
- , family
- , "disk.iotime"
- , "Disk Total I/O Time"
- , "milliseconds/s"
- , "proc"
- , "diskstats"
- , 2022
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_iotime, RRDSET_FLAG_DETAIL);
-
- d->rd_iotime_reads = rrddim_add(d->st_iotime, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_iotime_writes = rrddim_add(d->st_iotime, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_iotime);
-
- last_readms = rrddim_set_by_pointer(d->st_iotime, d->rd_iotime_reads, readms);
- last_writems = rrddim_set_by_pointer(d->st_iotime, d->rd_iotime_writes, writems);
- rrdset_done(d->st_iotime);
- }
-
- // --------------------------------------------------------------------
- // calculate differential charts
- // only if this is not the first time we run
-
- if(likely(dt)) {
- if( (d->do_iotime == CONFIG_BOOLEAN_YES || (d->do_iotime == CONFIG_BOOLEAN_AUTO && (readms || writems))) &&
- (d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes)))) {
-
- if(unlikely(!d->st_await)) {
- d->st_await = rrdset_create_localhost(
- "disk_await"
- , d->device
- , d->disk
- , family
- , "disk.await"
- , "Average Completed I/O Operation Time"
- , "ms per operation"
- , "proc"
- , "diskstats"
- , 2005
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_await, RRDSET_FLAG_DETAIL);
-
- d->rd_await_reads = rrddim_add(d->st_await, "reads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- d->rd_await_writes = rrddim_add(d->st_await, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_await);
-
- rrddim_set_by_pointer(d->st_await, d->rd_await_reads, (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0);
- rrddim_set_by_pointer(d->st_await, d->rd_await_writes, (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0);
- rrdset_done(d->st_await);
- }
-
- if( (d->do_io == CONFIG_BOOLEAN_YES || (d->do_io == CONFIG_BOOLEAN_AUTO && (readsectors || writesectors))) &&
- (d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes)))) {
-
- if(unlikely(!d->st_avgsz)) {
- d->st_avgsz = rrdset_create_localhost(
- "disk_avgsz"
- , d->device
- , d->disk
- , family
- , "disk.avgsz"
- , "Average Completed I/O Operation Bandwidth"
- , "kilobytes per operation"
- , "proc"
- , "diskstats"
- , 2006
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(d->st_avgsz, RRDSET_FLAG_DETAIL);
-
- d->rd_avgsz_reads = rrddim_add(d->st_avgsz, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_ABSOLUTE);
- d->rd_avgsz_writes = rrddim_add(d->st_avgsz, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_avgsz);
-
- rrddim_set_by_pointer(d->st_avgsz, d->rd_avgsz_reads, (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0);
- rrddim_set_by_pointer(d->st_avgsz, d->rd_avgsz_writes, (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0);
- rrdset_done(d->st_avgsz);
- }
-
- if( (d->do_util == CONFIG_BOOLEAN_YES || (d->do_util == CONFIG_BOOLEAN_AUTO && busy_ms)) &&
- (d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes)))) {
-
- if(unlikely(!d->st_svctm)) {
- d->st_svctm = rrdset_create_localhost(
- "disk_svctm"
- , d->device
- , d->disk
- , family
- , "disk.svctm"
- , "Average Service Time"
- , "ms per operation"
- , "proc"
- , "diskstats"
- , 2007
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_svctm, RRDSET_FLAG_DETAIL);
-
- d->rd_svctm_svctm = rrddim_add(d->st_svctm, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_svctm);
-
- rrddim_set_by_pointer(d->st_svctm, d->rd_svctm_svctm, ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0);
- rrdset_done(d->st_svctm);
- }
- }
-
- // --------------------------------------------------------------------------
- // read bcache metrics and generate the bcache charts
-
- if(d->device_is_bcache && d->do_bcache != CONFIG_BOOLEAN_NO) {
- unsigned long long int
- stats_total_cache_bypass_hits = 0,
- stats_total_cache_bypass_misses = 0,
- stats_total_cache_hits = 0,
- stats_total_cache_miss_collisions = 0,
- stats_total_cache_misses = 0,
- stats_five_minute_cache_hit_ratio = 0,
- stats_hour_cache_hit_ratio = 0,
- stats_day_cache_hit_ratio = 0,
- stats_total_cache_hit_ratio = 0,
- cache_available_percent = 0,
- cache_readaheads = 0,
- cache_congested = 0,
- dirty_data = 0,
- writeback_rate = 0;
-
- // read the bcache values
-
- if(d->bcache_filename_dirty_data)
- dirty_data = bcache_read_number_with_units(d->bcache_filename_dirty_data);
-
- if(d->bcache_filename_writeback_rate)
- writeback_rate = bcache_read_number_with_units(d->bcache_filename_writeback_rate);
-
- if(d->bcache_filename_cache_congested)
- cache_congested = bcache_read_number_with_units(d->bcache_filename_cache_congested);
-
- if(d->bcache_filename_cache_available_percent)
- read_single_number_file(d->bcache_filename_cache_available_percent, &cache_available_percent);
-
- if(d->bcache_filename_stats_five_minute_cache_hit_ratio)
- read_single_number_file(d->bcache_filename_stats_five_minute_cache_hit_ratio, &stats_five_minute_cache_hit_ratio);
-
- if(d->bcache_filename_stats_hour_cache_hit_ratio)
- read_single_number_file(d->bcache_filename_stats_hour_cache_hit_ratio, &stats_hour_cache_hit_ratio);
-
- if(d->bcache_filename_stats_day_cache_hit_ratio)
- read_single_number_file(d->bcache_filename_stats_day_cache_hit_ratio, &stats_day_cache_hit_ratio);
-
- if(d->bcache_filename_stats_total_cache_hit_ratio)
- read_single_number_file(d->bcache_filename_stats_total_cache_hit_ratio, &stats_total_cache_hit_ratio);
-
- if(d->bcache_filename_stats_total_cache_hits)
- read_single_number_file(d->bcache_filename_stats_total_cache_hits, &stats_total_cache_hits);
-
- if(d->bcache_filename_stats_total_cache_misses)
- read_single_number_file(d->bcache_filename_stats_total_cache_misses, &stats_total_cache_misses);
-
- if(d->bcache_filename_stats_total_cache_miss_collisions)
- read_single_number_file(d->bcache_filename_stats_total_cache_miss_collisions, &stats_total_cache_miss_collisions);
-
- if(d->bcache_filename_stats_total_cache_bypass_hits)
- read_single_number_file(d->bcache_filename_stats_total_cache_bypass_hits, &stats_total_cache_bypass_hits);
-
- if(d->bcache_filename_stats_total_cache_bypass_misses)
- read_single_number_file(d->bcache_filename_stats_total_cache_bypass_misses, &stats_total_cache_bypass_misses);
-
- if(d->bcache_filename_stats_total_cache_readaheads)
- cache_readaheads = bcache_read_number_with_units(d->bcache_filename_stats_total_cache_readaheads);
-
-
- // update the charts
-
- {
-
- if(unlikely(!d->st_bcache_hit_ratio)) {
- d->st_bcache_hit_ratio = rrdset_create_localhost(
- "disk_bcache_hit_ratio"
- , d->device
- , d->disk
- , family
- , "disk.bcache_hit_ratio"
- , "BCache Cache Hit Ratio"
- , "percentage"
- , "proc"
- , "diskstats"
- , 2120
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- d->rd_bcache_hit_ratio_5min = rrddim_add(d->st_bcache_hit_ratio, "5min", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- d->rd_bcache_hit_ratio_1hour = rrddim_add(d->st_bcache_hit_ratio, "1hour", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- d->rd_bcache_hit_ratio_1day = rrddim_add(d->st_bcache_hit_ratio, "1day", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- d->rd_bcache_hit_ratio_total = rrddim_add(d->st_bcache_hit_ratio, "ever", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_bcache_hit_ratio);
-
- rrddim_set_by_pointer(d->st_bcache_hit_ratio, d->rd_bcache_hit_ratio_5min, stats_five_minute_cache_hit_ratio);
- rrddim_set_by_pointer(d->st_bcache_hit_ratio, d->rd_bcache_hit_ratio_1hour, stats_hour_cache_hit_ratio);
- rrddim_set_by_pointer(d->st_bcache_hit_ratio, d->rd_bcache_hit_ratio_1day, stats_day_cache_hit_ratio);
- rrddim_set_by_pointer(d->st_bcache_hit_ratio, d->rd_bcache_hit_ratio_total, stats_total_cache_hit_ratio);
- rrdset_done(d->st_bcache_hit_ratio);
- }
-
- {
-
- if(unlikely(!d->st_bcache_rates)) {
- d->st_bcache_rates = rrdset_create_localhost(
- "disk_bcache_rates"
- , d->device
- , d->disk
- , family
- , "disk.bcache_rates"
- , "BCache Rates"
- , "KB/s"
- , "proc"
- , "diskstats"
- , 2121
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- d->rd_bcache_rate_congested = rrddim_add(d->st_bcache_rates, "congested", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- d->rd_bcache_rate_writeback = rrddim_add(d->st_bcache_rates, "writeback", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_bcache_rates);
-
- rrddim_set_by_pointer(d->st_bcache_rates, d->rd_bcache_rate_writeback, writeback_rate);
- rrddim_set_by_pointer(d->st_bcache_rates, d->rd_bcache_rate_congested, cache_congested);
- rrdset_done(d->st_bcache_rates);
- }
-
- {
- if(unlikely(!d->st_bcache_size)) {
- d->st_bcache_size = rrdset_create_localhost(
- "disk_bcache_size"
- , d->device
- , d->disk
- , family
- , "disk.bcache_size"
- , "BCache Cache Sizes"
- , "MB"
- , "proc"
- , "diskstats"
- , 2122
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- d->rd_bcache_dirty_size = rrddim_add(d->st_bcache_size, "dirty", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_bcache_size);
-
- rrddim_set_by_pointer(d->st_bcache_size, d->rd_bcache_dirty_size, dirty_data);
- rrdset_done(d->st_bcache_size);
- }
-
- {
- if(unlikely(!d->st_bcache_usage)) {
- d->st_bcache_usage = rrdset_create_localhost(
- "disk_bcache_usage"
- , d->device
- , d->disk
- , family
- , "disk.bcache_usage"
- , "BCache Cache Usage"
- , "percent"
- , "proc"
- , "diskstats"
- , 2123
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- d->rd_bcache_available_percent = rrddim_add(d->st_bcache_usage, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(d->st_bcache_usage);
-
- rrddim_set_by_pointer(d->st_bcache_usage, d->rd_bcache_available_percent, cache_available_percent);
- rrdset_done(d->st_bcache_usage);
- }
-
- if(d->do_bcache == CONFIG_BOOLEAN_YES || (d->do_bcache == CONFIG_BOOLEAN_AUTO && (stats_total_cache_hits != 0 || stats_total_cache_misses != 0 || stats_total_cache_miss_collisions != 0))) {
-
- if(unlikely(!d->st_bcache)) {
- d->st_bcache = rrdset_create_localhost(
- "disk_bcache"
- , d->device
- , d->disk
- , family
- , "disk.bcache"
- , "BCache Cache I/O Operations"
- , "operations/s"
- , "proc"
- , "diskstats"
- , 2124
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_bcache, RRDSET_FLAG_DETAIL);
-
- d->rd_bcache_hits = rrddim_add(d->st_bcache, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_bcache_misses = rrddim_add(d->st_bcache, "misses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_bcache_miss_collisions = rrddim_add(d->st_bcache, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_bcache_readaheads = rrddim_add(d->st_bcache, "readaheads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_bcache);
-
- rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_hits, stats_total_cache_hits);
- rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_misses, stats_total_cache_misses);
- rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_miss_collisions, stats_total_cache_miss_collisions);
- rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_readaheads, cache_readaheads);
- rrdset_done(d->st_bcache);
- }
-
- if(d->do_bcache == CONFIG_BOOLEAN_YES || (d->do_bcache == CONFIG_BOOLEAN_AUTO && (stats_total_cache_bypass_hits != 0 || stats_total_cache_bypass_misses != 0))) {
-
- if(unlikely(!d->st_bcache_bypass)) {
- d->st_bcache_bypass = rrdset_create_localhost(
- "disk_bcache_bypass"
- , d->device
- , d->disk
- , family
- , "disk.bcache_bypass"
- , "BCache Cache Bypass I/O Operations"
- , "operations/s"
- , "proc"
- , "diskstats"
- , 2125
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_bcache_bypass, RRDSET_FLAG_DETAIL);
-
- d->rd_bcache_bypass_hits = rrddim_add(d->st_bcache_bypass, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_bcache_bypass_misses = rrddim_add(d->st_bcache_bypass, "misses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_bcache_bypass);
-
- rrddim_set_by_pointer(d->st_bcache_bypass, d->rd_bcache_bypass_hits, stats_total_cache_bypass_hits);
- rrddim_set_by_pointer(d->st_bcache_bypass, d->rd_bcache_bypass_misses, stats_total_cache_bypass_misses);
- rrdset_done(d->st_bcache_bypass);
- }
- }
- }
-
-
- // ------------------------------------------------------------------------
- // update the system total I/O
-
- if(global_do_io == CONFIG_BOOLEAN_YES || (global_do_io == CONFIG_BOOLEAN_AUTO && (system_read_kb || system_write_kb))) {
- static RRDSET *st_io = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_io)) {
- st_io = rrdset_create_localhost(
- "system"
- , "io"
- , NULL
- , "disk"
- , NULL
- , "Disk I/O"
- , "kilobytes/s"
- , "proc"
- , "diskstats"
- , 150
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_io);
-
- rrddim_set_by_pointer(st_io, rd_in, system_read_kb);
- rrddim_set_by_pointer(st_io, rd_out, system_write_kb);
- rrdset_done(st_io);
- }
-
-
- // ------------------------------------------------------------------------
- // cleanup removed disks
-
- struct disk *d = disk_root, *last = NULL;
- while(d) {
- if(unlikely(global_cleanup_removed_disks && !d->updated)) {
- struct disk *t = d;
-
- rrdset_obsolete_and_pointer_null(d->st_avgsz);
- rrdset_obsolete_and_pointer_null(d->st_await);
- rrdset_obsolete_and_pointer_null(d->st_backlog);
- rrdset_obsolete_and_pointer_null(d->st_io);
- rrdset_obsolete_and_pointer_null(d->st_iotime);
- rrdset_obsolete_and_pointer_null(d->st_mops);
- rrdset_obsolete_and_pointer_null(d->st_ops);
- rrdset_obsolete_and_pointer_null(d->st_qops);
- rrdset_obsolete_and_pointer_null(d->st_svctm);
- rrdset_obsolete_and_pointer_null(d->st_util);
- rrdset_obsolete_and_pointer_null(d->st_bcache);
- rrdset_obsolete_and_pointer_null(d->st_bcache_bypass);
- rrdset_obsolete_and_pointer_null(d->st_bcache_rates);
- rrdset_obsolete_and_pointer_null(d->st_bcache_size);
- rrdset_obsolete_and_pointer_null(d->st_bcache_usage);
- rrdset_obsolete_and_pointer_null(d->st_bcache_hit_ratio);
-
- if(d == disk_root) {
- disk_root = d = d->next;
- last = NULL;
- }
- else if(last) {
- last->next = d = d->next;
- }
-
- freez(t->bcache_filename_dirty_data);
- freez(t->bcache_filename_writeback_rate);
- freez(t->bcache_filename_cache_congested);
- freez(t->bcache_filename_cache_available_percent);
- freez(t->bcache_filename_stats_five_minute_cache_hit_ratio);
- freez(t->bcache_filename_stats_hour_cache_hit_ratio);
- freez(t->bcache_filename_stats_day_cache_hit_ratio);
- freez(t->bcache_filename_stats_total_cache_hit_ratio);
- freez(t->bcache_filename_stats_total_cache_hits);
- freez(t->bcache_filename_stats_total_cache_misses);
- freez(t->bcache_filename_stats_total_cache_miss_collisions);
- freez(t->bcache_filename_stats_total_cache_bypass_hits);
- freez(t->bcache_filename_stats_total_cache_bypass_misses);
- freez(t->bcache_filename_stats_total_cache_readaheads);
-
- freez(t->disk);
- freez(t->device);
- freez(t->mount_point);
- freez(t);
- }
- else {
- d->updated = 0;
- last = d;
- d = d->next;
- }
- }
-
- return 0;
-}
diff --git a/src/proc_interrupts.c b/src/proc_interrupts.c
deleted file mode 100644
index 867f39eb2..000000000
--- a/src/proc_interrupts.c
+++ /dev/null
@@ -1,253 +0,0 @@
-#include "common.h"
-
-#define MAX_INTERRUPT_NAME 50
-
-struct cpu_interrupt {
- unsigned long long value;
- RRDDIM *rd;
-};
-
-struct interrupt {
- int used;
- char *id;
- char name[MAX_INTERRUPT_NAME + 1];
- RRDDIM *rd;
- unsigned long long total;
- struct cpu_interrupt cpu[];
-};
-
-// since each interrupt is variable in size
-// we use this to calculate its record size
-#define recordsize(cpus) (sizeof(struct interrupt) + ((cpus) * sizeof(struct cpu_interrupt)))
-
-// given a base, get a pointer to each record
-#define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[(line) * recordsize(cpus)])
-
-static inline struct interrupt *get_interrupts_array(size_t lines, int cpus) {
- static struct interrupt *irrs = NULL;
- static size_t allocated = 0;
-
- if(unlikely(lines != allocated)) {
- size_t l;
- int c;
-
- irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
-
- // reset all interrupt RRDDIM pointers as any line could have shifted
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- irr->rd = NULL;
- irr->name[0] = '\0';
- for(c = 0; c < cpus ;c++)
- irr->cpu[c].rd = NULL;
- }
-
- allocated = lines;
- }
-
- return irrs;
-}
-
-int do_proc_interrupts(int update_every, usec_t dt) {
- (void)dt;
- static procfile *ff = NULL;
- static int cpus = -1, do_per_core = -1;
- struct interrupt *irrs = NULL;
-
- if(unlikely(do_per_core == -1))
- do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1);
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/interrupts");
- ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- }
- if(unlikely(!ff))
- return 1;
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
- size_t words = procfile_linewords(ff, 0);
-
- if(unlikely(!lines)) {
- error("Cannot read /proc/interrupts, zero lines reported.");
- return 1;
- }
-
- // find how many CPUs are there
- if(unlikely(cpus == -1)) {
- uint32_t w;
- cpus = 0;
- for(w = 0; w < words ; w++) {
- if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
- cpus++;
- }
- }
-
- if(unlikely(!cpus)) {
- error("PLUGIN: PROC_INTERRUPTS: Cannot find the number of CPUs in /proc/interrupts");
- return 1;
- }
-
- // allocate the size we need;
- irrs = get_interrupts_array(lines, cpus);
- irrs[0].used = 0;
-
- // loop through all lines
- for(l = 1; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- irr->used = 0;
- irr->total = 0;
-
- words = procfile_linewords(ff, l);
- if(unlikely(!words)) continue;
-
- irr->id = procfile_lineword(ff, l, 0);
- if(unlikely(!irr->id || !irr->id[0])) continue;
-
- size_t idlen = strlen(irr->id);
- if(unlikely(idlen && irr->id[idlen - 1] == ':'))
- irr->id[idlen - 1] = '\0';
-
- int c;
- for(c = 0; c < cpus ;c++) {
- if(likely((c + 1) < (int)words))
- irr->cpu[c].value = str2ull(procfile_lineword(ff, l, (uint32_t)(c + 1)));
- else
- irr->cpu[c].value = 0;
-
- irr->total += irr->cpu[c].value;
- }
-
- if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) {
- strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME);
- size_t nlen = strlen(irr->name);
- idlen = strlen(irr->id);
- if(likely(nlen + 1 + idlen <= MAX_INTERRUPT_NAME)) {
- irr->name[nlen] = '_';
- strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen - 1);
- }
- else {
- irr->name[MAX_INTERRUPT_NAME - idlen - 1] = '_';
- strncpyz(&irr->name[MAX_INTERRUPT_NAME - idlen], irr->id, idlen);
- }
- }
- else {
- strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
- }
-
- irr->used = 1;
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_system_interrupts = NULL;
- if(unlikely(!st_system_interrupts))
- st_system_interrupts = rrdset_create_localhost(
- "system"
- , "interrupts"
- , NULL
- , "interrupts"
- , NULL
- , "System interrupts"
- , "interrupts/s"
- , "proc"
- , "interrupts"
- , 1000
- , update_every
- , RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_system_interrupts);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- if(unlikely(!irr->used)) continue;
-
- // some interrupt may have changed without changing the total number of lines
- // if the same number of interrupts have been added and removed between two
- // calls of this function.
- if(unlikely(!irr->rd || strncmp(irr->rd->name, irr->name, MAX_INTERRUPT_NAME) != 0)) {
- irr->rd = rrddim_find(st_system_interrupts, irr->id);
-
- if(unlikely(!irr->rd))
- irr->rd = rrddim_add(st_system_interrupts, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- else
- rrddim_set_name(st_system_interrupts, irr->rd, irr->name);
-
- // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
- if(likely(do_per_core)) {
- int c;
- for (c = 0; c < cpus ;c++) irr->cpu[c].rd = NULL;
- }
- }
-
- rrddim_set_by_pointer(st_system_interrupts, irr->rd, irr->total);
- }
-
- rrdset_done(st_system_interrupts);
-
- // --------------------------------------------------------------------
-
- if(likely(do_per_core)) {
- static RRDSET **core_st = NULL;
- static int old_cpus = 0;
-
- if(old_cpus < cpus) {
- core_st = reallocz(core_st, sizeof(RRDSET *) * cpus);
- memset(&core_st[old_cpus], 0, sizeof(RRDSET *) * (cpus - old_cpus));
- old_cpus = cpus;
- }
-
- int c;
-
- for(c = 0; c < cpus ;c++) {
- if(unlikely(!core_st[c])) {
- char id[50+1];
- snprintfz(id, 50, "cpu%d_interrupts", c);
-
- char title[100+1];
- snprintfz(title, 100, "CPU%d Interrupts", c);
- core_st[c] = rrdset_create_localhost(
- "cpu"
- , id
- , NULL
- , "interrupts"
- , "cpu.interrupts"
- , title
- , "interrupts/s"
- , "proc"
- , "interrupts"
- , 1100 + c
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(core_st[c]);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
-
- if(unlikely(!irr->used)) continue;
-
- if(unlikely(!irr->cpu[c].rd)) {
- irr->cpu[c].rd = rrddim_find(core_st[c], irr->id);
-
- if(unlikely(!irr->cpu[c].rd))
- irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- else
- rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name);
- }
-
- rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value);
- }
-
- rrdset_done(core_st[c]);
- }
- }
-
- return 0;
-}
diff --git a/src/proc_loadavg.c b/src/proc_loadavg.c
deleted file mode 100644
index 868f7d50a..000000000
--- a/src/proc_loadavg.c
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "common.h"
-
-// linux calculates this once every 5 seconds
-#define MIN_LOADAVG_UPDATE_EVERY 5
-
-int do_proc_loadavg(int update_every, usec_t dt) {
- static procfile *ff = NULL;
- static int do_loadavg = -1, do_all_processes = -1;
- static usec_t next_loadavg_dt = 0;
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/loadavg");
-
- ff = procfile_open(config_get("plugin:proc:/proc/loadavg", "filename to monitor", filename), " \t,:|/", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff))
- return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- if(unlikely(do_loadavg == -1)) {
- do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1);
- do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1);
- }
-
- if(unlikely(procfile_lines(ff) < 1)) {
- error("/proc/loadavg has no lines.");
- return 1;
- }
- if(unlikely(procfile_linewords(ff, 0) < 6)) {
- error("/proc/loadavg has less than 6 words in it.");
- return 1;
- }
-
- double load1 = strtod(procfile_lineword(ff, 0, 0), NULL);
- double load5 = strtod(procfile_lineword(ff, 0, 1), NULL);
- double load15 = strtod(procfile_lineword(ff, 0, 2), NULL);
-
- //unsigned long long running_processes = str2ull(procfile_lineword(ff, 0, 3));
- unsigned long long active_processes = str2ull(procfile_lineword(ff, 0, 4));
- //unsigned long long next_pid = str2ull(procfile_lineword(ff, 0, 5));
-
-
- // --------------------------------------------------------------------
-
- if(next_loadavg_dt <= dt) {
- if(likely(do_loadavg)) {
- static RRDSET *load_chart = NULL;
- static RRDDIM *rd_load1 = NULL, *rd_load5 = NULL, *rd_load15 = NULL;
-
- if(unlikely(!load_chart)) {
- load_chart = rrdset_create_localhost(
- "system"
- , "load"
- , NULL
- , "load"
- , NULL
- , "System Load Average"
- , "load"
- , "proc"
- , "loadavg"
- , 100
- , (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_load1 = rrddim_add(load_chart, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_load5 = rrddim_add(load_chart, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_load15 = rrddim_add(load_chart, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(load_chart);
-
- rrddim_set_by_pointer(load_chart, rd_load1, (collected_number) (load1 * 1000));
- rrddim_set_by_pointer(load_chart, rd_load5, (collected_number) (load5 * 1000));
- rrddim_set_by_pointer(load_chart, rd_load15, (collected_number) (load15 * 1000));
- rrdset_done(load_chart);
-
- next_loadavg_dt = load_chart->update_every * USEC_PER_SEC;
- }
- else next_loadavg_dt = MIN_LOADAVG_UPDATE_EVERY * USEC_PER_SEC;
- }
- else next_loadavg_dt -= dt;
-
- // --------------------------------------------------------------------
-
- if(likely(do_all_processes)) {
- static RRDSET *processes_chart = NULL;
- static RRDDIM *rd_active = NULL;
-
- if(unlikely(!processes_chart)) {
- processes_chart = rrdset_create_localhost(
- "system"
- , "active_processes"
- , NULL
- , "processes"
- , NULL
- , "System Active Processes"
- , "processes"
- , "proc"
- , "loadavg"
- , 750
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_active = rrddim_add(processes_chart, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(processes_chart);
-
- rrddim_set_by_pointer(processes_chart, rd_active, active_processes);
- rrdset_done(processes_chart);
- }
-
- return 0;
-}
diff --git a/src/proc_meminfo.c b/src/proc_meminfo.c
deleted file mode 100644
index 3915bf0e9..000000000
--- a/src/proc_meminfo.c
+++ /dev/null
@@ -1,514 +0,0 @@
-#include "common.h"
-
-int do_proc_meminfo(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
- static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1, do_hugepages = -1, do_transparent_hugepages = -1;
-
- static ARL_BASE *arl_base = NULL;
- static ARL_ENTRY *arl_hwcorrupted = NULL, *arl_memavailable = NULL;
-
- static unsigned long long
- MemTotal = 0,
- MemFree = 0,
- MemAvailable = 0,
- Buffers = 0,
- Cached = 0,
- //SwapCached = 0,
- //Active = 0,
- //Inactive = 0,
- //ActiveAnon = 0,
- //InactiveAnon = 0,
- //ActiveFile = 0,
- //InactiveFile = 0,
- //Unevictable = 0,
- //Mlocked = 0,
- SwapTotal = 0,
- SwapFree = 0,
- Dirty = 0,
- Writeback = 0,
- //AnonPages = 0,
- //Mapped = 0,
- //Shmem = 0,
- Slab = 0,
- SReclaimable = 0,
- SUnreclaim = 0,
- KernelStack = 0,
- PageTables = 0,
- NFS_Unstable = 0,
- Bounce = 0,
- WritebackTmp = 0,
- //CommitLimit = 0,
- Committed_AS = 0,
- //VmallocTotal = 0,
- VmallocUsed = 0,
- //VmallocChunk = 0,
- AnonHugePages = 0,
- ShmemHugePages = 0,
- HugePages_Total = 0,
- HugePages_Free = 0,
- HugePages_Rsvd = 0,
- HugePages_Surp = 0,
- Hugepagesize = 0,
- //DirectMap4k = 0,
- //DirectMap2M = 0,
- HardwareCorrupted = 0;
-
- if(unlikely(!arl_base)) {
- do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1);
- do_swap = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "system swap", CONFIG_BOOLEAN_AUTO);
- do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_BOOLEAN_AUTO);
- do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1);
- do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1);
- do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1);
- do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1);
- do_hugepages = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hugepages", CONFIG_BOOLEAN_AUTO);
- do_transparent_hugepages = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "transparent hugepages", CONFIG_BOOLEAN_AUTO);
-
- arl_base = arl_create("meminfo", NULL, 60);
- arl_expect(arl_base, "MemTotal", &MemTotal);
- arl_expect(arl_base, "MemFree", &MemFree);
- arl_memavailable = arl_expect(arl_base, "MemAvailable", &MemAvailable);
- arl_expect(arl_base, "Buffers", &Buffers);
- arl_expect(arl_base, "Cached", &Cached);
- //arl_expect(arl_base, "SwapCached", &SwapCached);
- //arl_expect(arl_base, "Active", &Active);
- //arl_expect(arl_base, "Inactive", &Inactive);
- //arl_expect(arl_base, "ActiveAnon", &ActiveAnon);
- //arl_expect(arl_base, "InactiveAnon", &InactiveAnon);
- //arl_expect(arl_base, "ActiveFile", &ActiveFile);
- //arl_expect(arl_base, "InactiveFile", &InactiveFile);
- //arl_expect(arl_base, "Unevictable", &Unevictable);
- //arl_expect(arl_base, "Mlocked", &Mlocked);
- arl_expect(arl_base, "SwapTotal", &SwapTotal);
- arl_expect(arl_base, "SwapFree", &SwapFree);
- arl_expect(arl_base, "Dirty", &Dirty);
- arl_expect(arl_base, "Writeback", &Writeback);
- //arl_expect(arl_base, "AnonPages", &AnonPages);
- //arl_expect(arl_base, "Mapped", &Mapped);
- //arl_expect(arl_base, "Shmem", &Shmem);
- arl_expect(arl_base, "Slab", &Slab);
- arl_expect(arl_base, "SReclaimable", &SReclaimable);
- arl_expect(arl_base, "SUnreclaim", &SUnreclaim);
- arl_expect(arl_base, "KernelStack", &KernelStack);
- arl_expect(arl_base, "PageTables", &PageTables);
- arl_expect(arl_base, "NFS_Unstable", &NFS_Unstable);
- arl_expect(arl_base, "Bounce", &Bounce);
- arl_expect(arl_base, "WritebackTmp", &WritebackTmp);
- //arl_expect(arl_base, "CommitLimit", &CommitLimit);
- arl_expect(arl_base, "Committed_AS", &Committed_AS);
- //arl_expect(arl_base, "VmallocTotal", &VmallocTotal);
- arl_expect(arl_base, "VmallocUsed", &VmallocUsed);
- //arl_expect(arl_base, "VmallocChunk", &VmallocChunk);
- arl_hwcorrupted = arl_expect(arl_base, "HardwareCorrupted", &HardwareCorrupted);
- arl_expect(arl_base, "AnonHugePages", &AnonHugePages);
- arl_expect(arl_base, "ShmemHugePages", &ShmemHugePages);
- arl_expect(arl_base, "HugePages_Total", &HugePages_Total);
- arl_expect(arl_base, "HugePages_Free", &HugePages_Free);
- arl_expect(arl_base, "HugePages_Rsvd", &HugePages_Rsvd);
- arl_expect(arl_base, "HugePages_Surp", &HugePages_Surp);
- arl_expect(arl_base, "Hugepagesize", &Hugepagesize);
- //arl_expect(arl_base, "DirectMap4k", &DirectMap4k);
- //arl_expect(arl_base, "DirectMap2M", &DirectMap2M);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/meminfo");
- ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff))
- return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- arl_begin(arl_base);
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 2)) continue;
-
- if(unlikely(arl_check(arl_base,
- procfile_lineword(ff, l, 0),
- procfile_lineword(ff, l, 1)))) break;
- }
-
- // --------------------------------------------------------------------
-
- // http://stackoverflow.com/questions/3019748/how-to-reliably-measure-available-memory-in-linux
- unsigned long long MemCached = Cached + Slab;
- unsigned long long MemUsed = MemTotal - MemFree - MemCached - Buffers;
-
- if(do_ram) {
- {
- static RRDSET *st_system_ram = NULL;
- static RRDDIM *rd_free = NULL, *rd_used = NULL, *rd_cached = NULL, *rd_buffers = NULL;
-
- if(unlikely(!st_system_ram)) {
- st_system_ram = rrdset_create_localhost(
- "system"
- , "ram"
- , NULL
- , "ram"
- , NULL
- , "System RAM"
- , "MB"
- , "proc"
- , "meminfo"
- , 200
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_free = rrddim_add(st_system_ram, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_used = rrddim_add(st_system_ram, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_cached = rrddim_add(st_system_ram, "cached", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_buffers = rrddim_add(st_system_ram, "buffers", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_system_ram);
-
- rrddim_set_by_pointer(st_system_ram, rd_free, MemFree);
- rrddim_set_by_pointer(st_system_ram, rd_used, MemUsed);
- rrddim_set_by_pointer(st_system_ram, rd_cached, MemCached);
- rrddim_set_by_pointer(st_system_ram, rd_buffers, Buffers);
-
- rrdset_done(st_system_ram);
- }
-
- if(arl_memavailable->flags & ARL_ENTRY_FLAG_FOUND) {
- static RRDSET *st_mem_available = NULL;
- static RRDDIM *rd_avail = NULL;
-
- if(unlikely(!st_mem_available)) {
- st_mem_available = rrdset_create_localhost(
- "mem"
- , "available"
- , NULL
- , "system"
- , NULL
- , "Available RAM for applications"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_SYSTEM_AVAILABLE
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_avail = rrddim_add(st_mem_available, "MemAvailable", "avail", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_available);
-
- rrddim_set_by_pointer(st_mem_available, rd_avail, MemAvailable);
-
- rrdset_done(st_mem_available);
- }
- }
-
- // --------------------------------------------------------------------
-
- unsigned long long SwapUsed = SwapTotal - SwapFree;
-
- if(do_swap == CONFIG_BOOLEAN_YES || SwapTotal || SwapUsed || SwapFree) {
- do_swap = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_system_swap = NULL;
- static RRDDIM *rd_free = NULL, *rd_used = NULL;
-
- if(unlikely(!st_system_swap)) {
- st_system_swap = rrdset_create_localhost(
- "system"
- , "swap"
- , NULL
- , "swap"
- , NULL
- , "System Swap"
- , "MB"
- , "proc"
- , "meminfo"
- , 201
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st_system_swap, RRDSET_FLAG_DETAIL);
-
- rd_free = rrddim_add(st_system_swap, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_used = rrddim_add(st_system_swap, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_system_swap);
-
- rrddim_set_by_pointer(st_system_swap, rd_used, SwapUsed);
- rrddim_set_by_pointer(st_system_swap, rd_free, SwapFree);
-
- rrdset_done(st_system_swap);
- }
-
- // --------------------------------------------------------------------
-
- if(arl_hwcorrupted->flags & ARL_ENTRY_FLAG_FOUND && (do_hwcorrupt == CONFIG_BOOLEAN_YES || (do_hwcorrupt == CONFIG_BOOLEAN_AUTO && HardwareCorrupted > 0))) {
- do_hwcorrupt = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_mem_hwcorrupt = NULL;
- static RRDDIM *rd_corrupted = NULL;
-
- if(unlikely(!st_mem_hwcorrupt)) {
- st_mem_hwcorrupt = rrdset_create_localhost(
- "mem"
- , "hwcorrupt"
- , NULL
- , "ecc"
- , NULL
- , "Corrupted Memory, detected by ECC"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_HW
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_mem_hwcorrupt, RRDSET_FLAG_DETAIL);
-
- rd_corrupted = rrddim_add(st_mem_hwcorrupt, "HardwareCorrupted", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_hwcorrupt);
-
- rrddim_set_by_pointer(st_mem_hwcorrupt, rd_corrupted, HardwareCorrupted);
-
- rrdset_done(st_mem_hwcorrupt);
- }
-
- // --------------------------------------------------------------------
-
- if(do_committed) {
- static RRDSET *st_mem_committed = NULL;
- static RRDDIM *rd_committed = NULL;
-
- if(unlikely(!st_mem_committed)) {
- st_mem_committed = rrdset_create_localhost(
- "mem"
- , "committed"
- , NULL
- , "system"
- , NULL
- , "Committed (Allocated) Memory"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(st_mem_committed, RRDSET_FLAG_DETAIL);
-
- rd_committed = rrddim_add(st_mem_committed, "Committed_AS", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_committed);
-
- rrddim_set_by_pointer(st_mem_committed, rd_committed, Committed_AS);
-
- rrdset_done(st_mem_committed);
- }
-
- // --------------------------------------------------------------------
-
- if(do_writeback) {
- static RRDSET *st_mem_writeback = NULL;
- static RRDDIM *rd_dirty = NULL, *rd_writeback = NULL, *rd_fusewriteback = NULL, *rd_nfs_writeback = NULL, *rd_bounce = NULL;
-
- if(unlikely(!st_mem_writeback)) {
- st_mem_writeback = rrdset_create_localhost(
- "mem"
- , "writeback"
- , NULL
- , "kernel"
- , NULL
- , "Writeback Memory"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_KERNEL
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_mem_writeback, RRDSET_FLAG_DETAIL);
-
- rd_dirty = rrddim_add(st_mem_writeback, "Dirty", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_writeback = rrddim_add(st_mem_writeback, "Writeback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_fusewriteback = rrddim_add(st_mem_writeback, "FuseWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_nfs_writeback = rrddim_add(st_mem_writeback, "NfsWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_bounce = rrddim_add(st_mem_writeback, "Bounce", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_writeback);
-
- rrddim_set_by_pointer(st_mem_writeback, rd_dirty, Dirty);
- rrddim_set_by_pointer(st_mem_writeback, rd_writeback, Writeback);
- rrddim_set_by_pointer(st_mem_writeback, rd_fusewriteback, WritebackTmp);
- rrddim_set_by_pointer(st_mem_writeback, rd_nfs_writeback, NFS_Unstable);
- rrddim_set_by_pointer(st_mem_writeback, rd_bounce, Bounce);
-
- rrdset_done(st_mem_writeback);
- }
-
- // --------------------------------------------------------------------
-
- if(do_kernel) {
- static RRDSET *st_mem_kernel = NULL;
- static RRDDIM *rd_slab = NULL, *rd_kernelstack = NULL, *rd_pagetables = NULL, *rd_vmallocused = NULL;
-
- if(unlikely(!st_mem_kernel)) {
- st_mem_kernel = rrdset_create_localhost(
- "mem"
- , "kernel"
- , NULL
- , "kernel"
- , NULL
- , "Memory Used by Kernel"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_KERNEL + 1
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st_mem_kernel, RRDSET_FLAG_DETAIL);
-
- rd_slab = rrddim_add(st_mem_kernel, "Slab", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_kernelstack = rrddim_add(st_mem_kernel, "KernelStack", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_pagetables = rrddim_add(st_mem_kernel, "PageTables", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_vmallocused = rrddim_add(st_mem_kernel, "VmallocUsed", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_kernel);
-
- rrddim_set_by_pointer(st_mem_kernel, rd_slab, Slab);
- rrddim_set_by_pointer(st_mem_kernel, rd_kernelstack, KernelStack);
- rrddim_set_by_pointer(st_mem_kernel, rd_pagetables, PageTables);
- rrddim_set_by_pointer(st_mem_kernel, rd_vmallocused, VmallocUsed);
-
- rrdset_done(st_mem_kernel);
- }
-
- // --------------------------------------------------------------------
-
- if(do_slab) {
- static RRDSET *st_mem_slab = NULL;
- static RRDDIM *rd_reclaimable = NULL, *rd_unreclaimable = NULL;
-
- if(unlikely(!st_mem_slab)) {
- st_mem_slab = rrdset_create_localhost(
- "mem"
- , "slab"
- , NULL
- , "slab"
- , NULL
- , "Reclaimable Kernel Memory"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_SLAB
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st_mem_slab, RRDSET_FLAG_DETAIL);
-
- rd_reclaimable = rrddim_add(st_mem_slab, "reclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_unreclaimable = rrddim_add(st_mem_slab, "unreclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_slab);
-
- rrddim_set_by_pointer(st_mem_slab, rd_reclaimable, SReclaimable);
- rrddim_set_by_pointer(st_mem_slab, rd_unreclaimable, SUnreclaim);
-
- rrdset_done(st_mem_slab);
- }
-
- // --------------------------------------------------------------------
-
- if(do_hugepages == CONFIG_BOOLEAN_YES || (do_hugepages == CONFIG_BOOLEAN_AUTO && Hugepagesize != 0 && HugePages_Total != 0)) {
- do_hugepages = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_mem_hugepages = NULL;
- static RRDDIM *rd_used = NULL, *rd_free = NULL, *rd_rsvd = NULL, *rd_surp = NULL;
-
- if(unlikely(!st_mem_hugepages)) {
- st_mem_hugepages = rrdset_create_localhost(
- "mem"
- , "hugepages"
- , NULL
- , "hugepages"
- , NULL
- , "Dedicated HugePages Memory"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_HUGEPAGES + 1
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st_mem_hugepages, RRDSET_FLAG_DETAIL);
-
- rd_free = rrddim_add(st_mem_hugepages, "free", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_used = rrddim_add(st_mem_hugepages, "used", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_surp = rrddim_add(st_mem_hugepages, "surplus", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_rsvd = rrddim_add(st_mem_hugepages, "reserved", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_hugepages);
-
- rrddim_set_by_pointer(st_mem_hugepages, rd_used, HugePages_Total - HugePages_Free - HugePages_Rsvd);
- rrddim_set_by_pointer(st_mem_hugepages, rd_free, HugePages_Free);
- rrddim_set_by_pointer(st_mem_hugepages, rd_rsvd, HugePages_Rsvd);
- rrddim_set_by_pointer(st_mem_hugepages, rd_surp, HugePages_Surp);
-
- rrdset_done(st_mem_hugepages);
- }
-
- // --------------------------------------------------------------------
-
- if(do_transparent_hugepages == CONFIG_BOOLEAN_YES || (do_transparent_hugepages == CONFIG_BOOLEAN_AUTO && (AnonHugePages != 0 || ShmemHugePages != 0))) {
- do_transparent_hugepages = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_mem_transparent_hugepages = NULL;
- static RRDDIM *rd_anonymous = NULL, *rd_shared = NULL;
-
- if(unlikely(!st_mem_transparent_hugepages)) {
- st_mem_transparent_hugepages = rrdset_create_localhost(
- "mem"
- , "transparent_hugepages"
- , NULL
- , "hugepages"
- , NULL
- , "Transparent HugePages Memory"
- , "MB"
- , "proc"
- , "meminfo"
- , NETDATA_CHART_PRIO_MEM_HUGEPAGES
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st_mem_transparent_hugepages, RRDSET_FLAG_DETAIL);
-
- rd_anonymous = rrddim_add(st_mem_transparent_hugepages, "anonymous", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_shared = rrddim_add(st_mem_transparent_hugepages, "shmem", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_mem_transparent_hugepages);
-
- rrddim_set_by_pointer(st_mem_transparent_hugepages, rd_anonymous, AnonHugePages);
- rrddim_set_by_pointer(st_mem_transparent_hugepages, rd_shared, ShmemHugePages);
-
- rrdset_done(st_mem_transparent_hugepages);
- }
-
- return 0;
-}
-
diff --git a/src/proc_net_dev.c b/src/proc_net_dev.c
deleted file mode 100644
index 341b9e0ca..000000000
--- a/src/proc_net_dev.c
+++ /dev/null
@@ -1,894 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// netdev list
-
-static struct netdev {
- char *name;
- uint32_t hash;
- size_t len;
-
- // flags
- int virtual;
- int configured;
- int enabled;
- int updated;
-
- int do_bandwidth;
- int do_packets;
- int do_errors;
- int do_drops;
- int do_fifo;
- int do_compressed;
- int do_events;
-
- const char *chart_type_net_bytes;
- const char *chart_type_net_packets;
- const char *chart_type_net_errors;
- const char *chart_type_net_fifo;
- const char *chart_type_net_events;
- const char *chart_type_net_drops;
- const char *chart_type_net_compressed;
-
- const char *chart_id_net_bytes;
- const char *chart_id_net_packets;
- const char *chart_id_net_errors;
- const char *chart_id_net_fifo;
- const char *chart_id_net_events;
- const char *chart_id_net_drops;
- const char *chart_id_net_compressed;
-
- const char *chart_family;
-
- int flipped;
- unsigned long priority;
-
- // data collected
- kernel_uint_t rbytes;
- kernel_uint_t rpackets;
- kernel_uint_t rerrors;
- kernel_uint_t rdrops;
- kernel_uint_t rfifo;
- kernel_uint_t rframe;
- kernel_uint_t rcompressed;
- kernel_uint_t rmulticast;
-
- kernel_uint_t tbytes;
- kernel_uint_t tpackets;
- kernel_uint_t terrors;
- kernel_uint_t tdrops;
- kernel_uint_t tfifo;
- kernel_uint_t tcollisions;
- kernel_uint_t tcarrier;
- kernel_uint_t tcompressed;
-
- // charts
- RRDSET *st_bandwidth;
- RRDSET *st_packets;
- RRDSET *st_errors;
- RRDSET *st_drops;
- RRDSET *st_fifo;
- RRDSET *st_compressed;
- RRDSET *st_events;
-
- // dimensions
- RRDDIM *rd_rbytes;
- RRDDIM *rd_rpackets;
- RRDDIM *rd_rerrors;
- RRDDIM *rd_rdrops;
- RRDDIM *rd_rfifo;
- RRDDIM *rd_rframe;
- RRDDIM *rd_rcompressed;
- RRDDIM *rd_rmulticast;
-
- RRDDIM *rd_tbytes;
- RRDDIM *rd_tpackets;
- RRDDIM *rd_terrors;
- RRDDIM *rd_tdrops;
- RRDDIM *rd_tfifo;
- RRDDIM *rd_tcollisions;
- RRDDIM *rd_tcarrier;
- RRDDIM *rd_tcompressed;
-
- struct netdev *next;
-} *netdev_root = NULL, *netdev_last_used = NULL;
-
-static size_t netdev_added = 0, netdev_found = 0;
-
-// ----------------------------------------------------------------------------
-
-static void netdev_charts_release(struct netdev *d) {
- if(d->st_bandwidth) rrdset_is_obsolete(d->st_bandwidth);
- if(d->st_packets) rrdset_is_obsolete(d->st_packets);
- if(d->st_errors) rrdset_is_obsolete(d->st_errors);
- if(d->st_drops) rrdset_is_obsolete(d->st_drops);
- if(d->st_fifo) rrdset_is_obsolete(d->st_fifo);
- if(d->st_compressed) rrdset_is_obsolete(d->st_compressed);
- if(d->st_events) rrdset_is_obsolete(d->st_events);
-
- d->st_bandwidth = NULL;
- d->st_compressed = NULL;
- d->st_drops = NULL;
- d->st_errors = NULL;
- d->st_events = NULL;
- d->st_fifo = NULL;
- d->st_packets = NULL;
-
- d->rd_rbytes = NULL;
- d->rd_rpackets = NULL;
- d->rd_rerrors = NULL;
- d->rd_rdrops = NULL;
- d->rd_rfifo = NULL;
- d->rd_rframe = NULL;
- d->rd_rcompressed = NULL;
- d->rd_rmulticast = NULL;
-
- d->rd_tbytes = NULL;
- d->rd_tpackets = NULL;
- d->rd_terrors = NULL;
- d->rd_tdrops = NULL;
- d->rd_tfifo = NULL;
- d->rd_tcollisions = NULL;
- d->rd_tcarrier = NULL;
- d->rd_tcompressed = NULL;
-}
-
-static void netdev_free_strings(struct netdev *d) {
- freez((void *)d->chart_type_net_bytes);
- freez((void *)d->chart_type_net_compressed);
- freez((void *)d->chart_type_net_drops);
- freez((void *)d->chart_type_net_errors);
- freez((void *)d->chart_type_net_events);
- freez((void *)d->chart_type_net_fifo);
- freez((void *)d->chart_type_net_packets);
-
- freez((void *)d->chart_id_net_bytes);
- freez((void *)d->chart_id_net_compressed);
- freez((void *)d->chart_id_net_drops);
- freez((void *)d->chart_id_net_errors);
- freez((void *)d->chart_id_net_events);
- freez((void *)d->chart_id_net_fifo);
- freez((void *)d->chart_id_net_packets);
-
- freez((void *)d->chart_family);
-}
-
-static void netdev_free(struct netdev *d) {
- netdev_charts_release(d);
- netdev_free_strings(d);
-
- freez((void *)d->name);
- freez((void *)d);
- netdev_added--;
-}
-
-
-// ----------------------------------------------------------------------------
-// netdev renames
-
-static struct netdev_rename {
- const char *host_device;
- uint32_t hash;
-
- const char *container_device;
- const char *container_name;
-
- int processed;
-
- struct netdev_rename *next;
-} *netdev_rename_root = NULL;
-
-static int netdev_pending_renames = 0;
-static netdata_mutex_t netdev_rename_mutex = NETDATA_MUTEX_INITIALIZER;
-
-static struct netdev_rename *netdev_rename_find(const char *host_device, uint32_t hash) {
- struct netdev_rename *r;
-
- for(r = netdev_rename_root; r ; r = r->next)
- if(r->hash == hash && !strcmp(host_device, r->host_device))
- return r;
-
- return NULL;
-}
-
-// other threads can call this function to register a rename to a netdev
-void netdev_rename_device_add(const char *host_device, const char *container_device, const char *container_name) {
- netdata_mutex_lock(&netdev_rename_mutex);
-
- uint32_t hash = simple_hash(host_device);
- struct netdev_rename *r = netdev_rename_find(host_device, hash);
- if(!r) {
- r = callocz(1, sizeof(struct netdev_rename));
- r->host_device = strdupz(host_device);
- r->container_device = strdupz(container_device);
- r->container_name = strdupz(container_name);
- r->hash = hash;
- r->next = netdev_rename_root;
- r->processed = 0;
- netdev_rename_root = r;
- netdev_pending_renames++;
- info("CGROUP: registered network interface rename for '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
- }
- else {
- if(strcmp(r->container_device, container_device) != 0 || strcmp(r->container_name, container_name) != 0) {
- freez((void *) r->container_device);
- freez((void *) r->container_name);
-
- r->container_device = strdupz(container_device);
- r->container_name = strdupz(container_name);
- r->processed = 0;
- netdev_pending_renames++;
- info("CGROUP: altered network interface rename for '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
- }
- }
-
- netdata_mutex_unlock(&netdev_rename_mutex);
-}
-
-// other threads can call this function to delete a rename to a netdev
-void netdev_rename_device_del(const char *host_device) {
- netdata_mutex_lock(&netdev_rename_mutex);
-
- struct netdev_rename *r, *last = NULL;
-
- uint32_t hash = simple_hash(host_device);
- for(r = netdev_rename_root; r ; last = r, r = r->next) {
- if (r->hash == hash && !strcmp(host_device, r->host_device)) {
- if (netdev_rename_root == r)
- netdev_rename_root = r->next;
- else if (last)
- last->next = r->next;
-
- if(!r->processed)
- netdev_pending_renames--;
-
- info("CGROUP: unregistered network interface rename for '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
-
- freez((void *) r->host_device);
- freez((void *) r->container_name);
- freez((void *) r->container_device);
- freez((void *) r);
- break;
- }
- }
-
- netdata_mutex_unlock(&netdev_rename_mutex);
-}
-
-static inline void netdev_rename_cgroup(struct netdev *d, struct netdev_rename *r) {
- info("CGROUP: renaming network interface '%s' as '%s' under '%s'", r->host_device, r->container_device, r->container_name);
-
- netdev_charts_release(d);
- netdev_free_strings(d);
-
- char buffer[RRD_ID_LENGTH_MAX + 1];
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "cgroup_%s", r->container_name);
- d->chart_type_net_bytes = strdupz(buffer);
- d->chart_type_net_compressed = strdupz(buffer);
- d->chart_type_net_drops = strdupz(buffer);
- d->chart_type_net_errors = strdupz(buffer);
- d->chart_type_net_events = strdupz(buffer);
- d->chart_type_net_fifo = strdupz(buffer);
- d->chart_type_net_packets = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_%s", r->container_device);
- d->chart_id_net_bytes = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_compressed_%s", r->container_device);
- d->chart_id_net_compressed = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_drops_%s", r->container_device);
- d->chart_id_net_drops = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_errors_%s", r->container_device);
- d->chart_id_net_errors = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_events_%s", r->container_device);
- d->chart_id_net_events = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_fifo_%s", r->container_device);
- d->chart_id_net_fifo = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net_packets_%s", r->container_device);
- d->chart_id_net_packets = strdupz(buffer);
-
- snprintfz(buffer, RRD_ID_LENGTH_MAX, "net %s", r->container_device);
- d->chart_family = strdupz(buffer);
-
- d->priority = 43000;
- d->flipped = 1;
-}
-
-static inline void netdev_rename(struct netdev *d) {
- struct netdev_rename *r = netdev_rename_find(d->name, d->hash);
- if(unlikely(r && !r->processed)) {
- netdev_rename_cgroup(d, r);
- r->processed = 1;
- netdev_pending_renames--;
- }
-}
-
-static inline void netdev_rename_lock(struct netdev *d) {
- netdata_mutex_lock(&netdev_rename_mutex);
- netdev_rename(d);
- netdata_mutex_unlock(&netdev_rename_mutex);
-}
-
-static inline void netdev_rename_all_lock(void) {
- netdata_mutex_lock(&netdev_rename_mutex);
-
- struct netdev *d;
- for(d = netdev_root; d ; d = d->next)
- netdev_rename(d);
-
- netdev_pending_renames = 0;
- netdata_mutex_unlock(&netdev_rename_mutex);
-}
-
-// ----------------------------------------------------------------------------
-// netdev data collection
-
-static void netdev_cleanup() {
- if(likely(netdev_found == netdev_added)) return;
-
- netdev_added = 0;
- struct netdev *d = netdev_root, *last = NULL;
- while(d) {
- if(unlikely(!d->updated)) {
- // info("Removing network device '%s', linked after '%s'", d->name, last?last->name:"ROOT");
-
- if(netdev_last_used == d)
- netdev_last_used = last;
-
- struct netdev *t = d;
-
- if(d == netdev_root || !last)
- netdev_root = d = d->next;
-
- else
- last->next = d = d->next;
-
- t->next = NULL;
- netdev_free(t);
- }
- else {
- netdev_added++;
- last = d;
- d->updated = 0;
- d = d->next;
- }
- }
-}
-
-static struct netdev *get_netdev(const char *name) {
- struct netdev *d;
-
- uint32_t hash = simple_hash(name);
-
- // search it, from the last position to the end
- for(d = netdev_last_used ; d ; d = d->next) {
- if(unlikely(hash == d->hash && !strcmp(name, d->name))) {
- netdev_last_used = d->next;
- return d;
- }
- }
-
- // search it from the beginning to the last position we used
- for(d = netdev_root ; d != netdev_last_used ; d = d->next) {
- if(unlikely(hash == d->hash && !strcmp(name, d->name))) {
- netdev_last_used = d->next;
- return d;
- }
- }
-
- // create a new one
- d = callocz(1, sizeof(struct netdev));
- d->name = strdupz(name);
- d->hash = simple_hash(d->name);
- d->len = strlen(d->name);
-
- d->chart_type_net_bytes = strdupz("net");
- d->chart_type_net_compressed = strdupz("net_compressed");
- d->chart_type_net_drops = strdupz("net_drops");
- d->chart_type_net_errors = strdupz("net_errors");
- d->chart_type_net_events = strdupz("net_events");
- d->chart_type_net_fifo = strdupz("net_fifo");
- d->chart_type_net_packets = strdupz("net_packets");
-
- d->chart_id_net_bytes = strdupz(d->name);
- d->chart_id_net_compressed = strdupz(d->name);
- d->chart_id_net_drops = strdupz(d->name);
- d->chart_id_net_errors = strdupz(d->name);
- d->chart_id_net_events = strdupz(d->name);
- d->chart_id_net_fifo = strdupz(d->name);
- d->chart_id_net_packets = strdupz(d->name);
-
- d->chart_family = strdupz(d->name);
- d->priority = 7000;
-
- netdev_rename_lock(d);
-
- netdev_added++;
-
- // link it to the end
- if(netdev_root) {
- struct netdev *e;
- for(e = netdev_root; e->next ; e = e->next) ;
- e->next = d;
- }
- else
- netdev_root = d;
-
- return d;
-}
-
-int do_proc_net_dev(int update_every, usec_t dt) {
- (void)dt;
- static SIMPLE_PATTERN *disabled_list = NULL;
- static procfile *ff = NULL;
- static int enable_new_interfaces = -1;
- static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
- static char *path_to_sys_devices_virtual_net = NULL;
-
- if(unlikely(enable_new_interfaces == -1)) {
- char filename[FILENAME_MAX + 1];
-
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/net/%s");
- path_to_sys_devices_virtual_net = config_get("plugin:proc:/proc/net/dev", "path to get virtual interfaces", filename);
-
- enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO);
-
- do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_BOOLEAN_AUTO);
- do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_BOOLEAN_AUTO);
- do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_BOOLEAN_AUTO);
- do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_BOOLEAN_AUTO);
- do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_BOOLEAN_AUTO);
- do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_BOOLEAN_AUTO);
- do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_BOOLEAN_AUTO);
-
- disabled_list = simple_pattern_create(config_get("plugin:proc:/proc/net/dev", "disable by default interfaces matching", "lo fireqos* *-ifb"), NULL, SIMPLE_PATTERN_EXACT);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/dev");
- ff = procfile_open(config_get("plugin:proc:/proc/net/dev", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- // rename all the devices, if we have pending renames
- if(unlikely(netdev_pending_renames))
- netdev_rename_all_lock();
-
- netdev_found = 0;
-
- kernel_uint_t system_rbytes = 0;
- kernel_uint_t system_tbytes = 0;
-
- size_t lines = procfile_lines(ff), l;
- for(l = 2; l < lines ;l++) {
- // require 17 words on each line
- if(unlikely(procfile_linewords(ff, l) < 17)) continue;
-
- struct netdev *d = get_netdev(procfile_lineword(ff, l, 0));
- d->updated = 1;
- netdev_found++;
-
- if(unlikely(!d->configured)) {
- // this is the first time we see this interface
-
- // remember we configured it
- d->configured = 1;
-
- d->enabled = enable_new_interfaces;
-
- if(d->enabled)
- d->enabled = !simple_pattern_matches(disabled_list, d->name);
-
- char buffer[FILENAME_MAX + 1];
-
- snprintfz(buffer, FILENAME_MAX, path_to_sys_devices_virtual_net, d->name);
- if(likely(access(buffer, R_OK) == 0)) {
- d->virtual = 1;
- }
- else
- d->virtual = 0;
-
- snprintfz(buffer, FILENAME_MAX, "plugin:proc:/proc/net/dev:%s", d->name);
- d->enabled = config_get_boolean_ondemand(buffer, "enabled", d->enabled);
- d->virtual = config_get_boolean(buffer, "virtual", d->virtual);
-
- if(d->enabled == CONFIG_BOOLEAN_NO)
- continue;
-
- d->do_bandwidth = config_get_boolean_ondemand(buffer, "bandwidth", do_bandwidth);
- d->do_packets = config_get_boolean_ondemand(buffer, "packets", do_packets);
- d->do_errors = config_get_boolean_ondemand(buffer, "errors", do_errors);
- d->do_drops = config_get_boolean_ondemand(buffer, "drops", do_drops);
- d->do_fifo = config_get_boolean_ondemand(buffer, "fifo", do_fifo);
- d->do_compressed = config_get_boolean_ondemand(buffer, "compressed", do_compressed);
- d->do_events = config_get_boolean_ondemand(buffer, "events", do_events);
- }
-
- if(unlikely(!d->enabled))
- continue;
-
- if(likely(d->do_bandwidth != CONFIG_BOOLEAN_NO || !d->virtual)) {
- d->rbytes = str2kernel_uint_t(procfile_lineword(ff, l, 1));
- d->tbytes = str2kernel_uint_t(procfile_lineword(ff, l, 9));
-
- if(likely(!d->virtual)) {
- system_rbytes += d->rbytes;
- system_tbytes += d->tbytes;
- }
- }
-
- if(likely(d->do_packets != CONFIG_BOOLEAN_NO)) {
- d->rpackets = str2kernel_uint_t(procfile_lineword(ff, l, 2));
- d->rmulticast = str2kernel_uint_t(procfile_lineword(ff, l, 8));
- d->tpackets = str2kernel_uint_t(procfile_lineword(ff, l, 10));
- }
-
- if(likely(d->do_errors != CONFIG_BOOLEAN_NO)) {
- d->rerrors = str2kernel_uint_t(procfile_lineword(ff, l, 3));
- d->terrors = str2kernel_uint_t(procfile_lineword(ff, l, 11));
- }
-
- if(likely(d->do_drops != CONFIG_BOOLEAN_NO)) {
- d->rdrops = str2kernel_uint_t(procfile_lineword(ff, l, 4));
- d->tdrops = str2kernel_uint_t(procfile_lineword(ff, l, 12));
- }
-
- if(likely(d->do_fifo != CONFIG_BOOLEAN_NO)) {
- d->rfifo = str2kernel_uint_t(procfile_lineword(ff, l, 5));
- d->tfifo = str2kernel_uint_t(procfile_lineword(ff, l, 13));
- }
-
- if(likely(d->do_compressed != CONFIG_BOOLEAN_NO)) {
- d->rcompressed = str2kernel_uint_t(procfile_lineword(ff, l, 7));
- d->tcompressed = str2kernel_uint_t(procfile_lineword(ff, l, 16));
- }
-
- if(likely(d->do_events != CONFIG_BOOLEAN_NO)) {
- d->rframe = str2kernel_uint_t(procfile_lineword(ff, l, 6));
- d->tcollisions = str2kernel_uint_t(procfile_lineword(ff, l, 14));
- d->tcarrier = str2kernel_uint_t(procfile_lineword(ff, l, 15));
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_bandwidth == CONFIG_BOOLEAN_AUTO && (d->rbytes || d->tbytes))))
- d->do_bandwidth = CONFIG_BOOLEAN_YES;
-
- if(d->do_bandwidth == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_bandwidth)) {
-
- d->st_bandwidth = rrdset_create_localhost(
- d->chart_type_net_bytes
- , d->chart_id_net_bytes
- , NULL
- , d->chart_family
- , "net.net"
- , "Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/dev"
- , d->priority
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- d->rd_rbytes = rrddim_add(d->st_bandwidth, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tbytes = rrddim_add(d->st_bandwidth, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
-
- if(d->flipped) {
- // flip receive/trasmit
-
- RRDDIM *td = d->rd_rbytes;
- d->rd_rbytes = d->rd_tbytes;
- d->rd_tbytes = td;
- }
- }
- else rrdset_next(d->st_bandwidth);
-
- rrddim_set_by_pointer(d->st_bandwidth, d->rd_rbytes, (collected_number)d->rbytes);
- rrddim_set_by_pointer(d->st_bandwidth, d->rd_tbytes, (collected_number)d->tbytes);
- rrdset_done(d->st_bandwidth);
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_packets == CONFIG_BOOLEAN_AUTO && (d->rpackets || d->tpackets || d->rmulticast))))
- d->do_packets = CONFIG_BOOLEAN_YES;
-
- if(d->do_packets == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_packets)) {
-
- d->st_packets = rrdset_create_localhost(
- d->chart_type_net_packets
- , d->chart_id_net_packets
- , NULL
- , d->chart_family
- , "net.packets"
- , "Packets"
- , "packets/s"
- , "proc"
- , "net/dev"
- , d->priority + 1
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_packets, RRDSET_FLAG_DETAIL);
-
- d->rd_rpackets = rrddim_add(d->st_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tpackets = rrddim_add(d->st_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_rmulticast = rrddim_add(d->st_packets, "multicast", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(d->flipped) {
- // flip receive/trasmit
-
- RRDDIM *td = d->rd_rpackets;
- d->rd_rpackets = d->rd_tpackets;
- d->rd_tpackets = td;
- }
- }
- else rrdset_next(d->st_packets);
-
- rrddim_set_by_pointer(d->st_packets, d->rd_rpackets, (collected_number)d->rpackets);
- rrddim_set_by_pointer(d->st_packets, d->rd_tpackets, (collected_number)d->tpackets);
- rrddim_set_by_pointer(d->st_packets, d->rd_rmulticast, (collected_number)d->rmulticast);
- rrdset_done(d->st_packets);
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_errors == CONFIG_BOOLEAN_AUTO && (d->rerrors || d->terrors))))
- d->do_errors = CONFIG_BOOLEAN_YES;
-
- if(d->do_errors == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_errors)) {
-
- d->st_errors = rrdset_create_localhost(
- d->chart_type_net_errors
- , d->chart_id_net_errors
- , NULL
- , d->chart_family
- , "net.errors"
- , "Interface Errors"
- , "errors/s"
- , "proc"
- , "net/dev"
- , d->priority + 2
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_errors, RRDSET_FLAG_DETAIL);
-
- d->rd_rerrors = rrddim_add(d->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_terrors = rrddim_add(d->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(d->flipped) {
- // flip receive/trasmit
-
- RRDDIM *td = d->rd_rerrors;
- d->rd_rerrors = d->rd_terrors;
- d->rd_terrors = td;
- }
- }
- else rrdset_next(d->st_errors);
-
- rrddim_set_by_pointer(d->st_errors, d->rd_rerrors, (collected_number)d->rerrors);
- rrddim_set_by_pointer(d->st_errors, d->rd_terrors, (collected_number)d->terrors);
- rrdset_done(d->st_errors);
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_drops == CONFIG_BOOLEAN_AUTO && (d->rdrops || d->tdrops))))
- d->do_drops = CONFIG_BOOLEAN_YES;
-
- if(d->do_drops == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_drops)) {
-
- d->st_drops = rrdset_create_localhost(
- d->chart_type_net_drops
- , d->chart_id_net_drops
- , NULL
- , d->chart_family
- , "net.drops"
- , "Interface Drops"
- , "drops/s"
- , "proc"
- , "net/dev"
- , d->priority + 3
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_drops, RRDSET_FLAG_DETAIL);
-
- d->rd_rdrops = rrddim_add(d->st_drops, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tdrops = rrddim_add(d->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(d->flipped) {
- // flip receive/trasmit
-
- RRDDIM *td = d->rd_rdrops;
- d->rd_rdrops = d->rd_tdrops;
- d->rd_tdrops = td;
- }
- }
- else rrdset_next(d->st_drops);
-
- rrddim_set_by_pointer(d->st_drops, d->rd_rdrops, (collected_number)d->rdrops);
- rrddim_set_by_pointer(d->st_drops, d->rd_tdrops, (collected_number)d->tdrops);
- rrdset_done(d->st_drops);
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_fifo == CONFIG_BOOLEAN_AUTO && (d->rfifo || d->tfifo))))
- d->do_fifo = CONFIG_BOOLEAN_YES;
-
- if(d->do_fifo == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_fifo)) {
-
- d->st_fifo = rrdset_create_localhost(
- d->chart_type_net_fifo
- , d->chart_id_net_fifo
- , NULL
- , d->chart_family
- , "net.fifo"
- , "Interface FIFO Buffer Errors"
- , "errors"
- , "proc"
- , "net/dev"
- , d->priority + 4
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_fifo, RRDSET_FLAG_DETAIL);
-
- d->rd_rfifo = rrddim_add(d->st_fifo, "receive", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tfifo = rrddim_add(d->st_fifo, "transmit", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(d->flipped) {
- // flip receive/trasmit
-
- RRDDIM *td = d->rd_rfifo;
- d->rd_rfifo = d->rd_tfifo;
- d->rd_tfifo = td;
- }
- }
- else rrdset_next(d->st_fifo);
-
- rrddim_set_by_pointer(d->st_fifo, d->rd_rfifo, (collected_number)d->rfifo);
- rrddim_set_by_pointer(d->st_fifo, d->rd_tfifo, (collected_number)d->tfifo);
- rrdset_done(d->st_fifo);
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_compressed == CONFIG_BOOLEAN_AUTO && (d->rcompressed || d->tcompressed))))
- d->do_compressed = CONFIG_BOOLEAN_YES;
-
- if(d->do_compressed == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_compressed)) {
-
- d->st_compressed = rrdset_create_localhost(
- d->chart_type_net_compressed
- , d->chart_id_net_compressed
- , NULL
- , d->chart_family
- , "net.compressed"
- , "Compressed Packets"
- , "packets/s"
- , "proc"
- , "net/dev"
- , d->priority + 5
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_compressed, RRDSET_FLAG_DETAIL);
-
- d->rd_rcompressed = rrddim_add(d->st_compressed, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tcompressed = rrddim_add(d->st_compressed, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(d->flipped) {
- // flip receive/trasmit
-
- RRDDIM *td = d->rd_rcompressed;
- d->rd_rcompressed = d->rd_tcompressed;
- d->rd_tcompressed = td;
- }
- }
- else rrdset_next(d->st_compressed);
-
- rrddim_set_by_pointer(d->st_compressed, d->rd_rcompressed, (collected_number)d->rcompressed);
- rrddim_set_by_pointer(d->st_compressed, d->rd_tcompressed, (collected_number)d->tcompressed);
- rrdset_done(d->st_compressed);
- }
-
- // --------------------------------------------------------------------
-
- if(unlikely((d->do_events == CONFIG_BOOLEAN_AUTO && (d->rframe || d->tcollisions || d->tcarrier))))
- d->do_events = CONFIG_BOOLEAN_YES;
-
- if(d->do_events == CONFIG_BOOLEAN_YES) {
- if(unlikely(!d->st_events)) {
-
- d->st_events = rrdset_create_localhost(
- d->chart_type_net_events
- , d->chart_id_net_events
- , NULL
- , d->chart_family
- , "net.events"
- , "Network Interface Events"
- , "events/s"
- , "proc"
- , "net/dev"
- , d->priority + 6
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(d->st_events, RRDSET_FLAG_DETAIL);
-
- d->rd_rframe = rrddim_add(d->st_events, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tcollisions = rrddim_add(d->st_events, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- d->rd_tcarrier = rrddim_add(d->st_events, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(d->st_events);
-
- rrddim_set_by_pointer(d->st_events, d->rd_rframe, (collected_number)d->rframe);
- rrddim_set_by_pointer(d->st_events, d->rd_tcollisions, (collected_number)d->tcollisions);
- rrddim_set_by_pointer(d->st_events, d->rd_tcarrier, (collected_number)d->tcarrier);
- rrdset_done(d->st_events);
- }
- }
-
- if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (system_rbytes || system_tbytes))) {
- do_bandwidth = CONFIG_BOOLEAN_YES;
- static RRDSET *st_system_net = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_system_net)) {
- st_system_net = rrdset_create_localhost(
- "system"
- , "net"
- , NULL
- , "network"
- , NULL
- , "Physical Network Interfaces Aggregated Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/dev"
- , 500
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st_system_net, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_system_net, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_system_net);
-
- rrddim_set_by_pointer(st_system_net, rd_in, (collected_number)system_rbytes);
- rrddim_set_by_pointer(st_system_net, rd_out, (collected_number)system_tbytes);
-
- rrdset_done(st_system_net);
- }
-
- netdev_cleanup();
-
- return 0;
-}
diff --git a/src/proc_net_ip_vs_stats.c b/src/proc_net_ip_vs_stats.c
deleted file mode 100644
index d76972f3c..000000000
--- a/src/proc_net_ip_vs_stats.c
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_NET_IPVS "ipvs"
-
-int do_proc_net_ip_vs_stats(int update_every, usec_t dt) {
- (void)dt;
- static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
- static procfile *ff = NULL;
-
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS bandwidth", 1);
- if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS connections", 1);
- if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS packets", 1);
-
- if(!ff) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/ip_vs_stats");
- ff = procfile_open(config_get("plugin:proc:/proc/net/ip_vs_stats", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
- }
- if(!ff) return 1;
-
- ff = procfile_readall(ff);
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
-
- // make sure we have 3 lines
- if(procfile_lines(ff) < 3) return 1;
-
- // make sure we have 5 words on the 3rd line
- if(procfile_linewords(ff, 2) < 5) return 1;
-
- unsigned long long entries, InPackets, OutPackets, InBytes, OutBytes;
-
- entries = strtoull(procfile_lineword(ff, 2, 0), NULL, 16);
- InPackets = strtoull(procfile_lineword(ff, 2, 1), NULL, 16);
- OutPackets = strtoull(procfile_lineword(ff, 2, 2), NULL, 16);
- InBytes = strtoull(procfile_lineword(ff, 2, 3), NULL, 16);
- OutBytes = strtoull(procfile_lineword(ff, 2, 4), NULL, 16);
-
-
- // --------------------------------------------------------------------
-
- if(do_sockets) {
- static RRDSET *st = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_IPVS
- , "sockets"
- , NULL
- , RRD_TYPE_NET_IPVS
- , NULL
- , "IPVS New Connections"
- , "connections/s"
- , "proc"
- , "net/ip_vs_stats"
- , 3101
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "connections", entries);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_packets) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_IPVS
- , "packets"
- , NULL
- , RRD_TYPE_NET_IPVS
- , NULL
- , "IPVS Packets"
- , "packets/s"
- , "proc"
- , "net/ip_vs_stats"
- , 3102
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "received", InPackets);
- rrddim_set(st, "sent", OutPackets);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_bandwidth) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_IPVS
- , "net"
- , NULL
- , RRD_TYPE_NET_IPVS
- , NULL
- , "IPVS Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/ip_vs_stats"
- , 3100
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "received", InBytes);
- rrddim_set(st, "sent", OutBytes);
- rrdset_done(st);
- }
-
- return 0;
-}
diff --git a/src/proc_net_netstat.c b/src/proc_net_netstat.c
deleted file mode 100644
index dd070e4c3..000000000
--- a/src/proc_net_netstat.c
+++ /dev/null
@@ -1,761 +0,0 @@
-#include "common.h"
-
-unsigned long long tcpext_TCPSynRetrans;
-
-static void parse_line_pair(procfile *ff, ARL_BASE *base, size_t header_line, size_t values_line) {
- size_t hwords = procfile_linewords(ff, header_line);
- size_t vwords = procfile_linewords(ff, values_line);
- size_t w;
-
- if(unlikely(vwords > hwords)) {
- error("File /proc/net/netstat on header line %zu has %zu words, but on value line %zu has %zu words.", header_line, hwords, values_line, vwords);
- vwords = hwords;
- }
-
- for(w = 1; w < vwords ;w++) {
- if(unlikely(arl_check(base, procfile_lineword(ff, header_line, w), procfile_lineword(ff, values_line, w))))
- break;
- }
-}
-
-int do_proc_net_netstat(int update_every, usec_t dt) {
- (void)dt;
-
- static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
- do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1,
- do_tcpext_listen = -1;
-
- static uint32_t hash_ipext = 0, hash_tcpext = 0;
- static procfile *ff = NULL;
-
- static ARL_BASE *arl_tcpext = NULL;
- static ARL_BASE *arl_ipext = NULL;
-
- // --------------------------------------------------------------------
- // IPv4
-
- // IPv4 bandwidth
- static unsigned long long ipext_InOctets = 0;
- static unsigned long long ipext_OutOctets = 0;
-
- // IPv4 input errors
- static unsigned long long ipext_InNoRoutes = 0;
- static unsigned long long ipext_InTruncatedPkts = 0;
- static unsigned long long ipext_InCsumErrors = 0;
-
- // IPv4 multicast bandwidth
- static unsigned long long ipext_InMcastOctets = 0;
- static unsigned long long ipext_OutMcastOctets = 0;
-
- // IPv4 multicast packets
- static unsigned long long ipext_InMcastPkts = 0;
- static unsigned long long ipext_OutMcastPkts = 0;
-
- // IPv4 broadcast bandwidth
- static unsigned long long ipext_InBcastOctets = 0;
- static unsigned long long ipext_OutBcastOctets = 0;
-
- // IPv4 broadcast packets
- static unsigned long long ipext_InBcastPkts = 0;
- static unsigned long long ipext_OutBcastPkts = 0;
-
- // IPv4 ECN
- static unsigned long long ipext_InNoECTPkts = 0;
- static unsigned long long ipext_InECT1Pkts = 0;
- static unsigned long long ipext_InECT0Pkts = 0;
- static unsigned long long ipext_InCEPkts = 0;
-
- // --------------------------------------------------------------------
- // IPv4 TCP
-
- // IPv4 TCP Reordering
- static unsigned long long tcpext_TCPRenoReorder = 0;
- static unsigned long long tcpext_TCPFACKReorder = 0;
- static unsigned long long tcpext_TCPSACKReorder = 0;
- static unsigned long long tcpext_TCPTSReorder = 0;
-
- // IPv4 TCP SYN Cookies
- static unsigned long long tcpext_SyncookiesSent = 0;
- static unsigned long long tcpext_SyncookiesRecv = 0;
- static unsigned long long tcpext_SyncookiesFailed = 0;
-
- // IPv4 TCP Out Of Order Queue
- // http://www.spinics.net/lists/netdev/msg204696.html
- static unsigned long long tcpext_TCPOFOQueue = 0; // Number of packets queued in OFO queue
- static unsigned long long tcpext_TCPOFODrop = 0; // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
- static unsigned long long tcpext_TCPOFOMerge = 0; // Number of packets in OFO that were merged with other packets.
- static unsigned long long tcpext_OfoPruned = 0; // packets dropped from out-of-order queue because of socket buffer overrun
-
- // IPv4 TCP connection resets
- // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
- static unsigned long long tcpext_TCPAbortOnData = 0; // connections reset due to unexpected data
- static unsigned long long tcpext_TCPAbortOnClose = 0; // connections reset due to early user close
- static unsigned long long tcpext_TCPAbortOnMemory = 0; // connections aborted due to memory pressure
- static unsigned long long tcpext_TCPAbortOnTimeout = 0; // connections aborted due to timeout
- static unsigned long long tcpext_TCPAbortOnLinger = 0; // connections aborted after user close in linger timeout
- static unsigned long long tcpext_TCPAbortFailed = 0; // times unable to send RST due to no memory
-
- // https://perfchron.com/2015/12/26/investigating-linux-network-issues-with-netstat-and-nstat/
- static unsigned long long tcpext_ListenOverflows = 0; // times the listen queue of a socket overflowed
- static unsigned long long tcpext_ListenDrops = 0; // SYNs to LISTEN sockets ignored
-
- // IPv4 TCP memory pressures
- static unsigned long long tcpext_TCPMemoryPressures = 0;
-
- // shared: tcpext_TCPSynRetrans
-
-
- if(unlikely(!arl_ipext)) {
- hash_ipext = simple_hash("IpExt");
- hash_tcpext = simple_hash("TcpExt");
-
- do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_BOOLEAN_AUTO);
- do_inerrors = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_BOOLEAN_AUTO);
- do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_BOOLEAN_AUTO);
- do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO);
- do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_BOOLEAN_AUTO);
- do_bcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_BOOLEAN_AUTO);
- do_ecn = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_BOOLEAN_AUTO);
-
- do_tcpext_reorder = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_BOOLEAN_AUTO);
- do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO);
- do_tcpext_ofo = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO);
- do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_BOOLEAN_AUTO);
- do_tcpext_memory = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_BOOLEAN_AUTO);
- do_tcpext_listen = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP listen issues", CONFIG_BOOLEAN_AUTO);
-
- arl_ipext = arl_create("netstat/ipext", NULL, 60);
- arl_tcpext = arl_create("netstat/tcpext", NULL, 60);
-
- // --------------------------------------------------------------------
- // IPv4
-
- if(do_bandwidth != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InOctets", &ipext_InOctets);
- arl_expect(arl_ipext, "OutOctets", &ipext_OutOctets);
- }
-
- if(do_inerrors != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InNoRoutes", &ipext_InNoRoutes);
- arl_expect(arl_ipext, "InTruncatedPkts", &ipext_InTruncatedPkts);
- arl_expect(arl_ipext, "InCsumErrors", &ipext_InCsumErrors);
- }
-
- if(do_mcast != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets);
- arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets);
- }
-
- if(do_mcast_p != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InMcastPkts", &ipext_InMcastPkts);
- arl_expect(arl_ipext, "OutMcastPkts", &ipext_OutMcastPkts);
- }
-
- if(do_bcast != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InBcastPkts", &ipext_InBcastPkts);
- arl_expect(arl_ipext, "OutBcastPkts", &ipext_OutBcastPkts);
- }
-
- if(do_bcast_p != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InBcastOctets", &ipext_InBcastOctets);
- arl_expect(arl_ipext, "OutBcastOctets", &ipext_OutBcastOctets);
- }
-
- if(do_ecn != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_ipext, "InNoECTPkts", &ipext_InNoECTPkts);
- arl_expect(arl_ipext, "InECT1Pkts", &ipext_InECT1Pkts);
- arl_expect(arl_ipext, "InECT0Pkts", &ipext_InECT0Pkts);
- arl_expect(arl_ipext, "InCEPkts", &ipext_InCEPkts);
- }
-
- // --------------------------------------------------------------------
- // IPv4 TCP
-
- if(do_tcpext_reorder != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder);
- arl_expect(arl_tcpext, "TCPSACKReorder", &tcpext_TCPSACKReorder);
- arl_expect(arl_tcpext, "TCPRenoReorder", &tcpext_TCPRenoReorder);
- arl_expect(arl_tcpext, "TCPTSReorder", &tcpext_TCPTSReorder);
- }
-
- if(do_tcpext_syscookies != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_tcpext, "SyncookiesSent", &tcpext_SyncookiesSent);
- arl_expect(arl_tcpext, "SyncookiesRecv", &tcpext_SyncookiesRecv);
- arl_expect(arl_tcpext, "SyncookiesFailed", &tcpext_SyncookiesFailed);
- }
-
- if(do_tcpext_ofo != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_tcpext, "TCPOFOQueue", &tcpext_TCPOFOQueue);
- arl_expect(arl_tcpext, "TCPOFODrop", &tcpext_TCPOFODrop);
- arl_expect(arl_tcpext, "TCPOFOMerge", &tcpext_TCPOFOMerge);
- arl_expect(arl_tcpext, "OfoPruned", &tcpext_OfoPruned);
- }
-
- if(do_tcpext_connaborts != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_tcpext, "TCPAbortOnData", &tcpext_TCPAbortOnData);
- arl_expect(arl_tcpext, "TCPAbortOnClose", &tcpext_TCPAbortOnClose);
- arl_expect(arl_tcpext, "TCPAbortOnMemory", &tcpext_TCPAbortOnMemory);
- arl_expect(arl_tcpext, "TCPAbortOnTimeout", &tcpext_TCPAbortOnTimeout);
- arl_expect(arl_tcpext, "TCPAbortOnLinger", &tcpext_TCPAbortOnLinger);
- arl_expect(arl_tcpext, "TCPAbortFailed", &tcpext_TCPAbortFailed);
- }
-
- if(do_tcpext_memory != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures);
- }
-
- if(do_tcpext_listen != CONFIG_BOOLEAN_NO) {
- arl_expect(arl_tcpext, "ListenOverflows", &tcpext_ListenOverflows);
- arl_expect(arl_tcpext, "ListenDrops", &tcpext_ListenDrops);
- }
-
- // shared metrics
- arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat");
- ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
- size_t words;
-
- arl_begin(arl_ipext);
- arl_begin(arl_tcpext);
-
- for(l = 0; l < lines ;l++) {
- char *key = procfile_lineword(ff, l, 0);
- uint32_t hash = simple_hash(key);
-
- if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
- size_t h = l++;
-
- words = procfile_linewords(ff, l);
- if(unlikely(words < 2)) {
- error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %zu.", words);
- continue;
- }
-
- parse_line_pair(ff, arl_ipext, h, l);
-
- // --------------------------------------------------------------------
-
- if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (ipext_InOctets || ipext_OutOctets))) {
- do_bandwidth = CONFIG_BOOLEAN_YES;
- static RRDSET *st_system_ipv4 = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_system_ipv4)) {
- st_system_ipv4 = rrdset_create_localhost(
- "system"
- , "ipv4"
- , NULL
- , "network"
- , NULL
- , "IPv4 Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/netstat"
- , 501
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st_system_ipv4, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_system_ipv4, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_system_ipv4);
-
- rrddim_set_by_pointer(st_system_ipv4, rd_in, ipext_InOctets);
- rrddim_set_by_pointer(st_system_ipv4, rd_out, ipext_OutOctets);
-
- rrdset_done(st_system_ipv4);
- }
-
- // --------------------------------------------------------------------
-
- if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && (ipext_InNoRoutes || ipext_InTruncatedPkts))) {
- do_inerrors = CONFIG_BOOLEAN_YES;
- static RRDSET *st_ipv4_inerrors = NULL;
- static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL;
-
- if(unlikely(!st_ipv4_inerrors)) {
- st_ipv4_inerrors = rrdset_create_localhost(
- "ipv4"
- , "inerrors"
- , NULL
- , "errors"
- , NULL
- , "IPv4 Input Errors"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 4000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_ipv4_inerrors, RRDSET_FLAG_DETAIL);
-
- rd_noroutes = rrddim_add(st_ipv4_inerrors, "InNoRoutes", "noroutes", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_truncated = rrddim_add(st_ipv4_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_checksum = rrddim_add(st_ipv4_inerrors, "InCsumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_ipv4_inerrors);
-
- rrddim_set_by_pointer(st_ipv4_inerrors, rd_noroutes, ipext_InNoRoutes);
- rrddim_set_by_pointer(st_ipv4_inerrors, rd_truncated, ipext_InTruncatedPkts);
- rrddim_set_by_pointer(st_ipv4_inerrors, rd_checksum, ipext_InCsumErrors);
-
- rrdset_done(st_ipv4_inerrors);
- }
-
- // --------------------------------------------------------------------
-
- if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (ipext_InMcastOctets || ipext_OutMcastOctets))) {
- do_mcast = CONFIG_BOOLEAN_YES;
- static RRDSET *st_ipv4_mcast = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_ipv4_mcast)) {
- st_ipv4_mcast = rrdset_create_localhost(
- "ipv4"
- , "mcast"
- , NULL
- , "multicast"
- , NULL
- , "IPv4 Multicast Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/netstat"
- , 9000
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(st_ipv4_mcast, RRDSET_FLAG_DETAIL);
-
- rd_in = rrddim_add(st_ipv4_mcast, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_ipv4_mcast, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_ipv4_mcast);
-
- rrddim_set_by_pointer(st_ipv4_mcast, rd_in, ipext_InMcastOctets);
- rrddim_set_by_pointer(st_ipv4_mcast, rd_out, ipext_OutMcastOctets);
-
- rrdset_done(st_ipv4_mcast);
- }
-
- // --------------------------------------------------------------------
-
- if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (ipext_InBcastOctets || ipext_OutBcastOctets))) {
- do_bcast = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_ipv4_bcast = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_ipv4_bcast)) {
- st_ipv4_bcast = rrdset_create_localhost(
- "ipv4"
- , "bcast"
- , NULL
- , "broadcast"
- , NULL
- , "IPv4 Broadcast Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/netstat"
- , 8000
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrdset_flag_set(st_ipv4_bcast, RRDSET_FLAG_DETAIL);
-
- rd_in = rrddim_add(st_ipv4_bcast, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_ipv4_bcast, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_ipv4_bcast);
-
- rrddim_set_by_pointer(st_ipv4_bcast, rd_in, ipext_InBcastOctets);
- rrddim_set_by_pointer(st_ipv4_bcast, rd_out, ipext_OutBcastOctets);
-
- rrdset_done(st_ipv4_bcast);
- }
-
- // --------------------------------------------------------------------
-
- if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InMcastPkts || ipext_OutMcastPkts))) {
- do_mcast_p = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_ipv4_mcastpkts = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_ipv4_mcastpkts)) {
- st_ipv4_mcastpkts = rrdset_create_localhost(
- "ipv4"
- , "mcastpkts"
- , NULL
- , "multicast"
- , NULL
- , "IPv4 Multicast Packets"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 8600
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_ipv4_mcastpkts, RRDSET_FLAG_DETAIL);
-
- rd_in = rrddim_add(st_ipv4_mcastpkts, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_ipv4_mcastpkts, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_ipv4_mcastpkts);
-
- rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_in, ipext_InMcastPkts);
- rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_out, ipext_OutMcastPkts);
-
- rrdset_done(st_ipv4_mcastpkts);
- }
-
- // --------------------------------------------------------------------
-
- if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InBcastPkts || ipext_OutBcastPkts))) {
- do_bcast_p = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_ipv4_bcastpkts = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_ipv4_bcastpkts)) {
- st_ipv4_bcastpkts = rrdset_create_localhost(
- "ipv4"
- , "bcastpkts"
- , NULL
- , "broadcast"
- , NULL
- , "IPv4 Broadcast Packets"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 8500
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_ipv4_bcastpkts, RRDSET_FLAG_DETAIL);
-
- rd_in = rrddim_add(st_ipv4_bcastpkts, "InBcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_ipv4_bcastpkts, "OutBcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_ipv4_bcastpkts);
-
- rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_in, ipext_InBcastPkts);
- rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_out, ipext_OutBcastPkts);
-
- rrdset_done(st_ipv4_bcastpkts);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) {
- do_ecn = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_ecnpkts = NULL;
- static RRDDIM *rd_cep = NULL, *rd_noectp = NULL, *rd_ectp0 = NULL, *rd_ectp1 = NULL;
-
- if(unlikely(!st_ecnpkts)) {
- st_ecnpkts = rrdset_create_localhost(
- "ipv4"
- , "ecnpkts"
- , NULL
- , "ecn"
- , NULL
- , "IPv4 ECN Statistics"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 8700
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_ecnpkts, RRDSET_FLAG_DETAIL);
-
- rd_cep = rrddim_add(st_ecnpkts, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_noectp = rrddim_add(st_ecnpkts, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ectp0 = rrddim_add(st_ecnpkts, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ectp1 = rrddim_add(st_ecnpkts, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_ecnpkts);
-
- rrddim_set_by_pointer(st_ecnpkts, rd_cep, ipext_InCEPkts);
- rrddim_set_by_pointer(st_ecnpkts, rd_noectp, ipext_InNoECTPkts);
- rrddim_set_by_pointer(st_ecnpkts, rd_ectp0, ipext_InECT0Pkts);
- rrddim_set_by_pointer(st_ecnpkts, rd_ectp1, ipext_InECT1Pkts);
-
- rrdset_done(st_ecnpkts);
- }
- }
- else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
- size_t h = l++;
-
- words = procfile_linewords(ff, l);
- if(unlikely(words < 2)) {
- error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words);
- continue;
- }
-
- parse_line_pair(ff, arl_tcpext, h, l);
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && (tcpext_TCPMemoryPressures))) {
- do_tcpext_memory = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_tcpmemorypressures = NULL;
- static RRDDIM *rd_pressures = NULL;
-
- if(unlikely(!st_tcpmemorypressures)) {
- st_tcpmemorypressures = rrdset_create_localhost(
- "ipv4"
- , "tcpmemorypressures"
- , NULL
- , "tcp"
- , NULL
- , "TCP Memory Pressures"
- , "events/s"
- , "proc"
- , "net/netstat"
- , 3000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_pressures = rrddim_add(st_tcpmemorypressures, "TCPMemoryPressures", "pressures", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_tcpmemorypressures);
-
- rrddim_set_by_pointer(st_tcpmemorypressures, rd_pressures, tcpext_TCPMemoryPressures);
-
- rrdset_done(st_tcpmemorypressures);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) {
- do_tcpext_connaborts = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_tcpconnaborts = NULL;
- static RRDDIM *rd_baddata = NULL, *rd_userclosed = NULL, *rd_nomemory = NULL, *rd_timeout = NULL, *rd_linger = NULL, *rd_failed = NULL;
-
- if(unlikely(!st_tcpconnaborts)) {
- st_tcpconnaborts = rrdset_create_localhost(
- "ipv4"
- , "tcpconnaborts"
- , NULL
- , "tcp"
- , NULL
- , "TCP Connection Aborts"
- , "connections/s"
- , "proc"
- , "net/netstat"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_baddata = rrddim_add(st_tcpconnaborts, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_userclosed = rrddim_add(st_tcpconnaborts, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_nomemory = rrddim_add(st_tcpconnaborts, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_timeout = rrddim_add(st_tcpconnaborts, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_linger = rrddim_add(st_tcpconnaborts, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st_tcpconnaborts, "TCPAbortFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_tcpconnaborts);
-
- rrddim_set_by_pointer(st_tcpconnaborts, rd_baddata, tcpext_TCPAbortOnData);
- rrddim_set_by_pointer(st_tcpconnaborts, rd_userclosed, tcpext_TCPAbortOnClose);
- rrddim_set_by_pointer(st_tcpconnaborts, rd_nomemory, tcpext_TCPAbortOnMemory);
- rrddim_set_by_pointer(st_tcpconnaborts, rd_timeout, tcpext_TCPAbortOnTimeout);
- rrddim_set_by_pointer(st_tcpconnaborts, rd_linger, tcpext_TCPAbortOnLinger);
- rrddim_set_by_pointer(st_tcpconnaborts, rd_failed, tcpext_TCPAbortFailed);
-
- rrdset_done(st_tcpconnaborts);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) {
- do_tcpext_reorder = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_tcpreorders = NULL;
- static RRDDIM *rd_timestamp = NULL, *rd_sack = NULL, *rd_fack = NULL, *rd_reno = NULL;
-
- if(unlikely(!st_tcpreorders)) {
- st_tcpreorders = rrdset_create_localhost(
- "ipv4"
- , "tcpreorders"
- , NULL
- , "tcp"
- , NULL
- , "TCP Reordered Packets by Detection Method"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 3020
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_timestamp = rrddim_add(st_tcpreorders, "TCPTSReorder", "timestamp", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sack = rrddim_add(st_tcpreorders, "TCPSACKReorder", "sack", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_fack = rrddim_add(st_tcpreorders, "TCPFACKReorder", "fack", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_reno = rrddim_add(st_tcpreorders, "TCPRenoReorder", "reno", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_tcpreorders);
-
- rrddim_set_by_pointer(st_tcpreorders, rd_timestamp, tcpext_TCPTSReorder);
- rrddim_set_by_pointer(st_tcpreorders, rd_sack, tcpext_TCPSACKReorder);
- rrddim_set_by_pointer(st_tcpreorders, rd_fack, tcpext_TCPFACKReorder);
- rrddim_set_by_pointer(st_tcpreorders, rd_reno, tcpext_TCPRenoReorder);
-
- rrdset_done(st_tcpreorders);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) {
- do_tcpext_ofo = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_ipv4_tcpofo = NULL;
- static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL;
-
- if(unlikely(!st_ipv4_tcpofo)) {
-
- st_ipv4_tcpofo = rrdset_create_localhost(
- "ipv4"
- , "tcpofo"
- , NULL
- , "tcp"
- , NULL
- , "TCP Out-Of-Order Queue"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 3050
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inqueue = rrddim_add(st_ipv4_tcpofo, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_dropped = rrddim_add(st_ipv4_tcpofo, "TCPOFODrop", "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_merged = rrddim_add(st_ipv4_tcpofo, "TCPOFOMerge", "merged", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_pruned = rrddim_add(st_ipv4_tcpofo, "OfoPruned", "pruned", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_ipv4_tcpofo);
-
- rrddim_set_by_pointer(st_ipv4_tcpofo, rd_inqueue, tcpext_TCPOFOQueue);
- rrddim_set_by_pointer(st_ipv4_tcpofo, rd_dropped, tcpext_TCPOFODrop);
- rrddim_set_by_pointer(st_ipv4_tcpofo, rd_merged, tcpext_TCPOFOMerge);
- rrddim_set_by_pointer(st_ipv4_tcpofo, rd_pruned, tcpext_OfoPruned);
-
- rrdset_done(st_ipv4_tcpofo);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) {
- do_tcpext_syscookies = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_syncookies = NULL;
- static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_failed = NULL;
-
- if(unlikely(!st_syncookies)) {
-
- st_syncookies = rrdset_create_localhost(
- "ipv4"
- , "tcpsyncookies"
- , NULL
- , "tcp"
- , NULL
- , "TCP SYN Cookies"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 3100
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st_syncookies, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st_syncookies, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st_syncookies, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_syncookies);
-
- rrddim_set_by_pointer(st_syncookies, rd_received, tcpext_SyncookiesRecv);
- rrddim_set_by_pointer(st_syncookies, rd_sent, tcpext_SyncookiesSent);
- rrddim_set_by_pointer(st_syncookies, rd_failed, tcpext_SyncookiesFailed);
-
- rrdset_done(st_syncookies);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) {
- do_tcpext_listen = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_listen = NULL;
- static RRDDIM *rd_overflows = NULL, *rd_drops = NULL;
-
- if(unlikely(!st_listen)) {
-
- st_listen = rrdset_create_localhost(
- "ipv4"
- , "tcplistenissues"
- , NULL
- , "tcp"
- , NULL
- , "TCP Listen Socket Issues"
- , "packets/s"
- , "proc"
- , "net/netstat"
- , 3015
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_drops = rrddim_add(st_listen, "ListenDrops", "drops", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_listen);
-
- rrddim_set_by_pointer(st_listen, rd_overflows, tcpext_ListenOverflows);
- rrddim_set_by_pointer(st_listen, rd_drops, tcpext_ListenDrops);
-
- rrdset_done(st_listen);
- }
- }
- }
-
- return 0;
-}
diff --git a/src/proc_net_rpc_nfs.c b/src/proc_net_rpc_nfs.c
deleted file mode 100644
index a4c778cba..000000000
--- a/src/proc_net_rpc_nfs.c
+++ /dev/null
@@ -1,449 +0,0 @@
-#include "common.h"
-
-struct nfs_procs {
- char name[30];
- unsigned long long value;
- int present;
- RRDDIM *rd;
-};
-
-struct nfs_procs nfs_proc2_values[] = {
- { "null" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"root" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"readlink", 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"wrcache" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"symlink" , 0ULL, 0, NULL}
- , {"mkdir" , 0ULL, 0, NULL}
- , {"rmdir" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"fsstat" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-struct nfs_procs nfs_proc3_values[] = {
- { "null" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"access" , 0ULL, 0, NULL}
- , {"readlink" , 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"mkdir" , 0ULL, 0, NULL}
- , {"symlink" , 0ULL, 0, NULL}
- , {"mknod" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rmdir" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"readdirplus", 0ULL, 0, NULL}
- , {"fsstat" , 0ULL, 0, NULL}
- , {"fsinfo" , 0ULL, 0, NULL}
- , {"pathconf" , 0ULL, 0, NULL}
- , {"commit" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-struct nfs_procs nfs_proc4_values[] = {
- { "null" , 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"commit" , 0ULL, 0, NULL}
- , {"open" , 0ULL, 0, NULL}
- , {"open_conf" , 0ULL, 0, NULL}
- , {"open_noat" , 0ULL, 0, NULL}
- , {"open_dgrd" , 0ULL, 0, NULL}
- , {"close" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"fsinfo" , 0ULL, 0, NULL}
- , {"renew" , 0ULL, 0, NULL}
- , {"setclntid" , 0ULL, 0, NULL}
- , {"confirm" , 0ULL, 0, NULL}
- , {"lock" , 0ULL, 0, NULL}
- , {"lockt" , 0ULL, 0, NULL}
- , {"locku" , 0ULL, 0, NULL}
- , {"access" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"lookup_root" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"symlink" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"pathconf" , 0ULL, 0, NULL}
- , {"statfs" , 0ULL, 0, NULL}
- , {"readlink" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"server_caps" , 0ULL, 0, NULL}
- , {"delegreturn" , 0ULL, 0, NULL}
- , {"getacl" , 0ULL, 0, NULL}
- , {"setacl" , 0ULL, 0, NULL}
- , {"fs_locations" , 0ULL, 0, NULL}
- , {"rel_lkowner" , 0ULL, 0, NULL}
- , {"secinfo" , 0ULL, 0, NULL}
- , {"fsid_present" , 0ULL, 0, NULL}
- ,
-
- /* nfsv4.1 client ops */
- { "exchange_id" , 0ULL, 0, NULL}
- , {"create_session" , 0ULL, 0, NULL}
- , {"destroy_session" , 0ULL, 0, NULL}
- , {"sequence" , 0ULL, 0, NULL}
- , {"get_lease_time" , 0ULL, 0, NULL}
- , {"reclaim_comp" , 0ULL, 0, NULL}
- , {"layoutget" , 0ULL, 0, NULL}
- , {"getdevinfo" , 0ULL, 0, NULL}
- , {"layoutcommit" , 0ULL, 0, NULL}
- , {"layoutreturn" , 0ULL, 0, NULL}
- , {"secinfo_no" , 0ULL, 0, NULL}
- , {"test_stateid" , 0ULL, 0, NULL}
- , {"free_stateid" , 0ULL, 0, NULL}
- , {"getdevicelist" , 0ULL, 0, NULL}
- , {"bind_conn_to_ses", 0ULL, 0, NULL}
- , {"destroy_clientid", 0ULL, 0, NULL}
- ,
-
- /* nfsv4.2 client ops */
- { "seek" , 0ULL, 0, NULL}
- , {"allocate" , 0ULL, 0, NULL}
- , {"deallocate" , 0ULL, 0, NULL}
- , {"layoutstats" , 0ULL, 0, NULL}
- , {"clone" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-int do_proc_net_rpc_nfs(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
- static int do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1;
- static int proc2_warning = 0, proc3_warning = 0, proc4_warning = 0;
-
- if(!ff) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfs");
- ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- }
- if(!ff) return 1;
-
- ff = procfile_readall(ff);
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
-
- if(do_net == -1) do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "network", 1);
- if(do_rpc == -1) do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "rpc", 1);
- if(do_proc2 == -1) do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v2 procedures", 1);
- if(do_proc3 == -1) do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v3 procedures", 1);
- if(do_proc4 == -1) do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v4 procedures", 1);
-
- // if they are enabled, reset them to 1
- // later we do them =2 to avoid doing strcmp() for all lines
- if(do_net) do_net = 1;
- if(do_rpc) do_rpc = 1;
- if(do_proc2) do_proc2 = 1;
- if(do_proc3) do_proc3 = 1;
- if(do_proc4) do_proc4 = 1;
-
- size_t lines = procfile_lines(ff), l;
-
- char *type;
- unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0;
- unsigned long long rpc_calls = 0, rpc_retransmits = 0, rpc_auth_refresh = 0;
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(!words) continue;
-
- type = procfile_lineword(ff, l, 0);
-
- if(do_net == 1 && strcmp(type, "net") == 0) {
- if(words < 5) {
- error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 5);
- continue;
- }
-
- net_count = str2ull(procfile_lineword(ff, l, 1));
- net_udp_count = str2ull(procfile_lineword(ff, l, 2));
- net_tcp_count = str2ull(procfile_lineword(ff, l, 3));
- net_tcp_connections = str2ull(procfile_lineword(ff, l, 4));
-
- unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections;
- if(sum == 0ULL) do_net = -1;
- else do_net = 2;
- }
- else if(do_rpc == 1 && strcmp(type, "rpc") == 0) {
- if(words < 4) {
- error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 6);
- continue;
- }
-
- rpc_calls = str2ull(procfile_lineword(ff, l, 1));
- rpc_retransmits = str2ull(procfile_lineword(ff, l, 2));
- rpc_auth_refresh = str2ull(procfile_lineword(ff, l, 3));
-
- unsigned long long sum = rpc_calls + rpc_retransmits + rpc_auth_refresh;
- if(sum == 0ULL) do_rpc = -1;
- else do_rpc = 2;
- }
- else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfs_proc2_values[i].name[0] ; i++, j++) {
- nfs_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfs_proc2_values[i].present = 1;
- sum += nfs_proc2_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc2_warning) {
- error("Disabling /proc/net/rpc/nfs v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc2_warning = 1;
- }
- do_proc2 = 0;
- }
- else do_proc2 = 2;
- }
- else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfs_proc3_values[i].name[0] ; i++, j++) {
- nfs_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfs_proc3_values[i].present = 1;
- sum += nfs_proc3_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc3_warning) {
- info("Disabling /proc/net/rpc/nfs v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc3_warning = 1;
- }
- do_proc3 = 0;
- }
- else do_proc3 = 2;
- }
- else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfs_proc4_values[i].name[0] ; i++, j++) {
- nfs_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfs_proc4_values[i].present = 1;
- sum += nfs_proc4_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc4_warning) {
- info("Disabling /proc/net/rpc/nfs v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc4_warning = 1;
- }
- do_proc4 = 0;
- }
- else do_proc4 = 2;
- }
- }
-
- // --------------------------------------------------------------------
-
- if(do_net == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_udp = NULL,
- *rd_tcp = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfs"
- , "net"
- , NULL
- , "network"
- , NULL
- , "NFS Client Network"
- , "operations/s"
- , "proc"
- , "net/rpc/nfs"
- , 2207
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- // ignore net_count, net_tcp_connections
- (void)net_count;
- (void)net_tcp_connections;
-
- rrddim_set_by_pointer(st, rd_udp, net_udp_count);
- rrddim_set_by_pointer(st, rd_tcp, net_tcp_count);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_rpc == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_calls = NULL,
- *rd_retransmits = NULL,
- *rd_auth_refresh = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfs"
- , "rpc"
- , NULL
- , "rpc"
- , NULL
- , "NFS Client Remote Procedure Calls Statistics"
- , "calls/s"
- , "proc"
- , "net/rpc/nfs"
- , 2208
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_retransmits = rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_auth_refresh = rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_calls, rpc_calls);
- rrddim_set_by_pointer(st, rd_retransmits, rpc_retransmits);
- rrddim_set_by_pointer(st, rd_auth_refresh, rpc_auth_refresh);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc2 == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfs"
- , "proc2"
- , NULL
- , "nfsv2rpc"
- , NULL
- , "NFS v2 Client Remote Procedure Calls"
- , "calls/s"
- , "proc"
- , "net/rpc/nfs"
- , 2209
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfs_proc2_values[i].present ; i++) {
- if(unlikely(!nfs_proc2_values[i].rd))
- nfs_proc2_values[i].rd = rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfs_proc2_values[i].rd, nfs_proc2_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc3 == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfs"
- , "proc3"
- , NULL
- , "nfsv3rpc"
- , NULL
- , "NFS v3 Client Remote Procedure Calls"
- , "calls/s"
- , "proc"
- , "net/rpc/nfs"
- , 2210
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfs_proc3_values[i].present ; i++) {
- if(unlikely(!nfs_proc3_values[i].rd))
- nfs_proc3_values[i].rd = rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfs_proc3_values[i].rd, nfs_proc3_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc4 == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfs"
- , "proc4"
- , NULL
- , "nfsv4rpc"
- , NULL
- , "NFS v4 Client Remote Procedure Calls"
- , "calls/s"
- , "proc"
- , "net/rpc/nfs"
- , 2211
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfs_proc4_values[i].present ; i++) {
- if(unlikely(!nfs_proc4_values[i].rd))
- nfs_proc4_values[i].rd = rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfs_proc4_values[i].rd, nfs_proc4_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- return 0;
-}
diff --git a/src/proc_net_rpc_nfsd.c b/src/proc_net_rpc_nfsd.c
deleted file mode 100644
index 8aca31aed..000000000
--- a/src/proc_net_rpc_nfsd.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-#include "common.h"
-
-struct nfsd_procs {
- char name[30];
- unsigned long long value;
- int present;
- RRDDIM *rd;
-};
-
-struct nfsd_procs nfsd_proc2_values[] = {
- { "null" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"root" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"readlink", 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"wrcache" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"symlink" , 0ULL, 0, NULL}
- , {"mkdir" , 0ULL, 0, NULL}
- , {"rmdir" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"fsstat" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-struct nfsd_procs nfsd_proc3_values[] = {
- { "null" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"access" , 0ULL, 0, NULL}
- , {"readlink" , 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"mkdir" , 0ULL, 0, NULL}
- , {"symlink" , 0ULL, 0, NULL}
- , {"mknod" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rmdir" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"readdirplus", 0ULL, 0, NULL}
- , {"fsstat" , 0ULL, 0, NULL}
- , {"fsinfo" , 0ULL, 0, NULL}
- , {"pathconf" , 0ULL, 0, NULL}
- , {"commit" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-struct nfsd_procs nfsd_proc4_values[] = {
- { "null" , 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"commit" , 0ULL, 0, NULL}
- , {"open" , 0ULL, 0, NULL}
- , {"open_conf" , 0ULL, 0, NULL}
- , {"open_noat" , 0ULL, 0, NULL}
- , {"open_dgrd" , 0ULL, 0, NULL}
- , {"close" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"fsinfo" , 0ULL, 0, NULL}
- , {"renew" , 0ULL, 0, NULL}
- , {"setclntid" , 0ULL, 0, NULL}
- , {"confirm" , 0ULL, 0, NULL}
- , {"lock" , 0ULL, 0, NULL}
- , {"lockt" , 0ULL, 0, NULL}
- , {"locku" , 0ULL, 0, NULL}
- , {"access" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"lookup_root" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"symlink" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"pathconf" , 0ULL, 0, NULL}
- , {"statfs" , 0ULL, 0, NULL}
- , {"readlink" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"server_caps" , 0ULL, 0, NULL}
- , {"delegreturn" , 0ULL, 0, NULL}
- , {"getacl" , 0ULL, 0, NULL}
- , {"setacl" , 0ULL, 0, NULL}
- , {"fs_locations" , 0ULL, 0, NULL}
- , {"rel_lkowner" , 0ULL, 0, NULL}
- , {"secinfo" , 0ULL, 0, NULL}
- , {"fsid_present" , 0ULL, 0, NULL}
- ,
-
- /* nfsv4.1 client ops */
- { "exchange_id" , 0ULL, 0, NULL}
- , {"create_session" , 0ULL, 0, NULL}
- , {"destroy_session" , 0ULL, 0, NULL}
- , {"sequence" , 0ULL, 0, NULL}
- , {"get_lease_time" , 0ULL, 0, NULL}
- , {"reclaim_comp" , 0ULL, 0, NULL}
- , {"layoutget" , 0ULL, 0, NULL}
- , {"getdevinfo" , 0ULL, 0, NULL}
- , {"layoutcommit" , 0ULL, 0, NULL}
- , {"layoutreturn" , 0ULL, 0, NULL}
- , {"secinfo_no" , 0ULL, 0, NULL}
- , {"test_stateid" , 0ULL, 0, NULL}
- , {"free_stateid" , 0ULL, 0, NULL}
- , {"getdevicelist" , 0ULL, 0, NULL}
- , {"bind_conn_to_ses", 0ULL, 0, NULL}
- , {"destroy_clientid", 0ULL, 0, NULL}
- ,
-
- /* nfsv4.2 client ops */
- { "seek" , 0ULL, 0, NULL}
- , {"allocate" , 0ULL, 0, NULL}
- , {"deallocate" , 0ULL, 0, NULL}
- , {"layoutstats" , 0ULL, 0, NULL}
- , {"clone" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-struct nfsd_procs nfsd4_ops_values[] = {
- { "unused_op0" , 0ULL, 0, NULL}
- , {"unused_op1" , 0ULL, 0, NULL}
- , {"future_op2" , 0ULL, 0, NULL}
- , {"access" , 0ULL, 0, NULL}
- , {"close" , 0ULL, 0, NULL}
- , {"commit" , 0ULL, 0, NULL}
- , {"create" , 0ULL, 0, NULL}
- , {"delegpurge" , 0ULL, 0, NULL}
- , {"delegreturn" , 0ULL, 0, NULL}
- , {"getattr" , 0ULL, 0, NULL}
- , {"getfh" , 0ULL, 0, NULL}
- , {"link" , 0ULL, 0, NULL}
- , {"lock" , 0ULL, 0, NULL}
- , {"lockt" , 0ULL, 0, NULL}
- , {"locku" , 0ULL, 0, NULL}
- , {"lookup" , 0ULL, 0, NULL}
- , {"lookup_root" , 0ULL, 0, NULL}
- , {"nverify" , 0ULL, 0, NULL}
- , {"open" , 0ULL, 0, NULL}
- , {"openattr" , 0ULL, 0, NULL}
- , {"open_confirm" , 0ULL, 0, NULL}
- , {"open_downgrade" , 0ULL, 0, NULL}
- , {"putfh" , 0ULL, 0, NULL}
- , {"putpubfh" , 0ULL, 0, NULL}
- , {"putrootfh" , 0ULL, 0, NULL}
- , {"read" , 0ULL, 0, NULL}
- , {"readdir" , 0ULL, 0, NULL}
- , {"readlink" , 0ULL, 0, NULL}
- , {"remove" , 0ULL, 0, NULL}
- , {"rename" , 0ULL, 0, NULL}
- , {"renew" , 0ULL, 0, NULL}
- , {"restorefh" , 0ULL, 0, NULL}
- , {"savefh" , 0ULL, 0, NULL}
- , {"secinfo" , 0ULL, 0, NULL}
- , {"setattr" , 0ULL, 0, NULL}
- , {"setclientid" , 0ULL, 0, NULL}
- , {"setclientid_confirm" , 0ULL, 0, NULL}
- , {"verify" , 0ULL, 0, NULL}
- , {"write" , 0ULL, 0, NULL}
- , {"release_lockowner" , 0ULL, 0, NULL}
- ,
-
- /* nfs41 */
- { "backchannel_ctl" , 0ULL, 0, NULL}
- , {"bind_conn_to_session", 0ULL, 0, NULL}
- , {"exchange_id" , 0ULL, 0, NULL}
- , {"create_session" , 0ULL, 0, NULL}
- , {"destroy_session" , 0ULL, 0, NULL}
- , {"free_stateid" , 0ULL, 0, NULL}
- , {"get_dir_delegation" , 0ULL, 0, NULL}
- , {"getdeviceinfo" , 0ULL, 0, NULL}
- , {"getdevicelist" , 0ULL, 0, NULL}
- , {"layoutcommit" , 0ULL, 0, NULL}
- , {"layoutget" , 0ULL, 0, NULL}
- , {"layoutreturn" , 0ULL, 0, NULL}
- , {"secinfo_no_name" , 0ULL, 0, NULL}
- , {"sequence" , 0ULL, 0, NULL}
- , {"set_ssv" , 0ULL, 0, NULL}
- , {"test_stateid" , 0ULL, 0, NULL}
- , {"want_delegation" , 0ULL, 0, NULL}
- , {"destroy_clientid" , 0ULL, 0, NULL}
- , {"reclaim_complete" , 0ULL, 0, NULL}
- ,
-
- /* nfs42 */
- { "allocate" , 0ULL, 0, NULL}
- , {"copy" , 0ULL, 0, NULL}
- , {"copy_notify" , 0ULL, 0, NULL}
- , {"deallocate" , 0ULL, 0, NULL}
- , {"ioadvise" , 0ULL, 0, NULL}
- , {"layouterror" , 0ULL, 0, NULL}
- , {"layoutstats" , 0ULL, 0, NULL}
- , {"offload_cancel" , 0ULL, 0, NULL}
- , {"offload_status" , 0ULL, 0, NULL}
- , {"read_plus" , 0ULL, 0, NULL}
- , {"seek" , 0ULL, 0, NULL}
- , {"write_same" , 0ULL, 0, NULL}
- ,
-
- /* termination */
- { "" , 0ULL, 0, NULL}
-};
-
-
-int do_proc_net_rpc_nfsd(int update_every, usec_t dt) {
- (void)dt;
- static procfile *ff = NULL;
- static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1;
- static int ra_warning = 0, th_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0;
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfsd");
- ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfsd", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- if(unlikely(do_rc == -1)) {
- do_rc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read cache", 1);
- do_fh = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "file handles", 1);
- do_io = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "I/O", 1);
- do_th = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "threads", 1);
- do_ra = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read ahead", 1);
- do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "network", 1);
- do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "rpc", 1);
- do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v2 procedures", 1);
- do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v3 procedures", 1);
- do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 procedures", 1);
- do_proc4ops = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 operations", 1);
- }
-
- // if they are enabled, reset them to 1
- // later we do them = 2 to avoid doing strcmp() for all lines
- if(do_rc) do_rc = 1;
- if(do_fh) do_fh = 1;
- if(do_io) do_io = 1;
- if(do_th) do_th = 1;
- if(do_ra) do_ra = 1;
- if(do_net) do_net = 1;
- if(do_rpc) do_rpc = 1;
- if(do_proc2) do_proc2 = 1;
- if(do_proc3) do_proc3 = 1;
- if(do_proc4) do_proc4 = 1;
- if(do_proc4ops) do_proc4ops = 1;
-
- size_t lines = procfile_lines(ff), l;
-
- char *type;
- unsigned long long rc_hits = 0, rc_misses = 0, rc_nocache = 0;
- unsigned long long fh_stale = 0, fh_total_lookups = 0, fh_anonymous_lookups = 0, fh_dir_not_in_dcache = 0, fh_non_dir_not_in_dcache = 0;
- unsigned long long io_read = 0, io_write = 0;
- unsigned long long th_threads = 0, th_fullcnt = 0, th_hist10 = 0, th_hist20 = 0, th_hist30 = 0, th_hist40 = 0, th_hist50 = 0, th_hist60 = 0, th_hist70 = 0, th_hist80 = 0, th_hist90 = 0, th_hist100 = 0;
- unsigned long long ra_size = 0, ra_hist10 = 0, ra_hist20 = 0, ra_hist30 = 0, ra_hist40 = 0, ra_hist50 = 0, ra_hist60 = 0, ra_hist70 = 0, ra_hist80 = 0, ra_hist90 = 0, ra_hist100 = 0, ra_none = 0;
- unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0;
- unsigned long long rpc_calls = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0;
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(!words)) continue;
-
- type = procfile_lineword(ff, l, 0);
-
- if(do_rc == 1 && strcmp(type, "rc") == 0) {
- if(unlikely(words < 4)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 4);
- continue;
- }
-
- rc_hits = str2ull(procfile_lineword(ff, l, 1));
- rc_misses = str2ull(procfile_lineword(ff, l, 2));
- rc_nocache = str2ull(procfile_lineword(ff, l, 3));
-
- unsigned long long sum = rc_hits + rc_misses + rc_nocache;
- if(sum == 0ULL) do_rc = -1;
- else do_rc = 2;
- }
- else if(do_fh == 1 && strcmp(type, "fh") == 0) {
- if(unlikely(words < 6)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 6);
- continue;
- }
-
- fh_stale = str2ull(procfile_lineword(ff, l, 1));
- fh_total_lookups = str2ull(procfile_lineword(ff, l, 2));
- fh_anonymous_lookups = str2ull(procfile_lineword(ff, l, 3));
- fh_dir_not_in_dcache = str2ull(procfile_lineword(ff, l, 4));
- fh_non_dir_not_in_dcache = str2ull(procfile_lineword(ff, l, 5));
-
- unsigned long long sum = fh_stale + fh_total_lookups + fh_anonymous_lookups + fh_dir_not_in_dcache + fh_non_dir_not_in_dcache;
- if(sum == 0ULL) do_fh = -1;
- else do_fh = 2;
- }
- else if(do_io == 1 && strcmp(type, "io") == 0) {
- if(unlikely(words < 3)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 3);
- continue;
- }
-
- io_read = str2ull(procfile_lineword(ff, l, 1));
- io_write = str2ull(procfile_lineword(ff, l, 2));
-
- unsigned long long sum = io_read + io_write;
- if(sum == 0ULL) do_io = -1;
- else do_io = 2;
- }
- else if(do_th == 1 && strcmp(type, "th") == 0) {
- if(unlikely(words < 13)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13);
- continue;
- }
-
- th_threads = str2ull(procfile_lineword(ff, l, 1));
- th_fullcnt = str2ull(procfile_lineword(ff, l, 2));
- th_hist10 = (unsigned long long)(atof(procfile_lineword(ff, l, 3)) * 1000.0);
- th_hist20 = (unsigned long long)(atof(procfile_lineword(ff, l, 4)) * 1000.0);
- th_hist30 = (unsigned long long)(atof(procfile_lineword(ff, l, 5)) * 1000.0);
- th_hist40 = (unsigned long long)(atof(procfile_lineword(ff, l, 6)) * 1000.0);
- th_hist50 = (unsigned long long)(atof(procfile_lineword(ff, l, 7)) * 1000.0);
- th_hist60 = (unsigned long long)(atof(procfile_lineword(ff, l, 8)) * 1000.0);
- th_hist70 = (unsigned long long)(atof(procfile_lineword(ff, l, 9)) * 1000.0);
- th_hist80 = (unsigned long long)(atof(procfile_lineword(ff, l, 10)) * 1000.0);
- th_hist90 = (unsigned long long)(atof(procfile_lineword(ff, l, 11)) * 1000.0);
- th_hist100 = (unsigned long long)(atof(procfile_lineword(ff, l, 12)) * 1000.0);
-
- // threads histogram has been disabled on recent kernels
- // http://permalink.gmane.org/gmane.linux.nfs/24528
- unsigned long long sum = th_hist10 + th_hist20 + th_hist30 + th_hist40 + th_hist50 + th_hist60 + th_hist70 + th_hist80 + th_hist90 + th_hist100;
- if(sum == 0ULL) {
- if(!th_warning) {
- info("Disabling /proc/net/rpc/nfsd threads histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- th_warning = 1;
- }
- do_th = -1;
- }
- else do_th = 2;
- }
- else if(do_ra == 1 && strcmp(type, "ra") == 0) {
- if(unlikely(words < 13)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13);
- continue;
- }
-
- ra_size = str2ull(procfile_lineword(ff, l, 1));
- ra_hist10 = str2ull(procfile_lineword(ff, l, 2));
- ra_hist20 = str2ull(procfile_lineword(ff, l, 3));
- ra_hist30 = str2ull(procfile_lineword(ff, l, 4));
- ra_hist40 = str2ull(procfile_lineword(ff, l, 5));
- ra_hist50 = str2ull(procfile_lineword(ff, l, 6));
- ra_hist60 = str2ull(procfile_lineword(ff, l, 7));
- ra_hist70 = str2ull(procfile_lineword(ff, l, 8));
- ra_hist80 = str2ull(procfile_lineword(ff, l, 9));
- ra_hist90 = str2ull(procfile_lineword(ff, l, 10));
- ra_hist100 = str2ull(procfile_lineword(ff, l, 11));
- ra_none = str2ull(procfile_lineword(ff, l, 12));
-
- unsigned long long sum = ra_hist10 + ra_hist20 + ra_hist30 + ra_hist40 + ra_hist50 + ra_hist60 + ra_hist70 + ra_hist80 + ra_hist90 + ra_hist100 + ra_none;
- if(sum == 0ULL) {
- if(!ra_warning) {
- info("Disabling /proc/net/rpc/nfsd read ahead histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- ra_warning = 1;
- }
- do_ra = -1;
- }
- else do_ra = 2;
- }
- else if(do_net == 1 && strcmp(type, "net") == 0) {
- if(unlikely(words < 5)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 5);
- continue;
- }
-
- net_count = str2ull(procfile_lineword(ff, l, 1));
- net_udp_count = str2ull(procfile_lineword(ff, l, 2));
- net_tcp_count = str2ull(procfile_lineword(ff, l, 3));
- net_tcp_connections = str2ull(procfile_lineword(ff, l, 4));
-
- unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections;
- if(sum == 0ULL) do_net = -1;
- else do_net = 2;
- }
- else if(do_rpc == 1 && strcmp(type, "rpc") == 0) {
- if(unlikely(words < 6)) {
- error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 6);
- continue;
- }
-
- rpc_calls = str2ull(procfile_lineword(ff, l, 1));
- rpc_bad_format = str2ull(procfile_lineword(ff, l, 2));
- rpc_bad_auth = str2ull(procfile_lineword(ff, l, 3));
- rpc_bad_client = str2ull(procfile_lineword(ff, l, 4));
-
- unsigned long long sum = rpc_calls + rpc_bad_format + rpc_bad_auth + rpc_bad_client;
- if(sum == 0ULL) do_rpc = -1;
- else do_rpc = 2;
- }
- else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfsd_proc2_values[i].name[0] ; i++, j++) {
- nfsd_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfsd_proc2_values[i].present = 1;
- sum += nfsd_proc2_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc2_warning) {
- error("Disabling /proc/net/rpc/nfsd v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc2_warning = 1;
- }
- do_proc2 = 0;
- }
- else do_proc2 = 2;
- }
- else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfsd_proc3_values[i].name[0] ; i++, j++) {
- nfsd_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfsd_proc3_values[i].present = 1;
- sum += nfsd_proc3_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc3_warning) {
- info("Disabling /proc/net/rpc/nfsd v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc3_warning = 1;
- }
- do_proc3 = 0;
- }
- else do_proc3 = 2;
- }
- else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfsd_proc4_values[i].name[0] ; i++, j++) {
- nfsd_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfsd_proc4_values[i].present = 1;
- sum += nfsd_proc4_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc4_warning) {
- info("Disabling /proc/net/rpc/nfsd v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc4_warning = 1;
- }
- do_proc4 = 0;
- }
- else do_proc4 = 2;
- }
- else if(do_proc4ops == 1 && strcmp(type, "proc4ops") == 0) {
- // the first number is the count of numbers present
- // so we start for word 2
-
- unsigned long long sum = 0;
- unsigned int i, j;
- for(i = 0, j = 2; j < words && nfsd4_ops_values[i].name[0] ; i++, j++) {
- nfsd4_ops_values[i].value = str2ull(procfile_lineword(ff, l, j));
- nfsd4_ops_values[i].present = 1;
- sum += nfsd4_ops_values[i].value;
- }
-
- if(sum == 0ULL) {
- if(!proc4ops_warning) {
- info("Disabling /proc/net/rpc/nfsd v4 operations chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
- proc4ops_warning = 1;
- }
- do_proc4ops = 0;
- }
- else do_proc4ops = 2;
- }
- }
-
- // --------------------------------------------------------------------
-
- if(do_rc == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_hits = NULL,
- *rd_misses = NULL,
- *rd_nocache = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "readcache"
- , NULL
- , "cache"
- , NULL
- , "NFS Server Read Cache"
- , "reads/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2100
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_hits = rrddim_add(st, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_misses = rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_nocache = rrddim_add(st, "nocache", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_hits, rc_hits);
- rrddim_set_by_pointer(st, rd_misses, rc_misses);
- rrddim_set_by_pointer(st, rd_nocache, rc_nocache);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_fh == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_stale = NULL,
- *rd_total_lookups = NULL,
- *rd_anonymous_lookups = NULL,
- *rd_dir_not_in_dcache = NULL,
- *rd_non_dir_not_in_dcache = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "filehandles"
- , NULL
- , "filehandles"
- , NULL
- , "NFS Server File Handles"
- , "handles/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2101
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_stale = rrddim_add(st, "stale", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_total_lookups = rrddim_add(st, "total_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_anonymous_lookups = rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_dir_not_in_dcache = rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_non_dir_not_in_dcache = rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_stale, fh_stale);
- rrddim_set_by_pointer(st, rd_total_lookups, fh_total_lookups);
- rrddim_set_by_pointer(st, rd_anonymous_lookups, fh_anonymous_lookups);
- rrddim_set_by_pointer(st, rd_dir_not_in_dcache, fh_dir_not_in_dcache);
- rrddim_set_by_pointer(st, rd_non_dir_not_in_dcache, fh_non_dir_not_in_dcache);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_io == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_read = NULL,
- *rd_write = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "io"
- , NULL
- , "io"
- , NULL
- , "NFS Server I/O"
- , "kilobytes/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2102
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_read = rrddim_add(st, "read", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rd_write = rrddim_add(st, "write", NULL, -1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_read, io_read);
- rrddim_set_by_pointer(st, rd_write, io_write);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_th == 2) {
- {
- static RRDSET *st = NULL;
- static RRDDIM *rd_threads = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "threads"
- , NULL
- , "threads"
- , NULL
- , "NFS Server Threads"
- , "threads"
- , "proc"
- , "net/rpc/nfsd"
- , 2103
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_threads = rrddim_add(st, "threads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_threads, th_threads);
- rrdset_done(st);
- }
-
- {
- static RRDSET *st = NULL;
- static RRDDIM *rd_full_count = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "threads_fullcnt"
- , NULL
- , "threads"
- , NULL
- , "NFS Server Threads Full Count"
- , "ops/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2104
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_full_count = rrddim_add(st, "full_count", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_full_count, th_fullcnt);
- rrdset_done(st);
- }
-
- {
- static RRDSET *st = NULL;
- static RRDDIM *rd_th_hist10 = NULL,
- *rd_th_hist20 = NULL,
- *rd_th_hist30 = NULL,
- *rd_th_hist40 = NULL,
- *rd_th_hist50 = NULL,
- *rd_th_hist60 = NULL,
- *rd_th_hist70 = NULL,
- *rd_th_hist80 = NULL,
- *rd_th_hist90 = NULL,
- *rd_th_hist100 = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "threads_histogram"
- , NULL
- , "threads"
- , NULL
- , "NFS Server Threads Usage Histogram"
- , "percentage"
- , "proc"
- , "net/rpc/nfsd"
- , 2105
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_th_hist10 = rrddim_add(st, "0%-10%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist20 = rrddim_add(st, "10%-20%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist30 = rrddim_add(st, "20%-30%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist40 = rrddim_add(st, "30%-40%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist50 = rrddim_add(st, "40%-50%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist60 = rrddim_add(st, "50%-60%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist70 = rrddim_add(st, "60%-70%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist80 = rrddim_add(st, "70%-80%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist90 = rrddim_add(st, "80%-90%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rd_th_hist100 = rrddim_add(st, "90%-100%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_th_hist10, th_hist10);
- rrddim_set_by_pointer(st, rd_th_hist20, th_hist20);
- rrddim_set_by_pointer(st, rd_th_hist30, th_hist30);
- rrddim_set_by_pointer(st, rd_th_hist40, th_hist40);
- rrddim_set_by_pointer(st, rd_th_hist50, th_hist50);
- rrddim_set_by_pointer(st, rd_th_hist60, th_hist60);
- rrddim_set_by_pointer(st, rd_th_hist70, th_hist70);
- rrddim_set_by_pointer(st, rd_th_hist80, th_hist80);
- rrddim_set_by_pointer(st, rd_th_hist90, th_hist90);
- rrddim_set_by_pointer(st, rd_th_hist100, th_hist100);
- rrdset_done(st);
- }
- }
-
- // --------------------------------------------------------------------
-
- if(do_ra == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_ra_hist10 = NULL,
- *rd_ra_hist20 = NULL,
- *rd_ra_hist30 = NULL,
- *rd_ra_hist40 = NULL,
- *rd_ra_hist50 = NULL,
- *rd_ra_hist60 = NULL,
- *rd_ra_hist70 = NULL,
- *rd_ra_hist80 = NULL,
- *rd_ra_hist90 = NULL,
- *rd_ra_hist100 = NULL,
- *rd_ra_none = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "readahead"
- , NULL
- , "readahead"
- , NULL
- , "NFS Server Read Ahead Depth"
- , "percentage"
- , "proc"
- , "net/rpc/nfsd"
- , 2105
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_ra_hist10 = rrddim_add(st, "10%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist20 = rrddim_add(st, "20%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist30 = rrddim_add(st, "30%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist40 = rrddim_add(st, "40%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist50 = rrddim_add(st, "50%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist60 = rrddim_add(st, "60%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist70 = rrddim_add(st, "70%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist80 = rrddim_add(st, "80%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist90 = rrddim_add(st, "90%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_hist100 = rrddim_add(st, "100%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_ra_none = rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else rrdset_next(st);
-
- // ignore ra_size
- (void)ra_size;
-
- rrddim_set_by_pointer(st, rd_ra_hist10, ra_hist10);
- rrddim_set_by_pointer(st, rd_ra_hist20, ra_hist20);
- rrddim_set_by_pointer(st, rd_ra_hist30, ra_hist30);
- rrddim_set_by_pointer(st, rd_ra_hist40, ra_hist40);
- rrddim_set_by_pointer(st, rd_ra_hist50, ra_hist50);
- rrddim_set_by_pointer(st, rd_ra_hist60, ra_hist60);
- rrddim_set_by_pointer(st, rd_ra_hist70, ra_hist70);
- rrddim_set_by_pointer(st, rd_ra_hist80, ra_hist80);
- rrddim_set_by_pointer(st, rd_ra_hist90, ra_hist90);
- rrddim_set_by_pointer(st, rd_ra_hist100,ra_hist100);
- rrddim_set_by_pointer(st, rd_ra_none, ra_none);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_net == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_udp = NULL,
- *rd_tcp = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "net"
- , NULL
- , "network"
- , NULL
- , "NFS Server Network Statistics"
- , "packets/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2107
- , update_every
- , RRDSET_TYPE_STACKED
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- // ignore net_count, net_tcp_connections
- (void)net_count;
- (void)net_tcp_connections;
-
- rrddim_set_by_pointer(st, rd_udp, net_udp_count);
- rrddim_set_by_pointer(st, rd_tcp, net_tcp_count);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_rpc == 2) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_calls = NULL,
- *rd_bad_format = NULL,
- *rd_bad_auth = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "rpc"
- , NULL
- , "rpc"
- , NULL
- , "NFS Server Remote Procedure Calls Statistics"
- , "calls/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2108
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_bad_format = rrddim_add(st, "bad_format", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_bad_auth = rrddim_add(st, "bad_auth", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- // ignore rpc_bad_client
- (void)rpc_bad_client;
-
- rrddim_set_by_pointer(st, rd_calls, rpc_calls);
- rrddim_set_by_pointer(st, rd_bad_format, rpc_bad_format);
- rrddim_set_by_pointer(st, rd_bad_auth, rpc_bad_auth);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc2 == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "proc2"
- , NULL
- , "nfsv2rpc"
- , NULL
- , "NFS v2 Server Remote Procedure Calls"
- , "calls/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2109
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfsd_proc2_values[i].present ; i++) {
- if(unlikely(!nfsd_proc2_values[i].rd))
- nfsd_proc2_values[i].rd = rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfsd_proc2_values[i].rd, nfsd_proc2_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc3 == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "proc3"
- , NULL
- , "nfsv3rpc"
- , NULL
- , "NFS v3 Server Remote Procedure Calls"
- , "calls/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2110
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfsd_proc3_values[i].present ; i++) {
- if(unlikely(!nfsd_proc3_values[i].rd))
- nfsd_proc3_values[i].rd = rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfsd_proc3_values[i].rd, nfsd_proc3_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc4 == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "proc4"
- , NULL
- , "nfsv4rpc"
- , NULL
- , "NFS v4 Server Remote Procedure Calls"
- , "calls/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2111
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfsd_proc4_values[i].present ; i++) {
- if(unlikely(!nfsd_proc4_values[i].rd))
- nfsd_proc4_values[i].rd = rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfsd_proc4_values[i].rd, nfsd_proc4_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_proc4ops == 2) {
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "nfsd"
- , "proc4ops"
- , NULL
- , "nfsv2ops"
- , NULL
- , "NFS v4 Server Operations"
- , "operations/s"
- , "proc"
- , "net/rpc/nfsd"
- , 2112
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else rrdset_next(st);
-
- size_t i;
- for(i = 0; nfsd4_ops_values[i].present ; i++) {
- if(unlikely(!nfsd4_ops_values[i].rd))
- nfsd4_ops_values[i].rd = rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st, nfsd4_ops_values[i].rd, nfsd4_ops_values[i].value);
- }
-
- rrdset_done(st);
- }
-
- return 0;
-}
diff --git a/src/proc_net_snmp.c b/src/proc_net_snmp.c
deleted file mode 100644
index 43c010c14..000000000
--- a/src/proc_net_snmp.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_NET_SNMP "ipv4"
-
-static struct proc_net_snmp {
- // kernel_uint_t ip_Forwarding;
- kernel_uint_t ip_DefaultTTL;
- kernel_uint_t ip_InReceives;
- kernel_uint_t ip_InHdrErrors;
- kernel_uint_t ip_InAddrErrors;
- kernel_uint_t ip_ForwDatagrams;
- kernel_uint_t ip_InUnknownProtos;
- kernel_uint_t ip_InDiscards;
- kernel_uint_t ip_InDelivers;
- kernel_uint_t ip_OutRequests;
- kernel_uint_t ip_OutDiscards;
- kernel_uint_t ip_OutNoRoutes;
- kernel_uint_t ip_ReasmTimeout;
- kernel_uint_t ip_ReasmReqds;
- kernel_uint_t ip_ReasmOKs;
- kernel_uint_t ip_ReasmFails;
- kernel_uint_t ip_FragOKs;
- kernel_uint_t ip_FragFails;
- kernel_uint_t ip_FragCreates;
-
- kernel_uint_t icmp_InMsgs;
- kernel_uint_t icmp_OutMsgs;
- kernel_uint_t icmp_InErrors;
- kernel_uint_t icmp_OutErrors;
- kernel_uint_t icmp_InCsumErrors;
-
- kernel_uint_t icmpmsg_InEchoReps;
- kernel_uint_t icmpmsg_OutEchoReps;
- kernel_uint_t icmpmsg_InDestUnreachs;
- kernel_uint_t icmpmsg_OutDestUnreachs;
- kernel_uint_t icmpmsg_InRedirects;
- kernel_uint_t icmpmsg_OutRedirects;
- kernel_uint_t icmpmsg_InEchos;
- kernel_uint_t icmpmsg_OutEchos;
- kernel_uint_t icmpmsg_InRouterAdvert;
- kernel_uint_t icmpmsg_OutRouterAdvert;
- kernel_uint_t icmpmsg_InRouterSelect;
- kernel_uint_t icmpmsg_OutRouterSelect;
- kernel_uint_t icmpmsg_InTimeExcds;
- kernel_uint_t icmpmsg_OutTimeExcds;
- kernel_uint_t icmpmsg_InParmProbs;
- kernel_uint_t icmpmsg_OutParmProbs;
- kernel_uint_t icmpmsg_InTimestamps;
- kernel_uint_t icmpmsg_OutTimestamps;
- kernel_uint_t icmpmsg_InTimestampReps;
- kernel_uint_t icmpmsg_OutTimestampReps;
-
- //kernel_uint_t tcp_RtoAlgorithm;
- //kernel_uint_t tcp_RtoMin;
- //kernel_uint_t tcp_RtoMax;
- ssize_t tcp_MaxConn;
- kernel_uint_t tcp_ActiveOpens;
- kernel_uint_t tcp_PassiveOpens;
- kernel_uint_t tcp_AttemptFails;
- kernel_uint_t tcp_EstabResets;
- kernel_uint_t tcp_CurrEstab;
- kernel_uint_t tcp_InSegs;
- kernel_uint_t tcp_OutSegs;
- kernel_uint_t tcp_RetransSegs;
- kernel_uint_t tcp_InErrs;
- kernel_uint_t tcp_OutRsts;
- kernel_uint_t tcp_InCsumErrors;
-
- kernel_uint_t udp_InDatagrams;
- kernel_uint_t udp_NoPorts;
- kernel_uint_t udp_InErrors;
- kernel_uint_t udp_OutDatagrams;
- kernel_uint_t udp_RcvbufErrors;
- kernel_uint_t udp_SndbufErrors;
- kernel_uint_t udp_InCsumErrors;
- kernel_uint_t udp_IgnoredMulti;
-
- kernel_uint_t udplite_InDatagrams;
- kernel_uint_t udplite_NoPorts;
- kernel_uint_t udplite_InErrors;
- kernel_uint_t udplite_OutDatagrams;
- kernel_uint_t udplite_RcvbufErrors;
- kernel_uint_t udplite_SndbufErrors;
- kernel_uint_t udplite_InCsumErrors;
- kernel_uint_t udplite_IgnoredMulti;
-} snmp_root = { 0 };
-
-int do_proc_net_snmp(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
- static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
- do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcp_opens = -1,
- do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1, do_udplite_packets = -1;
- static uint32_t hash_ip = 0, hash_icmp = 0, hash_tcp = 0, hash_udp = 0, hash_icmpmsg = 0, hash_udplite = 0;
-
- static ARL_BASE *arl_ip = NULL,
- *arl_icmp = NULL,
- *arl_icmpmsg = NULL,
- *arl_tcp = NULL,
- *arl_udp = NULL,
- *arl_udplite = NULL;
-
- static RRDVAR *tcp_max_connections_var = NULL;
- static ssize_t last_max_connections = 0;
-
- if(unlikely(!arl_ip)) {
- do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
- do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1);
- do_ip_fragsin = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1);
- do_ip_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1);
- do_tcp_sockets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1);
- do_tcp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1);
- do_tcp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1);
- do_tcp_opens = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP opens", 1);
- do_tcp_handshake = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1);
- do_udp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1);
- do_udp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1);
- do_icmp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP packets", 1);
- do_icmpmsg = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 ICMP messages", 1);
- do_udplite_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDPLite packets", 1);
-
- hash_ip = simple_hash("Ip");
- hash_tcp = simple_hash("Tcp");
- hash_udp = simple_hash("Udp");
- hash_icmp = simple_hash("Icmp");
- hash_icmpmsg = simple_hash("IcmpMsg");
- hash_udplite = simple_hash("UdpLite");
-
- arl_ip = arl_create("snmp/Ip", arl_callback_str2kernel_uint_t, 60);
- // arl_expect(arl_ip, "Forwarding", &snmp_root.ip_Forwarding);
- arl_expect(arl_ip, "DefaultTTL", &snmp_root.ip_DefaultTTL);
- arl_expect(arl_ip, "InReceives", &snmp_root.ip_InReceives);
- arl_expect(arl_ip, "InHdrErrors", &snmp_root.ip_InHdrErrors);
- arl_expect(arl_ip, "InAddrErrors", &snmp_root.ip_InAddrErrors);
- arl_expect(arl_ip, "ForwDatagrams", &snmp_root.ip_ForwDatagrams);
- arl_expect(arl_ip, "InUnknownProtos", &snmp_root.ip_InUnknownProtos);
- arl_expect(arl_ip, "InDiscards", &snmp_root.ip_InDiscards);
- arl_expect(arl_ip, "InDelivers", &snmp_root.ip_InDelivers);
- arl_expect(arl_ip, "OutRequests", &snmp_root.ip_OutRequests);
- arl_expect(arl_ip, "OutDiscards", &snmp_root.ip_OutDiscards);
- arl_expect(arl_ip, "OutNoRoutes", &snmp_root.ip_OutNoRoutes);
- arl_expect(arl_ip, "ReasmTimeout", &snmp_root.ip_ReasmTimeout);
- arl_expect(arl_ip, "ReasmReqds", &snmp_root.ip_ReasmReqds);
- arl_expect(arl_ip, "ReasmOKs", &snmp_root.ip_ReasmOKs);
- arl_expect(arl_ip, "ReasmFails", &snmp_root.ip_ReasmFails);
- arl_expect(arl_ip, "FragOKs", &snmp_root.ip_FragOKs);
- arl_expect(arl_ip, "FragFails", &snmp_root.ip_FragFails);
- arl_expect(arl_ip, "FragCreates", &snmp_root.ip_FragCreates);
-
- arl_icmp = arl_create("snmp/Icmp", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_icmp, "InMsgs", &snmp_root.icmp_InMsgs);
- arl_expect(arl_icmp, "OutMsgs", &snmp_root.icmp_OutMsgs);
- arl_expect(arl_icmp, "InErrors", &snmp_root.icmp_InErrors);
- arl_expect(arl_icmp, "OutErrors", &snmp_root.icmp_OutErrors);
- arl_expect(arl_icmp, "InCsumErrors", &snmp_root.icmp_InCsumErrors);
-
- arl_icmpmsg = arl_create("snmp/Icmpmsg", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_icmpmsg, "InType0", &snmp_root.icmpmsg_InEchoReps);
- arl_expect(arl_icmpmsg, "OutType0", &snmp_root.icmpmsg_OutEchoReps);
- arl_expect(arl_icmpmsg, "InType3", &snmp_root.icmpmsg_InDestUnreachs);
- arl_expect(arl_icmpmsg, "OutType3", &snmp_root.icmpmsg_OutDestUnreachs);
- arl_expect(arl_icmpmsg, "InType5", &snmp_root.icmpmsg_InRedirects);
- arl_expect(arl_icmpmsg, "OutType5", &snmp_root.icmpmsg_OutRedirects);
- arl_expect(arl_icmpmsg, "InType8", &snmp_root.icmpmsg_InEchos);
- arl_expect(arl_icmpmsg, "OutType8", &snmp_root.icmpmsg_OutEchos);
- arl_expect(arl_icmpmsg, "InType9", &snmp_root.icmpmsg_InRouterAdvert);
- arl_expect(arl_icmpmsg, "OutType9", &snmp_root.icmpmsg_OutRouterAdvert);
- arl_expect(arl_icmpmsg, "InType10", &snmp_root.icmpmsg_InRouterSelect);
- arl_expect(arl_icmpmsg, "OutType10", &snmp_root.icmpmsg_OutRouterSelect);
- arl_expect(arl_icmpmsg, "InType11", &snmp_root.icmpmsg_InTimeExcds);
- arl_expect(arl_icmpmsg, "OutType11", &snmp_root.icmpmsg_OutTimeExcds);
- arl_expect(arl_icmpmsg, "InType12", &snmp_root.icmpmsg_InParmProbs);
- arl_expect(arl_icmpmsg, "OutType12", &snmp_root.icmpmsg_OutParmProbs);
- arl_expect(arl_icmpmsg, "InType13", &snmp_root.icmpmsg_InTimestamps);
- arl_expect(arl_icmpmsg, "OutType13", &snmp_root.icmpmsg_OutTimestamps);
- arl_expect(arl_icmpmsg, "InType14", &snmp_root.icmpmsg_InTimestampReps);
- arl_expect(arl_icmpmsg, "OutType14", &snmp_root.icmpmsg_OutTimestampReps);
-
- arl_tcp = arl_create("snmp/Tcp", arl_callback_str2kernel_uint_t, 60);
- // arl_expect(arl_tcp, "RtoAlgorithm", &snmp_root.tcp_RtoAlgorithm);
- // arl_expect(arl_tcp, "RtoMin", &snmp_root.tcp_RtoMin);
- // arl_expect(arl_tcp, "RtoMax", &snmp_root.tcp_RtoMax);
- arl_expect(arl_tcp, "MaxConn", &snmp_root.tcp_MaxConn);
- arl_expect(arl_tcp, "ActiveOpens", &snmp_root.tcp_ActiveOpens);
- arl_expect(arl_tcp, "PassiveOpens", &snmp_root.tcp_PassiveOpens);
- arl_expect(arl_tcp, "AttemptFails", &snmp_root.tcp_AttemptFails);
- arl_expect(arl_tcp, "EstabResets", &snmp_root.tcp_EstabResets);
- arl_expect(arl_tcp, "CurrEstab", &snmp_root.tcp_CurrEstab);
- arl_expect(arl_tcp, "InSegs", &snmp_root.tcp_InSegs);
- arl_expect(arl_tcp, "OutSegs", &snmp_root.tcp_OutSegs);
- arl_expect(arl_tcp, "RetransSegs", &snmp_root.tcp_RetransSegs);
- arl_expect(arl_tcp, "InErrs", &snmp_root.tcp_InErrs);
- arl_expect(arl_tcp, "OutRsts", &snmp_root.tcp_OutRsts);
- arl_expect(arl_tcp, "InCsumErrors", &snmp_root.tcp_InCsumErrors);
-
- arl_udp = arl_create("snmp/Udp", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_udp, "InDatagrams", &snmp_root.udp_InDatagrams);
- arl_expect(arl_udp, "NoPorts", &snmp_root.udp_NoPorts);
- arl_expect(arl_udp, "InErrors", &snmp_root.udp_InErrors);
- arl_expect(arl_udp, "OutDatagrams", &snmp_root.udp_OutDatagrams);
- arl_expect(arl_udp, "RcvbufErrors", &snmp_root.udp_RcvbufErrors);
- arl_expect(arl_udp, "SndbufErrors", &snmp_root.udp_SndbufErrors);
- arl_expect(arl_udp, "InCsumErrors", &snmp_root.udp_InCsumErrors);
- arl_expect(arl_udp, "IgnoredMulti", &snmp_root.udp_IgnoredMulti);
-
- arl_udplite = arl_create("snmp/Udplite", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_udplite, "InDatagrams", &snmp_root.udplite_InDatagrams);
- arl_expect(arl_udplite, "NoPorts", &snmp_root.udplite_NoPorts);
- arl_expect(arl_udplite, "InErrors", &snmp_root.udplite_InErrors);
- arl_expect(arl_udplite, "OutDatagrams", &snmp_root.udplite_OutDatagrams);
- arl_expect(arl_udplite, "RcvbufErrors", &snmp_root.udplite_RcvbufErrors);
- arl_expect(arl_udplite, "SndbufErrors", &snmp_root.udplite_SndbufErrors);
- arl_expect(arl_udplite, "InCsumErrors", &snmp_root.udplite_InCsumErrors);
- arl_expect(arl_udplite, "IgnoredMulti", &snmp_root.udplite_IgnoredMulti);
-
- tcp_max_connections_var = rrdvar_custom_host_variable_create(localhost, "tcp_max_connections");
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp");
- ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
- size_t words, w;
-
- for(l = 0; l < lines ;l++) {
- char *key = procfile_lineword(ff, l, 0);
- uint32_t hash = simple_hash(key);
-
- if(unlikely(hash == hash_ip && strcmp(key, "Ip") == 0)) {
- size_t h = l++;
-
- if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) {
- error("Cannot read Ip line from /proc/net/snmp.");
- break;
- }
-
- words = procfile_linewords(ff, l);
- if(words < 3) {
- error("Cannot read /proc/net/snmp Ip line. Expected 3+ params, read %zu.", words);
- continue;
- }
-
- arl_begin(arl_ip);
- for(w = 1; w < words ; w++) {
- if (unlikely(arl_check(arl_ip, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0))
- break;
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_packets) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InReceives = NULL,
- *rd_OutRequests = NULL,
- *rd_ForwDatagrams = NULL,
- *rd_InDelivers = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "packets"
- , NULL
- , "packets"
- , NULL
- , "IPv4 Packets"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2450
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InReceives = rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutRequests = rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ForwDatagrams = rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InDelivers = rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_OutRequests, (collected_number)snmp_root.ip_OutRequests);
- rrddim_set_by_pointer(st, rd_InReceives, (collected_number)snmp_root.ip_InReceives);
- rrddim_set_by_pointer(st, rd_ForwDatagrams, (collected_number)snmp_root.ip_ForwDatagrams);
- rrddim_set_by_pointer(st, rd_InDelivers, (collected_number)snmp_root.ip_InDelivers);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_fragsout) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_FragOKs = NULL,
- *rd_FragFails = NULL,
- *rd_FragCreates = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "fragsout"
- , NULL
- , "fragments"
- , NULL
- , "IPv4 Fragments Sent"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 3020
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_FragOKs = rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_FragFails = rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_FragCreates = rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_FragOKs, (collected_number)snmp_root.ip_FragOKs);
- rrddim_set_by_pointer(st, rd_FragFails, (collected_number)snmp_root.ip_FragFails);
- rrddim_set_by_pointer(st, rd_FragCreates, (collected_number)snmp_root.ip_FragCreates);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_fragsin) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_ReasmOKs = NULL,
- *rd_ReasmFails = NULL,
- *rd_ReasmReqds = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "fragsin"
- , NULL
- , "fragments"
- , NULL
- , "IPv4 Fragments Reassembly"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 3030
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ReasmOKs = rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ReasmFails = rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ReasmReqds = rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ReasmOKs, (collected_number)snmp_root.ip_ReasmOKs);
- rrddim_set_by_pointer(st, rd_ReasmFails, (collected_number)snmp_root.ip_ReasmFails);
- rrddim_set_by_pointer(st, rd_ReasmReqds, (collected_number)snmp_root.ip_ReasmReqds);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_errors) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InDiscards = NULL,
- *rd_OutDiscards = NULL,
- *rd_InHdrErrors = NULL,
- *rd_OutNoRoutes = NULL,
- *rd_InAddrErrors = NULL,
- *rd_InUnknownProtos = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "errors"
- , NULL
- , "errors"
- , NULL
- , "IPv4 Errors"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2470
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_InDiscards = rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutDiscards = rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rd_InHdrErrors = rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutNoRoutes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rd_InAddrErrors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InUnknownProtos = rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InDiscards, (collected_number)snmp_root.ip_InDiscards);
- rrddim_set_by_pointer(st, rd_OutDiscards, (collected_number)snmp_root.ip_OutDiscards);
- rrddim_set_by_pointer(st, rd_InHdrErrors, (collected_number)snmp_root.ip_InHdrErrors);
- rrddim_set_by_pointer(st, rd_InAddrErrors, (collected_number)snmp_root.ip_InAddrErrors);
- rrddim_set_by_pointer(st, rd_InUnknownProtos, (collected_number)snmp_root.ip_InUnknownProtos);
- rrddim_set_by_pointer(st, rd_OutNoRoutes, (collected_number)snmp_root.ip_OutNoRoutes);
- rrdset_done(st);
- }
- }
- else if(unlikely(hash == hash_icmp && strcmp(key, "Icmp") == 0)) {
- size_t h = l++;
-
- if(strcmp(procfile_lineword(ff, l, 0), "Icmp") != 0) {
- error("Cannot read Icmp line from /proc/net/snmp.");
- break;
- }
-
- words = procfile_linewords(ff, l);
- if(words < 3) {
- error("Cannot read /proc/net/snmp Icmp line. Expected 3+ params, read %zu.", words);
- continue;
- }
-
- arl_begin(arl_icmp);
- for(w = 1; w < words ; w++) {
- if (unlikely(arl_check(arl_icmp, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0))
- break;
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_packets) {
- {
- static RRDSET *st_packets = NULL;
- static RRDDIM *rd_InMsgs = NULL,
- *rd_OutMsgs = NULL;
-
- if(unlikely(!st_packets)) {
- st_packets = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "icmp"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Packets"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2602
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InMsgs = rrddim_add(st_packets, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutMsgs = rrddim_add(st_packets, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_packets);
-
- rrddim_set_by_pointer(st_packets, rd_InMsgs, (collected_number)snmp_root.icmp_InMsgs);
- rrddim_set_by_pointer(st_packets, rd_OutMsgs, (collected_number)snmp_root.icmp_OutMsgs);
-
- rrdset_done(st_packets);
- }
-
- {
- static RRDSET *st_errors = NULL;
- static RRDDIM *rd_InErrors = NULL,
- *rd_OutErrors = NULL,
- *rd_InCsumErrors = NULL;
-
- if(unlikely(!st_errors)) {
- st_errors = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "icmp_errors"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Errors"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2603
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InErrors = rrddim_add(st_errors, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutErrors = rrddim_add(st_errors, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st_errors, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_errors);
-
- rrddim_set_by_pointer(st_errors, rd_InErrors, (collected_number)snmp_root.icmp_InErrors);
- rrddim_set_by_pointer(st_errors, rd_OutErrors, (collected_number)snmp_root.icmp_OutErrors);
- rrddim_set_by_pointer(st_errors, rd_InCsumErrors, (collected_number)snmp_root.icmp_InCsumErrors);
-
- rrdset_done(st_errors);
- }
- }
- }
- else if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) {
- size_t h = l++;
-
- if(strcmp(procfile_lineword(ff, l, 0), "IcmpMsg") != 0) {
- error("Cannot read IcmpMsg line from /proc/net/snmp.");
- break;
- }
-
- words = procfile_linewords(ff, l);
- if(words < 3) {
- error("Cannot read /proc/net/snmp IcmpMsg line. Expected 3+ params, read %zu.", words);
- continue;
- }
-
- arl_begin(arl_icmpmsg);
- for(w = 1; w < words ; w++) {
- if (unlikely(arl_check(arl_icmpmsg, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0))
- break;
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmpmsg) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InEchoReps = NULL,
- *rd_OutEchoReps = NULL,
- *rd_InDestUnreachs = NULL,
- *rd_OutDestUnreachs = NULL,
- *rd_InRedirects = NULL,
- *rd_OutRedirects = NULL,
- *rd_InEchos = NULL,
- *rd_OutEchos = NULL,
- *rd_InRouterAdvert = NULL,
- *rd_OutRouterAdvert = NULL,
- *rd_InRouterSelect = NULL,
- *rd_OutRouterSelect = NULL,
- *rd_InTimeExcds = NULL,
- *rd_OutTimeExcds = NULL,
- *rd_InParmProbs = NULL,
- *rd_OutParmProbs = NULL,
- *rd_InTimestamps = NULL,
- *rd_OutTimestamps = NULL,
- *rd_InTimestampReps = NULL,
- *rd_OutTimestampReps = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "icmpmsg"
- , NULL
- , "icmp"
- , NULL
- , "IPv4 ICMP Messages"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2604
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InEchoReps = rrddim_add(st, "InType0", "InEchoReps", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutEchoReps = rrddim_add(st, "OutType0", "OutEchoReps", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InDestUnreachs = rrddim_add(st, "InType3", "InDestUnreachs", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutDestUnreachs = rrddim_add(st, "OutType3", "OutDestUnreachs", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InRedirects = rrddim_add(st, "InType5", "InRedirects", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutRedirects = rrddim_add(st, "OutType5", "OutRedirects", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InEchos = rrddim_add(st, "InType8", "InEchos", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutEchos = rrddim_add(st, "OutType8", "OutEchos", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InRouterAdvert = rrddim_add(st, "InType9", "InRouterAdvert", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutRouterAdvert = rrddim_add(st, "OutType9", "OutRouterAdvert", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InRouterSelect = rrddim_add(st, "InType10", "InRouterSelect", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutRouterSelect = rrddim_add(st, "OutType10", "OutRouterSelect", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InTimeExcds = rrddim_add(st, "InType11", "InTimeExcds", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutTimeExcds = rrddim_add(st, "OutType11", "OutTimeExcds", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InParmProbs = rrddim_add(st, "InType12", "InParmProbs", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutParmProbs = rrddim_add(st, "OutType12", "OutParmProbs", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InTimestamps = rrddim_add(st, "InType13", "InTimestamps", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutTimestamps = rrddim_add(st, "OutType13", "OutTimestamps", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InTimestampReps = rrddim_add(st, "InType14", "InTimestampReps", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutTimestampReps = rrddim_add(st, "OutType14", "OutTimestampReps", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InEchoReps, (collected_number)snmp_root.icmpmsg_InEchoReps);
- rrddim_set_by_pointer(st, rd_OutEchoReps, (collected_number)snmp_root.icmpmsg_OutEchoReps);
- rrddim_set_by_pointer(st, rd_InDestUnreachs, (collected_number)snmp_root.icmpmsg_InDestUnreachs);
- rrddim_set_by_pointer(st, rd_OutDestUnreachs, (collected_number)snmp_root.icmpmsg_OutDestUnreachs);
- rrddim_set_by_pointer(st, rd_InRedirects, (collected_number)snmp_root.icmpmsg_InRedirects);
- rrddim_set_by_pointer(st, rd_OutRedirects, (collected_number)snmp_root.icmpmsg_OutRedirects);
- rrddim_set_by_pointer(st, rd_InEchos, (collected_number)snmp_root.icmpmsg_InEchos);
- rrddim_set_by_pointer(st, rd_OutEchos, (collected_number)snmp_root.icmpmsg_OutEchos);
- rrddim_set_by_pointer(st, rd_InRouterAdvert, (collected_number)snmp_root.icmpmsg_InRouterAdvert);
- rrddim_set_by_pointer(st, rd_OutRouterAdvert, (collected_number)snmp_root.icmpmsg_OutRouterAdvert);
- rrddim_set_by_pointer(st, rd_InRouterSelect, (collected_number)snmp_root.icmpmsg_InRouterSelect);
- rrddim_set_by_pointer(st, rd_OutRouterSelect, (collected_number)snmp_root.icmpmsg_OutRouterSelect);
- rrddim_set_by_pointer(st, rd_InTimeExcds, (collected_number)snmp_root.icmpmsg_InTimeExcds);
- rrddim_set_by_pointer(st, rd_OutTimeExcds, (collected_number)snmp_root.icmpmsg_OutTimeExcds);
- rrddim_set_by_pointer(st, rd_InParmProbs, (collected_number)snmp_root.icmpmsg_InParmProbs);
- rrddim_set_by_pointer(st, rd_OutParmProbs, (collected_number)snmp_root.icmpmsg_OutParmProbs);
- rrddim_set_by_pointer(st, rd_InTimestamps, (collected_number)snmp_root.icmpmsg_InTimestamps);
- rrddim_set_by_pointer(st, rd_OutTimestamps, (collected_number)snmp_root.icmpmsg_OutTimestamps);
- rrddim_set_by_pointer(st, rd_InTimestampReps, (collected_number)snmp_root.icmpmsg_InTimestampReps);
- rrddim_set_by_pointer(st, rd_OutTimestampReps, (collected_number)snmp_root.icmpmsg_OutTimestampReps);
-
- rrdset_done(st);
- }
- }
- else if(unlikely(hash == hash_tcp && strcmp(key, "Tcp") == 0)) {
- size_t h = l++;
-
- if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) {
- error("Cannot read Tcp line from /proc/net/snmp.");
- break;
- }
-
- words = procfile_linewords(ff, l);
- if(words < 3) {
- error("Cannot read /proc/net/snmp Tcp line. Expected 3+ params, read %zu.", words);
- continue;
- }
-
- arl_begin(arl_tcp);
- for(w = 1; w < words ; w++) {
- if (unlikely(arl_check(arl_tcp, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0))
- break;
- }
-
- // --------------------------------------------------------------------
-
- if(snmp_root.tcp_MaxConn != last_max_connections) {
- last_max_connections = snmp_root.tcp_MaxConn;
- rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, last_max_connections);
- }
-
- // --------------------------------------------------------------------
-
- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
- if(do_tcp_sockets) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_CurrEstab = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "tcpsock"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Connections"
- , "active connections"
- , "proc"
- , "net/snmp"
- , 2501
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_CurrEstab = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_CurrEstab, (collected_number)snmp_root.tcp_CurrEstab);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcp_packets) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InSegs = NULL,
- *rd_OutSegs = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "tcppackets"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Packets"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2510
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InSegs = rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutSegs = rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InSegs, (collected_number)snmp_root.tcp_InSegs);
- rrddim_set_by_pointer(st, rd_OutSegs, (collected_number)snmp_root.tcp_OutSegs);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcp_errors) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InErrs = NULL,
- *rd_InCsumErrors = NULL,
- *rd_RetransSegs = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "tcperrors"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Errors"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2525
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_InErrs = rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_RetransSegs = rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InErrs, (collected_number)snmp_root.tcp_InErrs);
- rrddim_set_by_pointer(st, rd_InCsumErrors, (collected_number)snmp_root.tcp_InCsumErrors);
- rrddim_set_by_pointer(st, rd_RetransSegs, (collected_number)snmp_root.tcp_RetransSegs);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcp_opens) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_ActiveOpens = NULL,
- *rd_PassiveOpens = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "tcpopens"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Opens"
- , "connections/s"
- , "proc"
- , "net/snmp"
- , 2502
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ActiveOpens = rrddim_add(st, "ActiveOpens", "active", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_PassiveOpens = rrddim_add(st, "PassiveOpens", "passive", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ActiveOpens, (collected_number)snmp_root.tcp_ActiveOpens);
- rrddim_set_by_pointer(st, rd_PassiveOpens, (collected_number)snmp_root.tcp_PassiveOpens);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_tcp_handshake) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_EstabResets = NULL,
- *rd_OutRsts = NULL,
- *rd_AttemptFails = NULL,
- *rd_TCPSynRetrans = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "tcphandshake"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Handshake Issues"
- , "events/s"
- , "proc"
- , "net/snmp"
- , 2530
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_EstabResets = rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutRsts = rrddim_add(st, "OutRsts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_AttemptFails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_TCPSynRetrans = rrddim_add(st, "TCPSynRetrans", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_EstabResets, (collected_number)snmp_root.tcp_EstabResets);
- rrddim_set_by_pointer(st, rd_OutRsts, (collected_number)snmp_root.tcp_OutRsts);
- rrddim_set_by_pointer(st, rd_AttemptFails, (collected_number)snmp_root.tcp_AttemptFails);
- rrddim_set_by_pointer(st, rd_TCPSynRetrans, tcpext_TCPSynRetrans);
- rrdset_done(st);
- }
- }
- else if(unlikely(hash == hash_udp && strcmp(key, "Udp") == 0)) {
- size_t h = l++;
-
- if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) {
- error("Cannot read Udp line from /proc/net/snmp.");
- break;
- }
-
- words = procfile_linewords(ff, l);
- if(words < 3) {
- error("Cannot read /proc/net/snmp Udp line. Expected 3+ params, read %zu.", words);
- continue;
- }
-
- arl_begin(arl_udp);
- for(w = 1; w < words ; w++) {
- if (unlikely(arl_check(arl_udp, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0))
- break;
- }
-
- // --------------------------------------------------------------------
-
- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
- if(do_udp_packets) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InDatagrams = NULL,
- *rd_OutDatagrams = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "udppackets"
- , NULL
- , "udp"
- , NULL
- , "IPv4 UDP Packets"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2602
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InDatagrams = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutDatagrams = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InDatagrams, (collected_number)snmp_root.udp_InDatagrams);
- rrddim_set_by_pointer(st, rd_OutDatagrams, (collected_number)snmp_root.udp_OutDatagrams);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_udp_errors) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_RcvbufErrors = NULL,
- *rd_SndbufErrors = NULL,
- *rd_InErrors = NULL,
- *rd_NoPorts = NULL,
- *rd_InCsumErrors = NULL,
- *rd_IgnoredMulti = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "udperrors"
- , NULL
- , "udp"
- , NULL
- , "IPv4 UDP Errors"
- , "events/s"
- , "proc"
- , "net/snmp"
- , 2701
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_IgnoredMulti = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InErrors, (collected_number)snmp_root.udp_InErrors);
- rrddim_set_by_pointer(st, rd_NoPorts, (collected_number)snmp_root.udp_NoPorts);
- rrddim_set_by_pointer(st, rd_RcvbufErrors, (collected_number)snmp_root.udp_RcvbufErrors);
- rrddim_set_by_pointer(st, rd_SndbufErrors, (collected_number)snmp_root.udp_SndbufErrors);
- rrddim_set_by_pointer(st, rd_InCsumErrors, (collected_number)snmp_root.udp_InCsumErrors);
- rrddim_set_by_pointer(st, rd_IgnoredMulti, (collected_number)snmp_root.udp_IgnoredMulti);
- rrdset_done(st);
- }
- }
- else if(unlikely(hash == hash_udplite && strcmp(key, "UdpLite") == 0)) {
- size_t h = l++;
-
- if(strcmp(procfile_lineword(ff, l, 0), "UdpLite") != 0) {
- error("Cannot read UdpLite line from /proc/net/snmp.");
- break;
- }
-
- words = procfile_linewords(ff, l);
- if(words < 3) {
- error("Cannot read /proc/net/snmp UdpLite line. Expected 3+ params, read %zu.", words);
- continue;
- }
-
- arl_begin(arl_udplite);
- for(w = 1; w < words ; w++) {
- if (unlikely(arl_check(arl_udplite, procfile_lineword(ff, h, w), procfile_lineword(ff, l, w)) != 0))
- break;
- }
-
- // --------------------------------------------------------------------
-
- if(do_udplite_packets) {
- {
- static RRDSET *st = NULL;
- static RRDDIM *rd_InDatagrams = NULL,
- *rd_OutDatagrams = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "udplite"
- , NULL
- , "udplite"
- , NULL
- , "IPv4 UDPLite Packets"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2603
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InDatagrams = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutDatagrams = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InDatagrams, (collected_number)snmp_root.udplite_InDatagrams);
- rrddim_set_by_pointer(st, rd_OutDatagrams, (collected_number)snmp_root.udplite_OutDatagrams);
- rrdset_done(st);
- }
-
- {
- static RRDSET *st = NULL;
- static RRDDIM *rd_RcvbufErrors = NULL,
- *rd_SndbufErrors = NULL,
- *rd_InErrors = NULL,
- *rd_NoPorts = NULL,
- *rd_InCsumErrors = NULL,
- *rd_IgnoredMulti = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP
- , "udplite_errors"
- , NULL
- , "udplite"
- , NULL
- , "IPv4 UDPLite Errors"
- , "packets/s"
- , "proc"
- , "net/snmp"
- , 2604
- , update_every
- , RRDSET_TYPE_LINE);
-
- rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_IgnoredMulti = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_NoPorts, (collected_number)snmp_root.udplite_NoPorts);
- rrddim_set_by_pointer(st, rd_InErrors, (collected_number)snmp_root.udplite_InErrors);
- rrddim_set_by_pointer(st, rd_InCsumErrors, (collected_number)snmp_root.udplite_InCsumErrors);
- rrddim_set_by_pointer(st, rd_RcvbufErrors, (collected_number)snmp_root.udplite_RcvbufErrors);
- rrddim_set_by_pointer(st, rd_SndbufErrors, (collected_number)snmp_root.udplite_SndbufErrors);
- rrddim_set_by_pointer(st, rd_IgnoredMulti, (collected_number)snmp_root.udplite_IgnoredMulti);
- rrdset_done(st);
- }
- }
- }
- }
-
- return 0;
-}
-
diff --git a/src/proc_net_snmp6.c b/src/proc_net_snmp6.c
deleted file mode 100644
index bd71b391a..000000000
--- a/src/proc_net_snmp6.c
+++ /dev/null
@@ -1,1265 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_NET_SNMP6 "ipv6"
-
-int do_proc_net_snmp6(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
-
- static int do_ip_packets = -1,
- do_ip_fragsout = -1,
- do_ip_fragsin = -1,
- do_ip_errors = -1,
- do_udplite_packets = -1,
- do_udplite_errors = -1,
- do_udp_packets = -1,
- do_udp_errors = -1,
- do_bandwidth = -1,
- do_mcast = -1,
- do_bcast = -1,
- do_mcast_p = -1,
- do_icmp = -1,
- do_icmp_redir = -1,
- do_icmp_errors = -1,
- do_icmp_echos = -1,
- do_icmp_groupmemb = -1,
- do_icmp_router = -1,
- do_icmp_neighbor = -1,
- do_icmp_mldv2 = -1,
- do_icmp_types = -1,
- do_ect = -1;
-
- static ARL_BASE *arl_base = NULL;
-
- static unsigned long long Ip6InReceives = 0ULL;
- static unsigned long long Ip6InHdrErrors = 0ULL;
- static unsigned long long Ip6InTooBigErrors = 0ULL;
- static unsigned long long Ip6InNoRoutes = 0ULL;
- static unsigned long long Ip6InAddrErrors = 0ULL;
- static unsigned long long Ip6InUnknownProtos = 0ULL;
- static unsigned long long Ip6InTruncatedPkts = 0ULL;
- static unsigned long long Ip6InDiscards = 0ULL;
- static unsigned long long Ip6InDelivers = 0ULL;
- static unsigned long long Ip6OutForwDatagrams = 0ULL;
- static unsigned long long Ip6OutRequests = 0ULL;
- static unsigned long long Ip6OutDiscards = 0ULL;
- static unsigned long long Ip6OutNoRoutes = 0ULL;
- static unsigned long long Ip6ReasmTimeout = 0ULL;
- static unsigned long long Ip6ReasmReqds = 0ULL;
- static unsigned long long Ip6ReasmOKs = 0ULL;
- static unsigned long long Ip6ReasmFails = 0ULL;
- static unsigned long long Ip6FragOKs = 0ULL;
- static unsigned long long Ip6FragFails = 0ULL;
- static unsigned long long Ip6FragCreates = 0ULL;
- static unsigned long long Ip6InMcastPkts = 0ULL;
- static unsigned long long Ip6OutMcastPkts = 0ULL;
- static unsigned long long Ip6InOctets = 0ULL;
- static unsigned long long Ip6OutOctets = 0ULL;
- static unsigned long long Ip6InMcastOctets = 0ULL;
- static unsigned long long Ip6OutMcastOctets = 0ULL;
- static unsigned long long Ip6InBcastOctets = 0ULL;
- static unsigned long long Ip6OutBcastOctets = 0ULL;
- static unsigned long long Ip6InNoECTPkts = 0ULL;
- static unsigned long long Ip6InECT1Pkts = 0ULL;
- static unsigned long long Ip6InECT0Pkts = 0ULL;
- static unsigned long long Ip6InCEPkts = 0ULL;
- static unsigned long long Icmp6InMsgs = 0ULL;
- static unsigned long long Icmp6InErrors = 0ULL;
- static unsigned long long Icmp6OutMsgs = 0ULL;
- static unsigned long long Icmp6OutErrors = 0ULL;
- static unsigned long long Icmp6InCsumErrors = 0ULL;
- static unsigned long long Icmp6InDestUnreachs = 0ULL;
- static unsigned long long Icmp6InPktTooBigs = 0ULL;
- static unsigned long long Icmp6InTimeExcds = 0ULL;
- static unsigned long long Icmp6InParmProblems = 0ULL;
- static unsigned long long Icmp6InEchos = 0ULL;
- static unsigned long long Icmp6InEchoReplies = 0ULL;
- static unsigned long long Icmp6InGroupMembQueries = 0ULL;
- static unsigned long long Icmp6InGroupMembResponses = 0ULL;
- static unsigned long long Icmp6InGroupMembReductions = 0ULL;
- static unsigned long long Icmp6InRouterSolicits = 0ULL;
- static unsigned long long Icmp6InRouterAdvertisements = 0ULL;
- static unsigned long long Icmp6InNeighborSolicits = 0ULL;
- static unsigned long long Icmp6InNeighborAdvertisements = 0ULL;
- static unsigned long long Icmp6InRedirects = 0ULL;
- static unsigned long long Icmp6InMLDv2Reports = 0ULL;
- static unsigned long long Icmp6OutDestUnreachs = 0ULL;
- static unsigned long long Icmp6OutPktTooBigs = 0ULL;
- static unsigned long long Icmp6OutTimeExcds = 0ULL;
- static unsigned long long Icmp6OutParmProblems = 0ULL;
- static unsigned long long Icmp6OutEchos = 0ULL;
- static unsigned long long Icmp6OutEchoReplies = 0ULL;
- static unsigned long long Icmp6OutGroupMembQueries = 0ULL;
- static unsigned long long Icmp6OutGroupMembResponses = 0ULL;
- static unsigned long long Icmp6OutGroupMembReductions = 0ULL;
- static unsigned long long Icmp6OutRouterSolicits = 0ULL;
- static unsigned long long Icmp6OutRouterAdvertisements = 0ULL;
- static unsigned long long Icmp6OutNeighborSolicits = 0ULL;
- static unsigned long long Icmp6OutNeighborAdvertisements = 0ULL;
- static unsigned long long Icmp6OutRedirects = 0ULL;
- static unsigned long long Icmp6OutMLDv2Reports = 0ULL;
- static unsigned long long Icmp6InType1 = 0ULL;
- static unsigned long long Icmp6InType128 = 0ULL;
- static unsigned long long Icmp6InType129 = 0ULL;
- static unsigned long long Icmp6InType136 = 0ULL;
- static unsigned long long Icmp6OutType1 = 0ULL;
- static unsigned long long Icmp6OutType128 = 0ULL;
- static unsigned long long Icmp6OutType129 = 0ULL;
- static unsigned long long Icmp6OutType133 = 0ULL;
- static unsigned long long Icmp6OutType135 = 0ULL;
- static unsigned long long Icmp6OutType143 = 0ULL;
- static unsigned long long Udp6InDatagrams = 0ULL;
- static unsigned long long Udp6NoPorts = 0ULL;
- static unsigned long long Udp6InErrors = 0ULL;
- static unsigned long long Udp6OutDatagrams = 0ULL;
- static unsigned long long Udp6RcvbufErrors = 0ULL;
- static unsigned long long Udp6SndbufErrors = 0ULL;
- static unsigned long long Udp6InCsumErrors = 0ULL;
- static unsigned long long Udp6IgnoredMulti = 0ULL;
- static unsigned long long UdpLite6InDatagrams = 0ULL;
- static unsigned long long UdpLite6NoPorts = 0ULL;
- static unsigned long long UdpLite6InErrors = 0ULL;
- static unsigned long long UdpLite6OutDatagrams = 0ULL;
- static unsigned long long UdpLite6RcvbufErrors = 0ULL;
- static unsigned long long UdpLite6SndbufErrors = 0ULL;
- static unsigned long long UdpLite6InCsumErrors = 0ULL;
-
- if(unlikely(!arl_base)) {
- do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_BOOLEAN_AUTO);
- do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO);
- do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO);
- do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_BOOLEAN_AUTO);
- do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_BOOLEAN_AUTO);
- do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_BOOLEAN_AUTO);
- do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_BOOLEAN_AUTO);
- do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_BOOLEAN_AUTO);
- do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_BOOLEAN_AUTO);
- do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_BOOLEAN_AUTO);
- do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO);
- do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_BOOLEAN_AUTO);
- do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_BOOLEAN_AUTO);
- do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_BOOLEAN_AUTO);
- do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_BOOLEAN_AUTO);
- do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_BOOLEAN_AUTO);
- do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_BOOLEAN_AUTO);
- do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_BOOLEAN_AUTO);
- do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_BOOLEAN_AUTO);
- do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_BOOLEAN_AUTO);
- do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_BOOLEAN_AUTO);
- do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_BOOLEAN_AUTO);
-
- arl_base = arl_create("snmp6", NULL, 60);
- arl_expect(arl_base, "Ip6InReceives", &Ip6InReceives);
- arl_expect(arl_base, "Ip6InHdrErrors", &Ip6InHdrErrors);
- arl_expect(arl_base, "Ip6InTooBigErrors", &Ip6InTooBigErrors);
- arl_expect(arl_base, "Ip6InNoRoutes", &Ip6InNoRoutes);
- arl_expect(arl_base, "Ip6InAddrErrors", &Ip6InAddrErrors);
- arl_expect(arl_base, "Ip6InUnknownProtos", &Ip6InUnknownProtos);
- arl_expect(arl_base, "Ip6InTruncatedPkts", &Ip6InTruncatedPkts);
- arl_expect(arl_base, "Ip6InDiscards", &Ip6InDiscards);
- arl_expect(arl_base, "Ip6InDelivers", &Ip6InDelivers);
- arl_expect(arl_base, "Ip6OutForwDatagrams", &Ip6OutForwDatagrams);
- arl_expect(arl_base, "Ip6OutRequests", &Ip6OutRequests);
- arl_expect(arl_base, "Ip6OutDiscards", &Ip6OutDiscards);
- arl_expect(arl_base, "Ip6OutNoRoutes", &Ip6OutNoRoutes);
- arl_expect(arl_base, "Ip6ReasmTimeout", &Ip6ReasmTimeout);
- arl_expect(arl_base, "Ip6ReasmReqds", &Ip6ReasmReqds);
- arl_expect(arl_base, "Ip6ReasmOKs", &Ip6ReasmOKs);
- arl_expect(arl_base, "Ip6ReasmFails", &Ip6ReasmFails);
- arl_expect(arl_base, "Ip6FragOKs", &Ip6FragOKs);
- arl_expect(arl_base, "Ip6FragFails", &Ip6FragFails);
- arl_expect(arl_base, "Ip6FragCreates", &Ip6FragCreates);
- arl_expect(arl_base, "Ip6InMcastPkts", &Ip6InMcastPkts);
- arl_expect(arl_base, "Ip6OutMcastPkts", &Ip6OutMcastPkts);
- arl_expect(arl_base, "Ip6InOctets", &Ip6InOctets);
- arl_expect(arl_base, "Ip6OutOctets", &Ip6OutOctets);
- arl_expect(arl_base, "Ip6InMcastOctets", &Ip6InMcastOctets);
- arl_expect(arl_base, "Ip6OutMcastOctets", &Ip6OutMcastOctets);
- arl_expect(arl_base, "Ip6InBcastOctets", &Ip6InBcastOctets);
- arl_expect(arl_base, "Ip6OutBcastOctets", &Ip6OutBcastOctets);
- arl_expect(arl_base, "Ip6InNoECTPkts", &Ip6InNoECTPkts);
- arl_expect(arl_base, "Ip6InECT1Pkts", &Ip6InECT1Pkts);
- arl_expect(arl_base, "Ip6InECT0Pkts", &Ip6InECT0Pkts);
- arl_expect(arl_base, "Ip6InCEPkts", &Ip6InCEPkts);
- arl_expect(arl_base, "Icmp6InMsgs", &Icmp6InMsgs);
- arl_expect(arl_base, "Icmp6InErrors", &Icmp6InErrors);
- arl_expect(arl_base, "Icmp6OutMsgs", &Icmp6OutMsgs);
- arl_expect(arl_base, "Icmp6OutErrors", &Icmp6OutErrors);
- arl_expect(arl_base, "Icmp6InCsumErrors", &Icmp6InCsumErrors);
- arl_expect(arl_base, "Icmp6InDestUnreachs", &Icmp6InDestUnreachs);
- arl_expect(arl_base, "Icmp6InPktTooBigs", &Icmp6InPktTooBigs);
- arl_expect(arl_base, "Icmp6InTimeExcds", &Icmp6InTimeExcds);
- arl_expect(arl_base, "Icmp6InParmProblems", &Icmp6InParmProblems);
- arl_expect(arl_base, "Icmp6InEchos", &Icmp6InEchos);
- arl_expect(arl_base, "Icmp6InEchoReplies", &Icmp6InEchoReplies);
- arl_expect(arl_base, "Icmp6InGroupMembQueries", &Icmp6InGroupMembQueries);
- arl_expect(arl_base, "Icmp6InGroupMembResponses", &Icmp6InGroupMembResponses);
- arl_expect(arl_base, "Icmp6InGroupMembReductions", &Icmp6InGroupMembReductions);
- arl_expect(arl_base, "Icmp6InRouterSolicits", &Icmp6InRouterSolicits);
- arl_expect(arl_base, "Icmp6InRouterAdvertisements", &Icmp6InRouterAdvertisements);
- arl_expect(arl_base, "Icmp6InNeighborSolicits", &Icmp6InNeighborSolicits);
- arl_expect(arl_base, "Icmp6InNeighborAdvertisements", &Icmp6InNeighborAdvertisements);
- arl_expect(arl_base, "Icmp6InRedirects", &Icmp6InRedirects);
- arl_expect(arl_base, "Icmp6InMLDv2Reports", &Icmp6InMLDv2Reports);
- arl_expect(arl_base, "Icmp6OutDestUnreachs", &Icmp6OutDestUnreachs);
- arl_expect(arl_base, "Icmp6OutPktTooBigs", &Icmp6OutPktTooBigs);
- arl_expect(arl_base, "Icmp6OutTimeExcds", &Icmp6OutTimeExcds);
- arl_expect(arl_base, "Icmp6OutParmProblems", &Icmp6OutParmProblems);
- arl_expect(arl_base, "Icmp6OutEchos", &Icmp6OutEchos);
- arl_expect(arl_base, "Icmp6OutEchoReplies", &Icmp6OutEchoReplies);
- arl_expect(arl_base, "Icmp6OutGroupMembQueries", &Icmp6OutGroupMembQueries);
- arl_expect(arl_base, "Icmp6OutGroupMembResponses", &Icmp6OutGroupMembResponses);
- arl_expect(arl_base, "Icmp6OutGroupMembReductions", &Icmp6OutGroupMembReductions);
- arl_expect(arl_base, "Icmp6OutRouterSolicits", &Icmp6OutRouterSolicits);
- arl_expect(arl_base, "Icmp6OutRouterAdvertisements", &Icmp6OutRouterAdvertisements);
- arl_expect(arl_base, "Icmp6OutNeighborSolicits", &Icmp6OutNeighborSolicits);
- arl_expect(arl_base, "Icmp6OutNeighborAdvertisements", &Icmp6OutNeighborAdvertisements);
- arl_expect(arl_base, "Icmp6OutRedirects", &Icmp6OutRedirects);
- arl_expect(arl_base, "Icmp6OutMLDv2Reports", &Icmp6OutMLDv2Reports);
- arl_expect(arl_base, "Icmp6InType1", &Icmp6InType1);
- arl_expect(arl_base, "Icmp6InType128", &Icmp6InType128);
- arl_expect(arl_base, "Icmp6InType129", &Icmp6InType129);
- arl_expect(arl_base, "Icmp6InType136", &Icmp6InType136);
- arl_expect(arl_base, "Icmp6OutType1", &Icmp6OutType1);
- arl_expect(arl_base, "Icmp6OutType128", &Icmp6OutType128);
- arl_expect(arl_base, "Icmp6OutType129", &Icmp6OutType129);
- arl_expect(arl_base, "Icmp6OutType133", &Icmp6OutType133);
- arl_expect(arl_base, "Icmp6OutType135", &Icmp6OutType135);
- arl_expect(arl_base, "Icmp6OutType143", &Icmp6OutType143);
- arl_expect(arl_base, "Udp6InDatagrams", &Udp6InDatagrams);
- arl_expect(arl_base, "Udp6NoPorts", &Udp6NoPorts);
- arl_expect(arl_base, "Udp6InErrors", &Udp6InErrors);
- arl_expect(arl_base, "Udp6OutDatagrams", &Udp6OutDatagrams);
- arl_expect(arl_base, "Udp6RcvbufErrors", &Udp6RcvbufErrors);
- arl_expect(arl_base, "Udp6SndbufErrors", &Udp6SndbufErrors);
- arl_expect(arl_base, "Udp6InCsumErrors", &Udp6InCsumErrors);
- arl_expect(arl_base, "Udp6IgnoredMulti", &Udp6IgnoredMulti);
- arl_expect(arl_base, "UdpLite6InDatagrams", &UdpLite6InDatagrams);
- arl_expect(arl_base, "UdpLite6NoPorts", &UdpLite6NoPorts);
- arl_expect(arl_base, "UdpLite6InErrors", &UdpLite6InErrors);
- arl_expect(arl_base, "UdpLite6OutDatagrams", &UdpLite6OutDatagrams);
- arl_expect(arl_base, "UdpLite6RcvbufErrors", &UdpLite6RcvbufErrors);
- arl_expect(arl_base, "UdpLite6SndbufErrors", &UdpLite6SndbufErrors);
- arl_expect(arl_base, "UdpLite6InCsumErrors", &UdpLite6InCsumErrors);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp6");
- ff = procfile_open(config_get("plugin:proc:/proc/net/snmp6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff))
- return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- arl_begin(arl_base);
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 2)) {
- if(unlikely(words)) error("Cannot read /proc/net/snmp6 line %zu. Expected 2 params, read %zu.", l, words);
- continue;
- }
-
- if(unlikely(arl_check(arl_base,
- procfile_lineword(ff, l, 0),
- procfile_lineword(ff, l, 1)))) break;
- }
-
- // --------------------------------------------------------------------
-
- if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (Ip6InOctets || Ip6OutOctets))) {
- do_bandwidth = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL,
- *rd_sent = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "ipv6"
- , NULL
- , "network"
- , NULL
- , "IPv6 Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/snmp6"
- , 502
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_received = rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_received, Ip6InOctets);
- rrddim_set_by_pointer(st, rd_sent, Ip6OutOctets);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_packets == CONFIG_BOOLEAN_YES || (do_ip_packets == CONFIG_BOOLEAN_AUTO && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) {
- do_ip_packets = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL,
- *rd_sent = NULL,
- *rd_forwarded = NULL,
- *rd_delivers = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "packets"
- , NULL
- , "packets"
- , NULL
- , "IPv6 Packets"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 3000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_forwarded = rrddim_add(st, "OutForwDatagrams", "forwarded", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_delivers = rrddim_add(st, "InDelivers", "delivers", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_received, Ip6InReceives);
- rrddim_set_by_pointer(st, rd_sent, Ip6OutRequests);
- rrddim_set_by_pointer(st, rd_forwarded, Ip6OutForwDatagrams);
- rrddim_set_by_pointer(st, rd_delivers, Ip6InDelivers);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_fragsout == CONFIG_BOOLEAN_YES || (do_ip_fragsout == CONFIG_BOOLEAN_AUTO && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) {
- do_ip_fragsout = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_ok = NULL,
- *rd_failed = NULL,
- *rd_all = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "fragsout"
- , NULL
- , "fragments6"
- , NULL
- , "IPv6 Fragments Sent"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 3011
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ok = rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_all = rrddim_add(st, "FragCreates", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ok, Ip6FragOKs);
- rrddim_set_by_pointer(st, rd_failed, Ip6FragFails);
- rrddim_set_by_pointer(st, rd_all, Ip6FragCreates);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_fragsin == CONFIG_BOOLEAN_YES || (do_ip_fragsin == CONFIG_BOOLEAN_AUTO
- && (
- Ip6ReasmOKs
- || Ip6ReasmFails
- || Ip6ReasmTimeout
- || Ip6ReasmReqds
- ))) {
- do_ip_fragsin = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_ok = NULL,
- *rd_failed = NULL,
- *rd_timeout = NULL,
- *rd_all = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "fragsin"
- , NULL
- , "fragments6"
- , NULL
- , "IPv6 Fragments Reassembly"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 3012
- , update_every
- , RRDSET_TYPE_LINE);
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_ok = rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_failed = rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_timeout = rrddim_add(st, "ReasmTimeout", "timeout", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_all = rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_ok, Ip6ReasmOKs);
- rrddim_set_by_pointer(st, rd_failed, Ip6ReasmFails);
- rrddim_set_by_pointer(st, rd_timeout, Ip6ReasmTimeout);
- rrddim_set_by_pointer(st, rd_all, Ip6ReasmReqds);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ip_errors == CONFIG_BOOLEAN_YES || (do_ip_errors == CONFIG_BOOLEAN_AUTO
- && (
- Ip6InDiscards
- || Ip6OutDiscards
- || Ip6InHdrErrors
- || Ip6InAddrErrors
- || Ip6InUnknownProtos
- || Ip6InTooBigErrors
- || Ip6InTruncatedPkts
- || Ip6InNoRoutes
- ))) {
- do_ip_errors = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InDiscards = NULL,
- *rd_OutDiscards = NULL,
- *rd_InHdrErrors = NULL,
- *rd_InAddrErrors = NULL,
- *rd_InUnknownProtos = NULL,
- *rd_InTooBigErrors = NULL,
- *rd_InTruncatedPkts = NULL,
- *rd_InNoRoutes = NULL,
- *rd_OutNoRoutes = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "errors"
- , NULL
- , "errors"
- , NULL
- , "IPv6 Errors"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 3002
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_InDiscards = rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutDiscards = rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InHdrErrors = rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InAddrErrors = rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InUnknownProtos = rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InTooBigErrors = rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InTruncatedPkts = rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InNoRoutes = rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutNoRoutes = rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InDiscards, Ip6InDiscards);
- rrddim_set_by_pointer(st, rd_OutDiscards, Ip6OutDiscards);
- rrddim_set_by_pointer(st, rd_InHdrErrors, Ip6InHdrErrors);
- rrddim_set_by_pointer(st, rd_InAddrErrors, Ip6InAddrErrors);
- rrddim_set_by_pointer(st, rd_InUnknownProtos, Ip6InUnknownProtos);
- rrddim_set_by_pointer(st, rd_InTooBigErrors, Ip6InTooBigErrors);
- rrddim_set_by_pointer(st, rd_InTruncatedPkts, Ip6InTruncatedPkts);
- rrddim_set_by_pointer(st, rd_InNoRoutes, Ip6InNoRoutes);
- rrddim_set_by_pointer(st, rd_OutNoRoutes, Ip6OutNoRoutes);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_udp_packets == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && (Udp6InDatagrams || Udp6OutDatagrams))) {
- do_udp_packets = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL,
- *rd_sent = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "udppackets"
- , NULL
- , "udp6"
- , NULL
- , "IPv6 UDP Packets"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 3601
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_received, Udp6InDatagrams);
- rrddim_set_by_pointer(st, rd_sent, Udp6OutDatagrams);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_udp_errors == CONFIG_BOOLEAN_YES || (do_udp_errors == CONFIG_BOOLEAN_AUTO
- && (
- Udp6InErrors
- || Udp6NoPorts
- || Udp6RcvbufErrors
- || Udp6SndbufErrors
- || Udp6InCsumErrors
- || Udp6IgnoredMulti
- ))) {
- do_udp_errors = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_RcvbufErrors = NULL,
- *rd_SndbufErrors = NULL,
- *rd_InErrors = NULL,
- *rd_NoPorts = NULL,
- *rd_InCsumErrors = NULL,
- *rd_IgnoredMulti = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "udperrors"
- , NULL
- , "udp6"
- , NULL
- , "IPv6 UDP Errors"
- , "events/s"
- , "proc"
- , "net/snmp6"
- , 3701
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_IgnoredMulti = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_RcvbufErrors, Udp6RcvbufErrors);
- rrddim_set_by_pointer(st, rd_SndbufErrors, Udp6SndbufErrors);
- rrddim_set_by_pointer(st, rd_InErrors, Udp6InErrors);
- rrddim_set_by_pointer(st, rd_NoPorts, Udp6NoPorts);
- rrddim_set_by_pointer(st, rd_InCsumErrors, Udp6InCsumErrors);
- rrddim_set_by_pointer(st, rd_IgnoredMulti, Udp6IgnoredMulti);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_udplite_packets == CONFIG_BOOLEAN_YES || (do_udplite_packets == CONFIG_BOOLEAN_AUTO && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) {
- do_udplite_packets = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_received = NULL,
- *rd_sent = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "udplitepackets"
- , NULL
- , "udplite6"
- , NULL
- , "IPv6 UDPlite Packets"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 3602
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_received = rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_sent = rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_received, UdpLite6InDatagrams);
- rrddim_set_by_pointer(st, rd_sent, UdpLite6OutDatagrams);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_udplite_errors == CONFIG_BOOLEAN_YES || (do_udplite_errors == CONFIG_BOOLEAN_AUTO
- && (
- UdpLite6InErrors
- || UdpLite6NoPorts
- || UdpLite6RcvbufErrors
- || UdpLite6SndbufErrors
- || Udp6InCsumErrors
- || UdpLite6InCsumErrors
- ))) {
- do_udplite_errors = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_RcvbufErrors = NULL,
- *rd_SndbufErrors = NULL,
- *rd_InErrors = NULL,
- *rd_NoPorts = NULL,
- *rd_InCsumErrors = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "udpliteerrors"
- , NULL
- , "udplite6"
- , NULL
- , "IPv6 UDP Lite Errors"
- , "events/s"
- , "proc"
- , "net/snmp6"
- , 3701
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_RcvbufErrors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_SndbufErrors = rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_NoPorts = rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InErrors, UdpLite6InErrors);
- rrddim_set_by_pointer(st, rd_NoPorts, UdpLite6NoPorts);
- rrddim_set_by_pointer(st, rd_RcvbufErrors, UdpLite6RcvbufErrors);
- rrddim_set_by_pointer(st, rd_SndbufErrors, UdpLite6SndbufErrors);
- rrddim_set_by_pointer(st, rd_InCsumErrors, UdpLite6InCsumErrors);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (Ip6OutMcastOctets || Ip6InMcastOctets))) {
- do_mcast = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_Ip6InMcastOctets = NULL,
- *rd_Ip6OutMcastOctets = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "mcast"
- , NULL
- , "multicast6"
- , NULL
- , "IPv6 Multicast Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/snmp6"
- , 9000
- , update_every
- , RRDSET_TYPE_AREA
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_Ip6InMcastOctets = rrddim_add(st, "InMcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_Ip6OutMcastOctets = rrddim_add(st, "OutMcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_Ip6InMcastOctets, Ip6InMcastOctets);
- rrddim_set_by_pointer(st, rd_Ip6OutMcastOctets, Ip6OutMcastOctets);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (Ip6OutBcastOctets || Ip6InBcastOctets))) {
- do_bcast = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_Ip6InBcastOctets = NULL,
- *rd_Ip6OutBcastOctets = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "bcast"
- , NULL
- , "broadcast6"
- , NULL
- , "IPv6 Broadcast Bandwidth"
- , "kilobits/s"
- , "proc"
- , "net/snmp6"
- , 8000
- , update_every
- , RRDSET_TYPE_AREA
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_Ip6InBcastOctets = rrddim_add(st, "InBcastOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- rd_Ip6OutBcastOctets = rrddim_add(st, "OutBcastOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_Ip6InBcastOctets, Ip6InBcastOctets);
- rrddim_set_by_pointer(st, rd_Ip6OutBcastOctets, Ip6OutBcastOctets);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (Ip6OutMcastPkts || Ip6InMcastPkts))) {
- do_mcast_p = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_Ip6InMcastPkts = NULL,
- *rd_Ip6OutMcastPkts = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "mcastpkts"
- , NULL
- , "multicast6"
- , NULL
- , "IPv6 Multicast Packets"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 9500
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_Ip6InMcastPkts = rrddim_add(st, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_Ip6OutMcastPkts = rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_Ip6InMcastPkts, Ip6InMcastPkts);
- rrddim_set_by_pointer(st, rd_Ip6OutMcastPkts, Ip6OutMcastPkts);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp == CONFIG_BOOLEAN_YES || (do_icmp == CONFIG_BOOLEAN_AUTO && (Icmp6InMsgs || Icmp6OutMsgs))) {
- do_icmp = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_Icmp6InMsgs = NULL,
- *rd_Icmp6OutMsgs = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmp"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP Messages"
- , "messages/s"
- , "proc"
- , "net/snmp6"
- , 10000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_Icmp6InMsgs = rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_Icmp6OutMsgs = rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_Icmp6InMsgs, Icmp6InMsgs);
- rrddim_set_by_pointer(st, rd_Icmp6OutMsgs, Icmp6OutMsgs);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_redir == CONFIG_BOOLEAN_YES || (do_icmp_redir == CONFIG_BOOLEAN_AUTO && (Icmp6InRedirects || Icmp6OutRedirects))) {
- do_icmp_redir = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_Icmp6InRedirects = NULL,
- *rd_Icmp6OutRedirects = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmpredir"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP Redirects"
- , "redirects/s"
- , "proc"
- , "net/snmp6"
- , 10050
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_Icmp6InRedirects = rrddim_add(st, "InRedirects", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_Icmp6OutRedirects = rrddim_add(st, "OutRedirects", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_Icmp6InRedirects, Icmp6InRedirects);
- rrddim_set_by_pointer(st, rd_Icmp6OutRedirects, Icmp6OutRedirects);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_errors == CONFIG_BOOLEAN_YES || (do_icmp_errors == CONFIG_BOOLEAN_AUTO
- && (
- Icmp6InErrors
- || Icmp6OutErrors
- || Icmp6InCsumErrors
- || Icmp6InDestUnreachs
- || Icmp6InPktTooBigs
- || Icmp6InTimeExcds
- || Icmp6InParmProblems
- || Icmp6OutDestUnreachs
- || Icmp6OutPktTooBigs
- || Icmp6OutTimeExcds
- || Icmp6OutParmProblems
- ))) {
- do_icmp_errors = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InErrors = NULL,
- *rd_OutErrors = NULL,
- *rd_InCsumErrors = NULL,
- *rd_InDestUnreachs = NULL,
- *rd_InPktTooBigs = NULL,
- *rd_InTimeExcds = NULL,
- *rd_InParmProblems = NULL,
- *rd_OutDestUnreachs = NULL,
- *rd_OutPktTooBigs = NULL,
- *rd_OutTimeExcds = NULL,
- *rd_OutParmProblems = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmperrors"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP Errors"
- , "errors/s"
- , "proc"
- , "net/snmp6"
- , 10100
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InErrors = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutErrors = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCsumErrors = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InDestUnreachs = rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InPktTooBigs = rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InTimeExcds = rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InParmProblems = rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutDestUnreachs = rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutPktTooBigs = rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutTimeExcds = rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutParmProblems = rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InErrors, Icmp6InErrors);
- rrddim_set_by_pointer(st, rd_OutErrors, Icmp6OutErrors);
- rrddim_set_by_pointer(st, rd_InCsumErrors, Icmp6InCsumErrors);
- rrddim_set_by_pointer(st, rd_InDestUnreachs, Icmp6InDestUnreachs);
- rrddim_set_by_pointer(st, rd_InPktTooBigs, Icmp6InPktTooBigs);
- rrddim_set_by_pointer(st, rd_InTimeExcds, Icmp6InTimeExcds);
- rrddim_set_by_pointer(st, rd_InParmProblems, Icmp6InParmProblems);
- rrddim_set_by_pointer(st, rd_OutDestUnreachs, Icmp6OutDestUnreachs);
- rrddim_set_by_pointer(st, rd_OutPktTooBigs, Icmp6OutPktTooBigs);
- rrddim_set_by_pointer(st, rd_OutTimeExcds, Icmp6OutTimeExcds);
- rrddim_set_by_pointer(st, rd_OutParmProblems, Icmp6OutParmProblems);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_echos == CONFIG_BOOLEAN_YES || (do_icmp_echos == CONFIG_BOOLEAN_AUTO
- && (
- Icmp6InEchos
- || Icmp6OutEchos
- || Icmp6InEchoReplies
- || Icmp6OutEchoReplies
- ))) {
- do_icmp_echos = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InEchos = NULL,
- *rd_OutEchos = NULL,
- *rd_InEchoReplies = NULL,
- *rd_OutEchoReplies = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmpechos"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP Echo"
- , "messages/s"
- , "proc"
- , "net/snmp6"
- , 10200
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InEchos = rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutEchos = rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InEchoReplies = rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutEchoReplies = rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InEchos, Icmp6InEchos);
- rrddim_set_by_pointer(st, rd_OutEchos, Icmp6OutEchos);
- rrddim_set_by_pointer(st, rd_InEchoReplies, Icmp6InEchoReplies);
- rrddim_set_by_pointer(st, rd_OutEchoReplies, Icmp6OutEchoReplies);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_groupmemb == CONFIG_BOOLEAN_YES || (do_icmp_groupmemb == CONFIG_BOOLEAN_AUTO
- && (
- Icmp6InGroupMembQueries
- || Icmp6OutGroupMembQueries
- || Icmp6InGroupMembResponses
- || Icmp6OutGroupMembResponses
- || Icmp6InGroupMembReductions
- || Icmp6OutGroupMembReductions
- ))) {
- do_icmp_groupmemb = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InQueries = NULL,
- *rd_OutQueries = NULL,
- *rd_InResponses = NULL,
- *rd_OutResponses = NULL,
- *rd_InReductions = NULL,
- *rd_OutReductions = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "groupmemb"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP Group Membership"
- , "messages/s"
- , "proc"
- , "net/snmp6"
- , 10300
- , update_every
- , RRDSET_TYPE_LINE);
-
- rd_InQueries = rrddim_add(st, "InQueries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutQueries = rrddim_add(st, "OutQueries", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InResponses = rrddim_add(st, "InResponses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutResponses = rrddim_add(st, "OutResponses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InReductions = rrddim_add(st, "InReductions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutReductions = rrddim_add(st, "OutReductions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InQueries, Icmp6InGroupMembQueries);
- rrddim_set_by_pointer(st, rd_OutQueries, Icmp6OutGroupMembQueries);
- rrddim_set_by_pointer(st, rd_InResponses, Icmp6InGroupMembResponses);
- rrddim_set_by_pointer(st, rd_OutResponses, Icmp6OutGroupMembResponses);
- rrddim_set_by_pointer(st, rd_InReductions, Icmp6InGroupMembReductions);
- rrddim_set_by_pointer(st, rd_OutReductions, Icmp6OutGroupMembReductions);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_router == CONFIG_BOOLEAN_YES || (do_icmp_router == CONFIG_BOOLEAN_AUTO
- && (
- Icmp6InRouterSolicits
- || Icmp6OutRouterSolicits
- || Icmp6InRouterAdvertisements
- || Icmp6OutRouterAdvertisements
- ))) {
- do_icmp_router = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InSolicits = NULL,
- *rd_OutSolicits = NULL,
- *rd_InAdvertisements = NULL,
- *rd_OutAdvertisements = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmprouter"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 Router Messages"
- , "messages/s"
- , "proc"
- , "net/snmp6"
- , 10400
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InSolicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutSolicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InAdvertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutAdvertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InSolicits, Icmp6InRouterSolicits);
- rrddim_set_by_pointer(st, rd_OutSolicits, Icmp6OutRouterSolicits);
- rrddim_set_by_pointer(st, rd_InAdvertisements, Icmp6InRouterAdvertisements);
- rrddim_set_by_pointer(st, rd_OutAdvertisements, Icmp6OutRouterAdvertisements);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_neighbor == CONFIG_BOOLEAN_YES || (do_icmp_neighbor == CONFIG_BOOLEAN_AUTO
- && (
- Icmp6InNeighborSolicits
- || Icmp6OutNeighborSolicits
- || Icmp6InNeighborAdvertisements
- || Icmp6OutNeighborAdvertisements
- ))) {
- do_icmp_neighbor = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InSolicits = NULL,
- *rd_OutSolicits = NULL,
- *rd_InAdvertisements = NULL,
- *rd_OutAdvertisements = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmpneighbor"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 Neighbor Messages"
- , "messages/s"
- , "proc"
- , "net/snmp6"
- , 10500
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InSolicits = rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutSolicits = rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InAdvertisements = rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutAdvertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InSolicits, Icmp6InNeighborSolicits);
- rrddim_set_by_pointer(st, rd_OutSolicits, Icmp6OutNeighborSolicits);
- rrddim_set_by_pointer(st, rd_InAdvertisements, Icmp6InNeighborAdvertisements);
- rrddim_set_by_pointer(st, rd_OutAdvertisements, Icmp6OutNeighborAdvertisements);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_mldv2 == CONFIG_BOOLEAN_YES || (do_icmp_mldv2 == CONFIG_BOOLEAN_AUTO && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) {
- do_icmp_mldv2 = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InMLDv2Reports = NULL,
- *rd_OutMLDv2Reports = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmpmldv2"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP MLDv2 Reports"
- , "reports/s"
- , "proc"
- , "net/snmp6"
- , 10600
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InMLDv2Reports = rrddim_add(st, "InMLDv2Reports", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutMLDv2Reports = rrddim_add(st, "OutMLDv2Reports", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InMLDv2Reports, Icmp6InMLDv2Reports);
- rrddim_set_by_pointer(st, rd_OutMLDv2Reports, Icmp6OutMLDv2Reports);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_icmp_types == CONFIG_BOOLEAN_YES || (do_icmp_types == CONFIG_BOOLEAN_AUTO
- && (
- Icmp6InType1
- || Icmp6InType128
- || Icmp6InType129
- || Icmp6InType136
- || Icmp6OutType1
- || Icmp6OutType128
- || Icmp6OutType129
- || Icmp6OutType133
- || Icmp6OutType135
- || Icmp6OutType143
- ))) {
- do_icmp_types = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InType1 = NULL,
- *rd_InType128 = NULL,
- *rd_InType129 = NULL,
- *rd_InType136 = NULL,
- *rd_OutType1 = NULL,
- *rd_OutType128 = NULL,
- *rd_OutType129 = NULL,
- *rd_OutType133 = NULL,
- *rd_OutType135 = NULL,
- *rd_OutType143 = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "icmptypes"
- , NULL
- , "icmp6"
- , NULL
- , "IPv6 ICMP Types"
- , "messages/s"
- , "proc"
- , "net/snmp6"
- , 10700
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InType1 = rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InType128 = rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InType129 = rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InType136 = rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutType1 = rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutType128 = rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutType129 = rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutType133 = rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutType135 = rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_OutType143 = rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InType1, Icmp6InType1);
- rrddim_set_by_pointer(st, rd_InType128, Icmp6InType128);
- rrddim_set_by_pointer(st, rd_InType129, Icmp6InType129);
- rrddim_set_by_pointer(st, rd_InType136, Icmp6InType136);
- rrddim_set_by_pointer(st, rd_OutType1, Icmp6OutType1);
- rrddim_set_by_pointer(st, rd_OutType128, Icmp6OutType128);
- rrddim_set_by_pointer(st, rd_OutType129, Icmp6OutType129);
- rrddim_set_by_pointer(st, rd_OutType133, Icmp6OutType133);
- rrddim_set_by_pointer(st, rd_OutType135, Icmp6OutType135);
- rrddim_set_by_pointer(st, rd_OutType143, Icmp6OutType143);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ect == CONFIG_BOOLEAN_YES || (do_ect == CONFIG_BOOLEAN_AUTO
- && (
- Ip6InNoECTPkts
- || Ip6InECT1Pkts
- || Ip6InECT0Pkts
- || Ip6InCEPkts
- ))) {
- do_ect = CONFIG_BOOLEAN_YES;
- static RRDSET *st = NULL;
- static RRDDIM *rd_InNoECTPkts = NULL,
- *rd_InECT1Pkts = NULL,
- *rd_InECT0Pkts = NULL,
- *rd_InCEPkts = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_SNMP6
- , "ect"
- , NULL
- , "packets"
- , NULL
- , "IPv6 ECT Packets"
- , "packets/s"
- , "proc"
- , "net/snmp6"
- , 10800
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_InNoECTPkts = rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InECT1Pkts = rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InECT0Pkts = rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_InCEPkts = rrddim_add(st, "InCEPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_InNoECTPkts, Ip6InNoECTPkts);
- rrddim_set_by_pointer(st, rd_InECT1Pkts, Ip6InECT1Pkts);
- rrddim_set_by_pointer(st, rd_InECT0Pkts, Ip6InECT0Pkts);
- rrddim_set_by_pointer(st, rd_InCEPkts, Ip6InCEPkts);
- rrdset_done(st);
- }
-
- return 0;
-}
-
diff --git a/src/proc_net_sockstat.c b/src/proc_net_sockstat.c
deleted file mode 100644
index db3070660..000000000
--- a/src/proc_net_sockstat.c
+++ /dev/null
@@ -1,514 +0,0 @@
-#include "common.h"
-
-static struct proc_net_sockstat {
- kernel_uint_t sockets_used;
-
- kernel_uint_t tcp_inuse;
- kernel_uint_t tcp_orphan;
- kernel_uint_t tcp_tw;
- kernel_uint_t tcp_alloc;
- kernel_uint_t tcp_mem;
-
- kernel_uint_t udp_inuse;
- kernel_uint_t udp_mem;
-
- kernel_uint_t udplite_inuse;
-
- kernel_uint_t raw_inuse;
-
- kernel_uint_t frag_inuse;
- kernel_uint_t frag_memory;
-} sockstat_root = { 0 };
-
-
-static int read_tcp_mem(void) {
- static char *filename = NULL;
- static RRDVAR *tcp_mem_low_threshold = NULL,
- *tcp_mem_pressure_threshold = NULL,
- *tcp_mem_high_threshold = NULL;
-
- if(unlikely(!tcp_mem_low_threshold)) {
- tcp_mem_low_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_low");
- tcp_mem_pressure_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_pressure");
- tcp_mem_high_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_high");
- }
-
- if(unlikely(!filename)) {
- char buffer[FILENAME_MAX + 1];
- snprintfz(buffer, FILENAME_MAX, "%s/proc/sys/net/ipv4/tcp_mem", netdata_configured_host_prefix);
- filename = strdupz(buffer);
- }
-
- char buffer[200 + 1], *start, *end;
- if(read_file(filename, buffer, 200) != 0) return 1;
- buffer[200] = '\0';
-
- unsigned long long low = 0, pressure = 0, high = 0;
-
- start = buffer;
- low = strtoull(start, &end, 10);
-
- start = end;
- pressure = strtoull(start, &end, 10);
-
- start = end;
- high = strtoull(start, &end, 10);
-
- // fprintf(stderr, "TCP MEM low = %llu, pressure = %llu, high = %llu\n", low, pressure, high);
-
- rrdvar_custom_host_variable_set(localhost, tcp_mem_low_threshold, low * sysconf(_SC_PAGESIZE) / 1024);
- rrdvar_custom_host_variable_set(localhost, tcp_mem_pressure_threshold, pressure * sysconf(_SC_PAGESIZE) / 1024);
- rrdvar_custom_host_variable_set(localhost, tcp_mem_high_threshold, high * sysconf(_SC_PAGESIZE) / 1024);
-
- return 0;
-}
-
-static kernel_uint_t read_tcp_max_orphans(void) {
- static char *filename = NULL;
- static RRDVAR *tcp_max_orphans_var = NULL;
-
- if(unlikely(!filename)) {
- char buffer[FILENAME_MAX + 1];
- snprintfz(buffer, FILENAME_MAX, "%s/proc/sys/net/ipv4/tcp_max_orphans", netdata_configured_host_prefix);
- filename = strdupz(buffer);
- }
-
- unsigned long long tcp_max_orphans = 0;
- if(read_single_number_file(filename, &tcp_max_orphans) == 0) {
-
- if(unlikely(!tcp_max_orphans_var))
- tcp_max_orphans_var = rrdvar_custom_host_variable_create(localhost, "tcp_max_orphans");
-
- rrdvar_custom_host_variable_set(localhost, tcp_max_orphans_var, tcp_max_orphans);
- return tcp_max_orphans;
- }
-
- return 0;
-}
-
-int do_proc_net_sockstat(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
-
- static uint32_t hash_sockets = 0,
- hash_raw = 0,
- hash_frag = 0,
- hash_tcp = 0,
- hash_udp = 0,
- hash_udplite = 0;
-
- static long long update_constants_every = 60, update_constants_count = 0;
-
- static ARL_BASE *arl_sockets = NULL;
- static ARL_BASE *arl_tcp = NULL;
- static ARL_BASE *arl_udp = NULL;
- static ARL_BASE *arl_udplite = NULL;
- static ARL_BASE *arl_raw = NULL;
- static ARL_BASE *arl_frag = NULL;
-
- static int do_sockets = -1, do_tcp_sockets = -1, do_tcp_mem = -1, do_udp_sockets = -1, do_udp_mem = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1, do_frag_mem = -1;
-
- static char *keys[7] = { NULL };
- static uint32_t hashes[7] = { 0 };
- static ARL_BASE *bases[7] = { NULL };
-
- if(unlikely(!arl_sockets)) {
- do_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 sockets", CONFIG_BOOLEAN_AUTO);
- do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 TCP sockets", CONFIG_BOOLEAN_AUTO);
- do_tcp_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 TCP memory", CONFIG_BOOLEAN_AUTO);
- do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDP sockets", CONFIG_BOOLEAN_AUTO);
- do_udp_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDP memory", CONFIG_BOOLEAN_AUTO);
- do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 UDPLITE sockets", CONFIG_BOOLEAN_AUTO);
- do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 RAW sockets", CONFIG_BOOLEAN_AUTO);
- do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 FRAG sockets", CONFIG_BOOLEAN_AUTO);
- do_frag_mem = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat", "ipv4 FRAG memory", CONFIG_BOOLEAN_AUTO);
-
- update_constants_every = config_get_number("plugin:proc:/proc/net/sockstat", "update constants every", update_constants_every);
- update_constants_count = update_constants_every;
-
- arl_sockets = arl_create("sockstat/sockets", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_sockets, "used", &sockstat_root.sockets_used);
-
- arl_tcp = arl_create("sockstat/TCP", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_tcp, "inuse", &sockstat_root.tcp_inuse);
- arl_expect(arl_tcp, "orphan", &sockstat_root.tcp_orphan);
- arl_expect(arl_tcp, "tw", &sockstat_root.tcp_tw);
- arl_expect(arl_tcp, "alloc", &sockstat_root.tcp_alloc);
- arl_expect(arl_tcp, "mem", &sockstat_root.tcp_mem);
-
- arl_udp = arl_create("sockstat/UDP", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_udp, "inuse", &sockstat_root.udp_inuse);
- arl_expect(arl_udp, "mem", &sockstat_root.udp_mem);
-
- arl_udplite = arl_create("sockstat/UDPLITE", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_udplite, "inuse", &sockstat_root.udplite_inuse);
-
- arl_raw = arl_create("sockstat/RAW", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_raw, "inuse", &sockstat_root.raw_inuse);
-
- arl_frag = arl_create("sockstat/FRAG", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_frag, "inuse", &sockstat_root.frag_inuse);
- arl_expect(arl_frag, "memory", &sockstat_root.frag_memory);
-
- hash_sockets = simple_hash("sockets");
- hash_tcp = simple_hash("TCP");
- hash_udp = simple_hash("UDP");
- hash_udplite = simple_hash("UDPLITE");
- hash_raw = simple_hash("RAW");
- hash_frag = simple_hash("FRAG");
-
- keys[0] = "sockets"; hashes[0] = hash_sockets; bases[0] = arl_sockets;
- keys[1] = "TCP"; hashes[1] = hash_tcp; bases[1] = arl_tcp;
- keys[2] = "UDP"; hashes[2] = hash_udp; bases[2] = arl_udp;
- keys[3] = "UDPLITE"; hashes[3] = hash_udplite; bases[3] = arl_udplite;
- keys[4] = "RAW"; hashes[4] = hash_raw; bases[4] = arl_raw;
- keys[5] = "FRAG"; hashes[5] = hash_frag; bases[5] = arl_frag;
- keys[6] = NULL; // terminator
- }
-
- update_constants_count += update_every;
- if(unlikely(update_constants_count > update_constants_every)) {
- read_tcp_max_orphans();
- read_tcp_mem();
- update_constants_count = 0;
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat");
- ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- char *key = procfile_lineword(ff, l, 0);
- uint32_t hash = simple_hash(key);
-
- int k;
- for(k = 0; keys[k] ; k++) {
- if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) {
- // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words);
- ARL_BASE *arl = bases[k];
- arl_begin(arl);
- size_t w = 1;
-
- while(w + 1 < words) {
- char *name = procfile_lineword(ff, l, w); w++;
- char *value = procfile_lineword(ff, l, w); w++;
- // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words);
- if(unlikely(arl_check(arl, name, value) != 0))
- break;
- }
-
- break;
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- if(do_sockets == CONFIG_BOOLEAN_YES || (do_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.sockets_used)) {
- do_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_used = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_sockets"
- , NULL
- , "sockets"
- , NULL
- , "IPv4 Sockets Used"
- , "sockets"
- , "proc"
- , "net/sockstat"
- , 2400
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_used = rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_used, (collected_number)sockstat_root.sockets_used);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat_root.tcp_inuse || sockstat_root.tcp_orphan || sockstat_root.tcp_tw || sockstat_root.tcp_alloc))) {
- do_tcp_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL,
- *rd_orphan = NULL,
- *rd_timewait = NULL,
- *rd_alloc = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_tcp_sockets"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat"
- , 2500
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_alloc = rrddim_add(st, "alloc", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_orphan = rrddim_add(st, "orphan", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_timewait = rrddim_add(st, "timewait", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.tcp_inuse);
- rrddim_set_by_pointer(st, rd_orphan, (collected_number)sockstat_root.tcp_orphan);
- rrddim_set_by_pointer(st, rd_timewait, (collected_number)sockstat_root.tcp_tw);
- rrddim_set_by_pointer(st, rd_alloc, (collected_number)sockstat_root.tcp_alloc);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_tcp_mem == CONFIG_BOOLEAN_YES || (do_tcp_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.tcp_mem)) {
- do_tcp_mem = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_mem = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_tcp_mem"
- , NULL
- , "tcp"
- , NULL
- , "IPv4 TCP Sockets Memory"
- , "KB"
- , "proc"
- , "net/sockstat"
- , 4000
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_mem = rrddim_add(st, "mem", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.tcp_mem);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.udp_inuse)) {
- do_udp_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_udp_sockets"
- , NULL
- , "udp"
- , NULL
- , "IPv4 UDP Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat"
- , 2600
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.udp_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_udp_mem == CONFIG_BOOLEAN_YES || (do_udp_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.udp_mem)) {
- do_udp_mem = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_mem = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_udp_mem"
- , NULL
- , "udp"
- , NULL
- , "IPv4 UDP Sockets Memory"
- , "KB"
- , "proc"
- , "net/sockstat"
- , 2603
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_mem = rrddim_add(st, "mem", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.udp_mem);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.udplite_inuse)) {
- do_udplite_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_udplite_sockets"
- , NULL
- , "udplite"
- , NULL
- , "IPv4 UDPLITE Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat"
- , 2602
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.udplite_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.raw_inuse)) {
- do_raw_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_raw_sockets"
- , NULL
- , "raw"
- , NULL
- , "IPv4 RAW Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.raw_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat_root.frag_inuse)) {
- do_frag_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_frag_sockets"
- , NULL
- , "fragments"
- , NULL
- , "IPv4 FRAG Sockets"
- , "fragments"
- , "proc"
- , "net/sockstat"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat_root.frag_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_frag_mem == CONFIG_BOOLEAN_YES || (do_frag_mem == CONFIG_BOOLEAN_AUTO && sockstat_root.frag_memory)) {
- do_frag_mem = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_mem = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv4"
- , "sockstat_frag_mem"
- , NULL
- , "fragments"
- , NULL
- , "IPv4 FRAG Sockets Memory"
- , "KB"
- , "proc"
- , "net/sockstat"
- , 3020
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_mem = rrddim_add(st, "mem", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_mem, (collected_number)sockstat_root.frag_memory);
- rrdset_done(st);
- }
-
- return 0;
-}
-
diff --git a/src/proc_net_sockstat6.c b/src/proc_net_sockstat6.c
deleted file mode 100644
index 97175ccf7..000000000
--- a/src/proc_net_sockstat6.c
+++ /dev/null
@@ -1,269 +0,0 @@
-#include "common.h"
-
-static struct proc_net_sockstat6 {
- kernel_uint_t tcp6_inuse;
- kernel_uint_t udp6_inuse;
- kernel_uint_t udplite6_inuse;
- kernel_uint_t raw6_inuse;
- kernel_uint_t frag6_inuse;
-} sockstat6_root = { 0 };
-
-int do_proc_net_sockstat6(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
-
- static uint32_t hash_raw = 0,
- hash_frag = 0,
- hash_tcp = 0,
- hash_udp = 0,
- hash_udplite = 0;
-
- static ARL_BASE *arl_tcp = NULL;
- static ARL_BASE *arl_udp = NULL;
- static ARL_BASE *arl_udplite = NULL;
- static ARL_BASE *arl_raw = NULL;
- static ARL_BASE *arl_frag = NULL;
-
- static int do_tcp_sockets = -1, do_udp_sockets = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1;
-
- static char *keys[6] = { NULL };
- static uint32_t hashes[6] = { 0 };
- static ARL_BASE *bases[6] = { NULL };
-
- if(unlikely(!arl_tcp)) {
- do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 TCP sockets", CONFIG_BOOLEAN_AUTO);
- do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDP sockets", CONFIG_BOOLEAN_AUTO);
- do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDPLITE sockets", CONFIG_BOOLEAN_AUTO);
- do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 RAW sockets", CONFIG_BOOLEAN_AUTO);
- do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 FRAG sockets", CONFIG_BOOLEAN_AUTO);
-
- arl_tcp = arl_create("sockstat6/TCP6", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_tcp, "inuse", &sockstat6_root.tcp6_inuse);
-
- arl_udp = arl_create("sockstat6/UDP6", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_udp, "inuse", &sockstat6_root.udp6_inuse);
-
- arl_udplite = arl_create("sockstat6/UDPLITE6", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_udplite, "inuse", &sockstat6_root.udplite6_inuse);
-
- arl_raw = arl_create("sockstat6/RAW6", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_raw, "inuse", &sockstat6_root.raw6_inuse);
-
- arl_frag = arl_create("sockstat6/FRAG6", arl_callback_str2kernel_uint_t, 60);
- arl_expect(arl_frag, "inuse", &sockstat6_root.frag6_inuse);
-
- hash_tcp = simple_hash("TCP6");
- hash_udp = simple_hash("UDP6");
- hash_udplite = simple_hash("UDPLITE6");
- hash_raw = simple_hash("RAW6");
- hash_frag = simple_hash("FRAG6");
-
- keys[0] = "TCP6"; hashes[0] = hash_tcp; bases[0] = arl_tcp;
- keys[1] = "UDP6"; hashes[1] = hash_udp; bases[1] = arl_udp;
- keys[2] = "UDPLITE6"; hashes[2] = hash_udplite; bases[2] = arl_udplite;
- keys[3] = "RAW6"; hashes[3] = hash_raw; bases[3] = arl_raw;
- keys[4] = "FRAG6"; hashes[4] = hash_frag; bases[4] = arl_frag;
- keys[5] = NULL; // terminator
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat6");
- ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- char *key = procfile_lineword(ff, l, 0);
- uint32_t hash = simple_hash(key);
-
- int k;
- for(k = 0; keys[k] ; k++) {
- if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) {
- // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words);
- ARL_BASE *arl = bases[k];
- arl_begin(arl);
- size_t w = 1;
-
- while(w + 1 < words) {
- char *name = procfile_lineword(ff, l, w); w++;
- char *value = procfile_lineword(ff, l, w); w++;
- // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words);
- if(unlikely(arl_check(arl, name, value) != 0))
- break;
- }
-
- break;
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat6_root.tcp6_inuse))) {
- do_tcp_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "sockstat6_tcp_sockets"
- , NULL
- , "tcp6"
- , NULL
- , "IPv6 TCP Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat6"
- , 3599
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.tcp6_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udp6_inuse)) {
- do_udp_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "sockstat6_udp_sockets"
- , NULL
- , "udp6"
- , NULL
- , "IPv6 UDP Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat6"
- , 3600
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udp6_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udplite6_inuse)) {
- do_udplite_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "sockstat6_udplite_sockets"
- , NULL
- , "udplite6"
- , NULL
- , "IPv6 UDPLITE Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat6"
- , 3601
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udplite6_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.raw6_inuse)) {
- do_raw_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "sockstat6_raw_sockets"
- , NULL
- , "raw6"
- , NULL
- , "IPv6 RAW Sockets"
- , "sockets"
- , "proc"
- , "net/sockstat6"
- , 3700
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.raw6_inuse);
- rrdset_done(st);
- }
-
- // ------------------------------------------------------------------------
-
- if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.frag6_inuse)) {
- do_frag_sockets = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- static RRDDIM *rd_inuse = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "ipv6"
- , "sockstat6_frag_sockets"
- , NULL
- , "fragments6"
- , NULL
- , "IPv6 FRAG Sockets"
- , "fragments"
- , "proc"
- , "net/sockstat6"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.frag6_inuse);
- rrdset_done(st);
- }
-
- return 0;
-}
diff --git a/src/proc_net_softnet_stat.c b/src/proc_net_softnet_stat.c
deleted file mode 100644
index f3c117e16..000000000
--- a/src/proc_net_softnet_stat.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include "common.h"
-
-static inline char *softnet_column_name(size_t column) {
- switch(column) {
- // https://github.com/torvalds/linux/blob/a7fd20d1c476af4563e66865213474a2f9f473a4/net/core/net-procfs.c#L161-L166
- case 0: return "processed";
- case 1: return "dropped";
- case 2: return "squeezed";
- case 9: return "received_rps";
- case 10: return "flow_limit_count";
- default: return NULL;
- }
-}
-
-int do_proc_net_softnet_stat(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
- static int do_per_core = -1;
- static size_t allocated_lines = 0, allocated_columns = 0;
- static uint32_t *data = NULL;
-
- if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/net/softnet_stat", "softnet_stat per core", 1);
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/softnet_stat");
- ff = procfile_open(config_get("plugin:proc:/proc/net/softnet_stat", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
- size_t words = procfile_linewords(ff, 0), w;
-
- if(unlikely(!lines || !words)) {
- error("Cannot read /proc/net/softnet_stat, %zu lines and %zu columns reported.", lines, words);
- return 1;
- }
-
- if(unlikely(lines > 200)) lines = 200;
- if(unlikely(words > 50)) words = 50;
-
- if(unlikely(!data || lines > allocated_lines || words > allocated_columns)) {
- freez(data);
- allocated_lines = lines;
- allocated_columns = words;
- data = mallocz((allocated_lines + 1) * allocated_columns * sizeof(uint32_t));
- }
-
- // initialize to zero
- memset(data, 0, (allocated_lines + 1) * allocated_columns * sizeof(uint32_t));
-
- // parse the values
- for(l = 0; l < lines ;l++) {
- words = procfile_linewords(ff, l);
- if(unlikely(!words)) continue;
-
- if(unlikely(words > allocated_columns))
- words = allocated_columns;
-
- for(w = 0; w < words ; w++) {
- if(unlikely(softnet_column_name(w))) {
- uint32_t t = (uint32_t)strtoul(procfile_lineword(ff, l, w), NULL, 16);
- data[w] += t;
- data[((l + 1) * allocated_columns) + w] = t;
- }
- }
- }
-
- if(unlikely(data[(lines * allocated_columns)] == 0))
- lines--;
-
- RRDSET *st;
-
- // --------------------------------------------------------------------
-
- st = rrdset_find_bytype_localhost("system", "softnet_stat");
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "softnet_stat"
- , NULL
- , "softnet_stat"
- , "system.softnet_stat"
- , "System softnet_stat"
- , "events/s"
- , "proc"
- , "net/softnet_stat"
- , 955
- , update_every
- , RRDSET_TYPE_LINE
- );
- for(w = 0; w < allocated_columns ;w++)
- if(unlikely(softnet_column_name(w)))
- rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- for(w = 0; w < allocated_columns ;w++)
- if(unlikely(softnet_column_name(w)))
- rrddim_set(st, softnet_column_name(w), data[w]);
-
- rrdset_done(st);
-
- if(do_per_core) {
- for(l = 0; l < lines ;l++) {
- char id[50+1];
- snprintfz(id, 50, "cpu%zu_softnet_stat", l);
-
- st = rrdset_find_bytype_localhost("cpu", id);
- if(unlikely(!st)) {
- char title[100+1];
- snprintfz(title, 100, "CPU%zu softnet_stat", l);
-
- st = rrdset_create_localhost(
- "cpu"
- , id
- , NULL
- , "softnet_stat"
- , "cpu.softnet_stat"
- , title
- , "events/s"
- , "proc"
- , "net/softnet_stat"
- , 4101 + l
- , update_every
- , RRDSET_TYPE_LINE
- );
- for(w = 0; w < allocated_columns ;w++)
- if(unlikely(softnet_column_name(w)))
- rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- for(w = 0; w < allocated_columns ;w++)
- if(unlikely(softnet_column_name(w)))
- rrddim_set(st, softnet_column_name(w), data[((l + 1) * allocated_columns) + w]);
-
- rrdset_done(st);
- }
- }
-
- return 0;
-}
diff --git a/src/proc_net_stat_conntrack.c b/src/proc_net_stat_conntrack.c
deleted file mode 100644
index 363fbc199..000000000
--- a/src/proc_net_stat_conntrack.c
+++ /dev/null
@@ -1,348 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
-#define RRD_TYPE_NET_STAT_CONNTRACK "conntrack"
-
-int do_proc_net_stat_conntrack(int update_every, usec_t dt) {
- static procfile *ff = NULL;
- static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
- static usec_t get_max_every = 10 * USEC_PER_SEC, usec_since_last_max = 0;
- static int read_full = 1;
- static char *nf_conntrack_filename, *nf_conntrack_count_filename, *nf_conntrack_max_filename;
- static RRDVAR *rrdvar_max = NULL;
-
- unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0,
- ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0;
-
- if(unlikely(do_sockets == -1)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/stat/nf_conntrack");
- nf_conntrack_filename = config_get("plugin:proc:/proc/net/stat/nf_conntrack", "filename to monitor", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sys/net/netfilter/nf_conntrack_max");
- nf_conntrack_max_filename = config_get("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "filename to monitor", filename);
- usec_since_last_max = get_max_every = config_get_number("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "read every seconds", 10) * USEC_PER_SEC;
-
- read_full = 1;
- ff = procfile_open(nf_conntrack_filename, " \t:", PROCFILE_FLAG_DEFAULT);
- if(!ff) read_full = 0;
-
- do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", read_full);
- do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", read_full);
- do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", read_full);
- do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", read_full);
- do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", read_full);
-
- do_sockets = 1;
- if(!read_full) {
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sys/net/netfilter/nf_conntrack_count");
- nf_conntrack_count_filename = config_get("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_count", "filename to monitor", filename);
-
- if(read_single_number_file(nf_conntrack_count_filename, &aentries))
- do_sockets = 0;
- }
-
- do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", do_sockets);
-
- if(!do_sockets && !read_full)
- return 1;
-
- rrdvar_max = rrdvar_custom_host_variable_create(localhost, "netfilter.conntrack.max");
- }
-
- if(likely(read_full)) {
- if(unlikely(!ff)) {
- ff = procfile_open(nf_conntrack_filename, " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- for(l = 1; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 17)) {
- if(unlikely(words)) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %zu.", words);
- continue;
- }
-
- unsigned long long tentries = 0, tsearched = 0, tfound = 0, tnew = 0, tinvalid = 0, tignore = 0, tdelete = 0, tdelete_list = 0, tinsert = 0, tinsert_failed = 0, tdrop = 0, tearly_drop = 0, ticmp_error = 0, texpect_new = 0, texpect_create = 0, texpect_delete = 0, tsearch_restart = 0;
-
- tentries = strtoull(procfile_lineword(ff, l, 0), NULL, 16);
- tsearched = strtoull(procfile_lineword(ff, l, 1), NULL, 16);
- tfound = strtoull(procfile_lineword(ff, l, 2), NULL, 16);
- tnew = strtoull(procfile_lineword(ff, l, 3), NULL, 16);
- tinvalid = strtoull(procfile_lineword(ff, l, 4), NULL, 16);
- tignore = strtoull(procfile_lineword(ff, l, 5), NULL, 16);
- tdelete = strtoull(procfile_lineword(ff, l, 6), NULL, 16);
- tdelete_list = strtoull(procfile_lineword(ff, l, 7), NULL, 16);
- tinsert = strtoull(procfile_lineword(ff, l, 8), NULL, 16);
- tinsert_failed = strtoull(procfile_lineword(ff, l, 9), NULL, 16);
- tdrop = strtoull(procfile_lineword(ff, l, 10), NULL, 16);
- tearly_drop = strtoull(procfile_lineword(ff, l, 11), NULL, 16);
- ticmp_error = strtoull(procfile_lineword(ff, l, 12), NULL, 16);
- texpect_new = strtoull(procfile_lineword(ff, l, 13), NULL, 16);
- texpect_create = strtoull(procfile_lineword(ff, l, 14), NULL, 16);
- texpect_delete = strtoull(procfile_lineword(ff, l, 15), NULL, 16);
- tsearch_restart = strtoull(procfile_lineword(ff, l, 16), NULL, 16);
-
- if(unlikely(!aentries)) aentries = tentries;
-
- // sum all the cpus together
- asearched += tsearched; // conntrack.search
- afound += tfound; // conntrack.search
- anew += tnew; // conntrack.new
- ainvalid += tinvalid; // conntrack.new
- aignore += tignore; // conntrack.new
- adelete += tdelete; // conntrack.changes
- adelete_list += tdelete_list; // conntrack.changes
- ainsert += tinsert; // conntrack.changes
- ainsert_failed += tinsert_failed; // conntrack.errors
- adrop += tdrop; // conntrack.errors
- aearly_drop += tearly_drop; // conntrack.errors
- aicmp_error += ticmp_error; // conntrack.errors
- aexpect_new += texpect_new; // conntrack.expect
- aexpect_create += texpect_create; // conntrack.expect
- aexpect_delete += texpect_delete; // conntrack.expect
- asearch_restart += tsearch_restart; // conntrack.search
- }
- }
- else {
- if(unlikely(read_single_number_file(nf_conntrack_count_filename, &aentries)))
- return 0; // we return 0, so that we will retry to open it next time
- }
-
- usec_since_last_max += dt;
- if(unlikely(rrdvar_max && usec_since_last_max >= get_max_every)) {
- usec_since_last_max = 0;
-
- unsigned long long max;
- if(likely(!read_single_number_file(nf_conntrack_max_filename, &max)))
- rrdvar_custom_host_variable_set(localhost, rrdvar_max, max);
- }
-
- // --------------------------------------------------------------------
-
- if(do_sockets) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_connections = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_sockets"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Connections"
- , "active connections"
- , "proc"
- , "net/stat/nf_conntrack"
- , 3000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_connections = rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_connections, aentries);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_new) {
- static RRDSET *st = NULL;
- static RRDDIM
- *rd_new = NULL,
- *rd_ignore = NULL,
- *rd_invalid = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_new"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker New Connections"
- , "connections/s"
- , "proc"
- , "net/stat/nf_conntrack"
- , 3001
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_new = rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_ignore = rrddim_add(st, "ignore", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_invalid = rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_new, anew);
- rrddim_set_by_pointer(st, rd_ignore, aignore);
- rrddim_set_by_pointer(st, rd_invalid, ainvalid);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_changes) {
- static RRDSET *st = NULL;
- static RRDDIM
- *rd_inserted = NULL,
- *rd_deleted = NULL,
- *rd_delete_list = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_changes"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Changes"
- , "changes/s"
- , "proc"
- , "net/stat/nf_conntrack"
- , 3002
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_inserted = rrddim_add(st, "inserted", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_deleted = rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_delete_list = rrddim_add(st, "delete_list", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_inserted, ainsert);
- rrddim_set_by_pointer(st, rd_deleted, adelete);
- rrddim_set_by_pointer(st, rd_delete_list, adelete_list);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_expect) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_created = NULL,
- *rd_deleted = NULL,
- *rd_new = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_expect"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Expectations"
- , "expectations/s"
- , "proc"
- , "net/stat/nf_conntrack"
- , 3003
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_created = rrddim_add(st, "created", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_deleted = rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_new = rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_created, aexpect_create);
- rrddim_set_by_pointer(st, rd_deleted, aexpect_delete);
- rrddim_set_by_pointer(st, rd_new, aexpect_new);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_search) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_searched = NULL,
- *rd_restarted = NULL,
- *rd_found = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_search"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Searches"
- , "searches/s"
- , "proc"
- , "net/stat/nf_conntrack"
- , 3010
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_searched = rrddim_add(st, "searched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_restarted = rrddim_add(st, "restarted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_found = rrddim_add(st, "found", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_searched, asearched);
- rrddim_set_by_pointer(st, rd_restarted, asearch_restart);
- rrddim_set_by_pointer(st, rd_found, afound);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_errors) {
- static RRDSET *st = NULL;
- static RRDDIM *rd_icmp_error = NULL,
- *rd_insert_failed = NULL,
- *rd_drop = NULL,
- *rd_early_drop = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_CONNTRACK "_errors"
- , NULL
- , RRD_TYPE_NET_STAT_CONNTRACK
- , NULL
- , "Connection Tracker Errors"
- , "events/s"
- , "proc"
- , "net/stat/nf_conntrack"
- , 3005
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
-
- rd_icmp_error = rrddim_add(st, "icmp_error", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_insert_failed = rrddim_add(st, "insert_failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_drop = rrddim_add(st, "drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_early_drop = rrddim_add(st, "early_drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd_icmp_error, aicmp_error);
- rrddim_set_by_pointer(st, rd_insert_failed, ainsert_failed);
- rrddim_set_by_pointer(st, rd_drop, adrop);
- rrddim_set_by_pointer(st, rd_early_drop, aearly_drop);
- rrdset_done(st);
- }
-
- return 0;
-}
diff --git a/src/proc_net_stat_synproxy.c b/src/proc_net_stat_synproxy.c
deleted file mode 100644
index 0d6f6ee03..000000000
--- a/src/proc_net_stat_synproxy.c
+++ /dev/null
@@ -1,181 +0,0 @@
-#include "common.h"
-
-#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
-#define RRD_TYPE_NET_STAT_SYNPROXY "synproxy"
-
-int do_proc_net_stat_synproxy(int update_every, usec_t dt) {
- (void)dt;
-
- static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
- static procfile *ff = NULL;
-
- if(unlikely(do_entries == -1)) {
- do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_BOOLEAN_AUTO);
- do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_BOOLEAN_AUTO);
- do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_BOOLEAN_AUTO);
- do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_BOOLEAN_AUTO);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/stat/synproxy");
- ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff))
- return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- // make sure we have 3 lines
- size_t lines = procfile_lines(ff), l;
- if(unlikely(lines < 2)) {
- error("/proc/net/stat/synproxy has %zu lines, expected no less than 2. Disabling it.", lines);
- return 1;
- }
-
- unsigned long long entries = 0, syn_received = 0, cookie_invalid = 0, cookie_valid = 0, cookie_retrans = 0, conn_reopened = 0;
-
- // synproxy gives its values per CPU
- for(l = 1; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 6))
- continue;
-
- entries += strtoull(procfile_lineword(ff, l, 0), NULL, 16);
- syn_received += strtoull(procfile_lineword(ff, l, 1), NULL, 16);
- cookie_invalid += strtoull(procfile_lineword(ff, l, 2), NULL, 16);
- cookie_valid += strtoull(procfile_lineword(ff, l, 3), NULL, 16);
- cookie_retrans += strtoull(procfile_lineword(ff, l, 4), NULL, 16);
- conn_reopened += strtoull(procfile_lineword(ff, l, 5), NULL, 16);
- }
-
- unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened;
-
- // --------------------------------------------------------------------
-
- if((do_entries == CONFIG_BOOLEAN_AUTO && events) || do_entries == CONFIG_BOOLEAN_YES) {
- do_entries = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_SYNPROXY "_entries"
- , NULL
- , RRD_TYPE_NET_STAT_SYNPROXY
- , NULL
- , "SYNPROXY Entries Used"
- , "entries"
- , "proc"
- , "net/stat/synproxy"
- , 3304
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "entries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "entries", entries);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if((do_syns == CONFIG_BOOLEAN_AUTO && events) || do_syns == CONFIG_BOOLEAN_YES) {
- do_syns = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_SYNPROXY "_syn_received"
- , NULL
- , RRD_TYPE_NET_STAT_SYNPROXY
- , NULL
- , "SYNPROXY SYN Packets received"
- , "SYN/s"
- , "proc"
- , "net/stat/synproxy"
- , 3301
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "received", syn_received);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if((do_reopened == CONFIG_BOOLEAN_AUTO && events) || do_reopened == CONFIG_BOOLEAN_YES) {
- do_reopened = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened"
- , NULL
- , RRD_TYPE_NET_STAT_SYNPROXY
- , NULL
- , "SYNPROXY Connections Reopened"
- , "connections/s"
- , "proc"
- , "net/stat/synproxy"
- , 3303
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "reopened", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "reopened", conn_reopened);
- rrdset_done(st);
- }
-
- // --------------------------------------------------------------------
-
- if((do_cookies == CONFIG_BOOLEAN_AUTO && events) || do_cookies == CONFIG_BOOLEAN_YES) {
- do_cookies = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st = NULL;
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- RRD_TYPE_NET_STAT_NETFILTER
- , RRD_TYPE_NET_STAT_SYNPROXY "_cookies"
- , NULL
- , RRD_TYPE_NET_STAT_SYNPROXY
- , NULL
- , "SYNPROXY TCP Cookies"
- , "cookies/s"
- , "proc"
- , "net/stat/synproxy"
- , 3302
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(st, "valid", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(st, "retransmits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st);
-
- rrddim_set(st, "valid", cookie_valid);
- rrddim_set(st, "invalid", cookie_invalid);
- rrddim_set(st, "retransmits", cookie_retrans);
- rrdset_done(st);
- }
-
- return 0;
-}
diff --git a/src/proc_self_mountinfo.c b/src/proc_self_mountinfo.c
deleted file mode 100644
index 4ccdddff1..000000000
--- a/src/proc_self_mountinfo.c
+++ /dev/null
@@ -1,401 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// taken from gnulib/mountlist.c
-
-#ifndef ME_REMOTE
-/* A file system is "remote" if its Fs_name contains a ':'
- or if (it is of type (smbfs or cifs) and its Fs_name starts with '//')
- or Fs_name is equal to "-hosts" (used by autofs to mount remote fs). */
-# define ME_REMOTE(Fs_name, Fs_type) \
- (strchr (Fs_name, ':') != NULL \
- || ((Fs_name)[0] == '/' \
- && (Fs_name)[1] == '/' \
- && (strcmp (Fs_type, "smbfs") == 0 \
- || strcmp (Fs_type, "cifs") == 0)) \
- || (strcmp("-hosts", Fs_name) == 0))
-#endif
-
-#define ME_DUMMY_0(Fs_name, Fs_type) \
- (strcmp (Fs_type, "autofs") == 0 \
- || strcmp (Fs_type, "proc") == 0 \
- || strcmp (Fs_type, "subfs") == 0 \
- /* for Linux 2.6/3.x */ \
- || strcmp (Fs_type, "debugfs") == 0 \
- || strcmp (Fs_type, "devpts") == 0 \
- || strcmp (Fs_type, "fusectl") == 0 \
- || strcmp (Fs_type, "mqueue") == 0 \
- || strcmp (Fs_type, "rpc_pipefs") == 0 \
- || strcmp (Fs_type, "sysfs") == 0 \
- /* FreeBSD, Linux 2.4 */ \
- || strcmp (Fs_type, "devfs") == 0 \
- /* for NetBSD 3.0 */ \
- || strcmp (Fs_type, "kernfs") == 0 \
- /* for Irix 6.5 */ \
- || strcmp (Fs_type, "ignore") == 0)
-
-/* Historically, we have marked as "dummy" any file system of type "none",
- but now that programs like du need to know about bind-mounted directories,
- we grant an exception to any with "bind" in its list of mount options.
- I.e., those are *not* dummy entries. */
-# define ME_DUMMY(Fs_name, Fs_type) \
- (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
-
-// ----------------------------------------------------------------------------
-
-// find the mount info with the given major:minor
-// in the supplied linked list of mountinfo structures
-struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor) {
- struct mountinfo *mi;
-
- for(mi = root; mi ; mi = mi->next)
- if(unlikely(mi->major == major && mi->minor == minor))
- return mi;
-
- return NULL;
-}
-
-// find the mount info with the given filesystem and mount_source
-// in the supplied linked list of mountinfo structures
-struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *root, const char *filesystem, const char *mount_source) {
- struct mountinfo *mi;
- uint32_t filesystem_hash = simple_hash(filesystem), mount_source_hash = simple_hash(mount_source);
-
- for(mi = root; mi ; mi = mi->next)
- if(unlikely(mi->filesystem
- && mi->mount_source
- && mi->filesystem_hash == filesystem_hash
- && mi->mount_source_hash == mount_source_hash
- && !strcmp(mi->filesystem, filesystem)
- && !strcmp(mi->mount_source, mount_source)))
- return mi;
-
- return NULL;
-}
-
-struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *root, const char *filesystem, const char *super_options) {
- struct mountinfo *mi;
- uint32_t filesystem_hash = simple_hash(filesystem);
-
- size_t solen = strlen(super_options);
-
- for(mi = root; mi ; mi = mi->next)
- if(unlikely(mi->filesystem
- && mi->super_options
- && mi->filesystem_hash == filesystem_hash
- && !strcmp(mi->filesystem, filesystem))) {
-
- // super_options is a comma separated list
- char *s = mi->super_options, *e;
- while(*s) {
- e = s + 1;
- while(*e && *e != ',') e++;
-
- size_t len = e - s;
- if(unlikely(len == solen && !strncmp(s, super_options, len)))
- return mi;
-
- if(*e == ',') s = ++e;
- else s = e;
- }
- }
-
- return NULL;
-}
-
-static void mountinfo_free(struct mountinfo *mi) {
- freez(mi->root);
- freez(mi->mount_point);
- freez(mi->mount_options);
- freez(mi->persistent_id);
-/*
- if(mi->optional_fields_count) {
- int i;
- for(i = 0; i < mi->optional_fields_count ; i++)
- free(*mi->optional_fields[i]);
- }
- free(mi->optional_fields);
-*/
- freez(mi->filesystem);
- freez(mi->mount_source);
- freez(mi->super_options);
- freez(mi);
-}
-
-// free a linked list of mountinfo structures
-void mountinfo_free_all(struct mountinfo *mi) {
- while(mi) {
- struct mountinfo *t = mi;
- mi = mi->next;
-
- mountinfo_free(t);
- }
-}
-
-static char *strdupz_decoding_octal(const char *string) {
- char *buffer = strdupz(string);
-
- char *d = buffer;
- const char *s = string;
-
- while(*s) {
- if(unlikely(*s == '\\')) {
- s++;
- if(likely(isdigit(*s) && isdigit(s[1]) && isdigit(s[2]))) {
- char c = *s++ - '0';
- c <<= 3;
- c |= *s++ - '0';
- c <<= 3;
- c |= *s++ - '0';
- *d++ = c;
- }
- else *d++ = '_';
- }
- else *d++ = *s++;
- }
- *d = '\0';
-
- return buffer;
-}
-
-static inline int is_read_only(const char *s) {
- if(!s) return 0;
-
- size_t len = strlen(s);
- if(len < 2) return 0;
- if(len == 2) {
- if(!strcmp(s, "ro")) return 1;
- return 0;
- }
- if(!strncmp(s, "ro,", 3)) return 1;
- if(!strncmp(&s[len - 3], ",ro", 3)) return 1;
- if(strstr(s, ",ro,")) return 1;
- return 0;
-}
-
-// read the whole mountinfo into a linked list
-struct mountinfo *mountinfo_read(int do_statvfs) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
- procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix);
- ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return NULL;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return NULL;
-
- struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
-
- unsigned long l, lines = procfile_lines(ff);
- for(l = 0; l < lines ;l++) {
- if(unlikely(procfile_linewords(ff, l) < 5))
- continue;
-
- mi = mallocz(sizeof(struct mountinfo));
-
- unsigned long w = 0;
- mi->id = str2ul(procfile_lineword(ff, l, w)); w++;
- mi->parentid = str2ul(procfile_lineword(ff, l, w)); w++;
-
- char *major = procfile_lineword(ff, l, w), *minor; w++;
- for(minor = major; *minor && *minor != ':' ;minor++) ;
-
- if(unlikely(!*minor)) {
- error("Cannot parse major:minor on '%s' at line %lu of '%s'", major, l + 1, filename);
- freez(mi);
- continue;
- }
-
- *minor = '\0';
- minor++;
-
- mi->flags = 0;
-
- mi->major = str2ul(major);
- mi->minor = str2ul(minor);
-
- mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
- mi->root_hash = simple_hash(mi->root);
-
- mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
- mi->mount_point_hash = simple_hash(mi->mount_point);
-
- mi->persistent_id = strdupz(mi->mount_point);
- netdata_fix_chart_id(mi->persistent_id);
- mi->persistent_id_hash = simple_hash(mi->persistent_id);
-
- mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
-
- if(unlikely(is_read_only(mi->mount_options)))
- mi->flags |= MOUNTINFO_READONLY;
-
- // count the optional fields
-/*
- unsigned long wo = w;
-*/
- mi->optional_fields_count = 0;
- char *s = procfile_lineword(ff, l, w);
- while(*s && *s != '-') {
- w++;
- s = procfile_lineword(ff, l, w);
- mi->optional_fields_count++;
- }
-
-/*
- if(unlikely(mi->optional_fields_count)) {
- // we have some optional fields
- // read them into a new array of pointers;
-
- mi->optional_fields = mallocz(mi->optional_fields_count * sizeof(char *));
-
- int i;
- for(i = 0; i < mi->optional_fields_count ; i++) {
- *mi->optional_fields[wo] = strdupz(procfile_lineword(ff, l, w));
- wo++;
- }
- }
- else
- mi->optional_fields = NULL;
-*/
-
- if(likely(*s == '-')) {
- w++;
-
- mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++;
- mi->filesystem_hash = simple_hash(mi->filesystem);
-
- mi->mount_source = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
- mi->mount_source_hash = simple_hash(mi->mount_source);
-
- mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
-
- if(unlikely(is_read_only(mi->super_options)))
- mi->flags |= MOUNTINFO_READONLY;
-
- if(unlikely(ME_DUMMY(mi->mount_source, mi->filesystem)))
- mi->flags |= MOUNTINFO_IS_DUMMY;
-
- if(unlikely(ME_REMOTE(mi->mount_source, mi->filesystem)))
- mi->flags |= MOUNTINFO_IS_REMOTE;
-
- // mark as BIND the duplicates (i.e. same filesystem + same source)
- if(do_statvfs) {
- struct stat buf;
- if(unlikely(stat(mi->mount_point, &buf) == -1)) {
- mi->st_dev = 0;
- mi->flags |= MOUNTINFO_NO_STAT;
- }
- else {
- mi->st_dev = buf.st_dev;
-
- struct mountinfo *mt;
- for(mt = root; mt; mt = mt->next) {
- if(unlikely(mt->st_dev == mi->st_dev && !(mt->flags & MOUNTINFO_IS_SAME_DEV))) {
- if(strlen(mi->mount_point) < strlen(mt->mount_point))
- mt->flags |= MOUNTINFO_IS_SAME_DEV;
- else
- mi->flags |= MOUNTINFO_IS_SAME_DEV;
- }
- }
- }
- }
- else {
- mi->st_dev = 0;
- }
- }
- else {
- mi->filesystem = NULL;
- mi->filesystem_hash = 0;
-
- mi->mount_source = NULL;
- mi->mount_source_hash = 0;
-
- mi->super_options = NULL;
-
- mi->st_dev = 0;
- }
-
- // check if it has size
- if(do_statvfs && !(mi->flags & MOUNTINFO_IS_DUMMY)) {
- struct statvfs buff_statvfs;
- if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) {
- mi->flags |= MOUNTINFO_NO_STAT;
- }
- else if(unlikely(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */)) {
- mi->flags |= MOUNTINFO_NO_SIZE;
- }
- }
-
- // link it
- if(unlikely(!root))
- root = mi;
- else
- last->next = mi;
-
- last = mi;
- mi->next = NULL;
-
-/*
-#ifdef NETDATA_INTERNAL_CHECKS
- fprintf(stderr, "MOUNTINFO: %ld %ld %lu:%lu root '%s', persistent id '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'%s%s%s%s%s%s\n",
- mi->id,
- mi->parentid,
- mi->major,
- mi->minor,
- mi->root,
- mi->persistent_id,
- (mi->mount_point)?mi->mount_point:"",
- (mi->mount_options)?mi->mount_options:"",
- (mi->filesystem)?mi->filesystem:"",
- (mi->mount_source)?mi->mount_source:"",
- (mi->super_options)?mi->super_options:"",
- (mi->flags & MOUNTINFO_IS_DUMMY)?" DUMMY":"",
- (mi->flags & MOUNTINFO_IS_BIND)?" BIND":"",
- (mi->flags & MOUNTINFO_IS_REMOTE)?" REMOTE":"",
- (mi->flags & MOUNTINFO_NO_STAT)?" NOSTAT":"",
- (mi->flags & MOUNTINFO_NO_SIZE)?" NOSIZE":"",
- (mi->flags & MOUNTINFO_IS_SAME_DEV)?" SAMEDEV":""
- );
-#endif
-*/
- }
-
-/* find if the mount options have "bind" in them
- {
- FILE *fp = setmntent(MOUNTED, "r");
- if (fp != NULL) {
- struct mntent mntbuf;
- struct mntent *mnt;
- char buf[4096 + 1];
-
- while ((mnt = getmntent_r(fp, &mntbuf, buf, 4096))) {
- char *bind = hasmntopt(mnt, "bind");
- if(unlikely(bind)) {
- struct mountinfo *mi;
- for(mi = root; mi ; mi = mi->next) {
- if(unlikely(strcmp(mnt->mnt_dir, mi->mount_point) == 0)) {
- fprintf(stderr, "Mount point '%s' is BIND\n", mi->mount_point);
- mi->flags |= MOUNTINFO_IS_BIND;
- break;
- }
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(!mi)) {
- error("Mount point '%s' not found in /proc/self/mountinfo", mnt->mnt_dir);
- }
-#endif
- }
- }
- endmntent(fp);
- }
- }
-*/
-
- procfile_close(ff);
- return root;
-}
diff --git a/src/proc_self_mountinfo.h b/src/proc_self_mountinfo.h
deleted file mode 100644
index a8d337539..000000000
--- a/src/proc_self_mountinfo.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef NETDATA_PROC_SELF_MOUNTINFO_H
-#define NETDATA_PROC_SELF_MOUNTINFO_H 1
-
-#define MOUNTINFO_IS_DUMMY 0x00000001
-#define MOUNTINFO_IS_REMOTE 0x00000002
-#define MOUNTINFO_IS_BIND 0x00000004
-#define MOUNTINFO_IS_SAME_DEV 0x00000008
-#define MOUNTINFO_NO_STAT 0x00000010
-#define MOUNTINFO_NO_SIZE 0x00000020
-#define MOUNTINFO_READONLY 0x00000040
-
-struct mountinfo {
- long id; // mount ID: unique identifier of the mount (may be reused after umount(2)).
- long parentid; // parent ID: ID of parent mount (or of self for the top of the mount tree).
- unsigned long major; // major:minor: value of st_dev for files on filesystem (see stat(2)).
- unsigned long minor;
-
- char *persistent_id; // a calculated persistent id for the mount point
- uint32_t persistent_id_hash;
-
- char *root; // root: root of the mount within the filesystem.
- uint32_t root_hash;
-
- char *mount_point; // mount point: mount point relative to the process's root.
- uint32_t mount_point_hash;
-
- char *mount_options; // mount options: per-mount options.
-
- int optional_fields_count;
-/*
- char ***optional_fields; // optional fields: zero or more fields of the form "tag[:value]".
-*/
- char *filesystem; // filesystem type: name of filesystem in the form "type[.subtype]".
- uint32_t filesystem_hash;
-
- char *mount_source; // mount source: filesystem-specific information or "none".
- uint32_t mount_source_hash;
-
- char *super_options; // super options: per-superblock options.
-
- uint32_t flags;
-
- dev_t st_dev; // id of device as given by stat()
-
- struct mountinfo *next;
-};
-
-extern struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor);
-extern struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *root, const char *filesystem, const char *mount_source);
-extern struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *root, const char *filesystem, const char *super_options);
-
-extern void mountinfo_free_all(struct mountinfo *mi);
-extern struct mountinfo *mountinfo_read(int do_statvfs);
-
-#endif /* NETDATA_PROC_SELF_MOUNTINFO_H */ \ No newline at end of file
diff --git a/src/proc_softirqs.c b/src/proc_softirqs.c
deleted file mode 100644
index cd7440b00..000000000
--- a/src/proc_softirqs.c
+++ /dev/null
@@ -1,249 +0,0 @@
-#include "common.h"
-
-#define MAX_INTERRUPT_NAME 50
-
-struct cpu_interrupt {
- unsigned long long value;
- RRDDIM *rd;
-};
-
-struct interrupt {
- int used;
- char *id;
- char name[MAX_INTERRUPT_NAME + 1];
- RRDDIM *rd;
- unsigned long long total;
- struct cpu_interrupt cpu[];
-};
-
-// since each interrupt is variable in size
-// we use this to calculate its record size
-#define recordsize(cpus) (sizeof(struct interrupt) + ((cpus) * sizeof(struct cpu_interrupt)))
-
-// given a base, get a pointer to each record
-#define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[(line) * recordsize(cpus)])
-
-static inline struct interrupt *get_interrupts_array(size_t lines, int cpus) {
- static struct interrupt *irrs = NULL;
- static size_t allocated = 0;
-
- if(unlikely(lines != allocated)) {
- uint32_t l;
- int c;
-
- irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
-
- // reset all interrupt RRDDIM pointers as any line could have shifted
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- irr->rd = NULL;
- irr->name[0] = '\0';
- for(c = 0; c < cpus ;c++)
- irr->cpu[c].rd = NULL;
- }
-
- allocated = lines;
- }
-
- return irrs;
-}
-
-int do_proc_softirqs(int update_every, usec_t dt) {
- (void)dt;
- static procfile *ff = NULL;
- static int cpus = -1, do_per_core = -1;
- struct interrupt *irrs = NULL;
-
- if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/softirqs");
- ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
- size_t words = procfile_linewords(ff, 0);
-
- if(unlikely(!lines)) {
- error("Cannot read /proc/softirqs, zero lines reported.");
- return 1;
- }
-
- // find how many CPUs are there
- if(unlikely(cpus == -1)) {
- uint32_t w;
- cpus = 0;
- for(w = 0; w < words ; w++) {
- if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
- cpus++;
- }
- }
-
- if(unlikely(!cpus)) {
- error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
- return 1;
- }
-
- // allocate the size we need;
- irrs = get_interrupts_array(lines, cpus);
- irrs[0].used = 0;
-
- // loop through all lines
- for(l = 1; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- irr->used = 0;
- irr->total = 0;
-
- words = procfile_linewords(ff, l);
- if(unlikely(!words)) continue;
-
- irr->id = procfile_lineword(ff, l, 0);
- if(unlikely(!irr->id || !irr->id[0])) continue;
-
- size_t idlen = strlen(irr->id);
- if(unlikely(idlen && irr->id[idlen - 1] == ':'))
- irr->id[idlen - 1] = '\0';
-
- int c;
- for(c = 0; c < cpus ;c++) {
- if(likely((c + 1) < (int)words))
- irr->cpu[c].value = str2ull(procfile_lineword(ff, l, (uint32_t)(c + 1)));
- else
- irr->cpu[c].value = 0;
-
- irr->total += irr->cpu[c].value;
- }
-
- strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
-
- irr->used = 1;
- }
-
- // --------------------------------------------------------------------
-
- static RRDSET *st_system_softirqs = NULL;
- if(unlikely(!st_system_softirqs))
- st_system_softirqs = rrdset_create_localhost(
- "system"
- , "softirqs"
- , NULL
- , "softirqs"
- , NULL
- , "System softirqs"
- , "softirqs/s"
- , "proc"
- , "softirqs"
- , 950
- , update_every
- , RRDSET_TYPE_STACKED
- );
- else
- rrdset_next(st_system_softirqs);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
-
- if(unlikely(!irr->used)) continue;
-
- // some interrupt may have changed without changing the total number of lines
- // if the same number of interrupts have been added and removed between two
- // calls of this function.
- if(unlikely(!irr->rd || strncmp(irr->name, irr->rd->name, MAX_INTERRUPT_NAME) != 0)) {
- irr->rd = rrddim_find(st_system_softirqs, irr->id);
-
- if(unlikely(!irr->rd))
- irr->rd = rrddim_add(st_system_softirqs, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- else
- rrddim_set_name(st_system_softirqs, irr->rd, irr->name);
-
- // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
- if(likely(do_per_core)) {
- int c;
- for (c = 0; c < cpus ;c++) irr->cpu[c].rd = NULL;
- }
- }
-
- rrddim_set_by_pointer(st_system_softirqs, irr->rd, irr->total);
- }
-
- rrdset_done(st_system_softirqs);
-
- // --------------------------------------------------------------------
-
- if(do_per_core) {
- static RRDSET **core_st = NULL;
- static int old_cpus = 0;
-
- if(old_cpus < cpus) {
- core_st = reallocz(core_st, sizeof(RRDSET *) * cpus);
- memset(&core_st[old_cpus], 0, sizeof(RRDSET *) * (cpus - old_cpus));
- old_cpus = cpus;
- }
-
- int c;
-
- for(c = 0; c < cpus ; c++) {
- if(unlikely(!core_st[c])) {
- // find if everything is just zero
- unsigned long long core_sum = 0;
-
- for (l = 0; l < lines; l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- if (unlikely(!irr->used)) continue;
- core_sum += irr->cpu[c].value;
- }
-
- if (unlikely(core_sum == 0)) continue; // try next core
-
- char id[50 + 1];
- snprintfz(id, 50, "cpu%d_softirqs", c);
-
- char title[100 + 1];
- snprintfz(title, 100, "CPU%d softirqs", c);
-
- core_st[c] = rrdset_create_localhost(
- "cpu"
- , id
- , NULL
- , "softirqs"
- , "cpu.softirqs"
- , title
- , "softirqs/s"
- , "proc"
- , "softirqs"
- , 3000 + c
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else
- rrdset_next(core_st[c]);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
-
- if(unlikely(!irr->used)) continue;
-
- if(unlikely(!irr->cpu[c].rd)) {
- irr->cpu[c].rd = rrddim_find(core_st[c], irr->id);
-
- if(unlikely(!irr->cpu[c].rd))
- irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- else
- rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name);
- }
-
- rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value);
- }
-
- rrdset_done(core_st[c]);
- }
- }
-
- return 0;
-}
diff --git a/src/proc_spl_kstat_zfs.c b/src/proc_spl_kstat_zfs.c
deleted file mode 100644
index 9d489d8e4..000000000
--- a/src/proc_spl_kstat_zfs.c
+++ /dev/null
@@ -1,153 +0,0 @@
-#include "common.h"
-#include "zfs_common.h"
-
-#define ZFS_PROC_ARCSTATS "/proc/spl/kstat/zfs/arcstats"
-
-extern struct arcstats arcstats;
-
-int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
- static ARL_BASE *arl_base = NULL;
-
- arcstats.l2exist = -1;
-
- if(unlikely(!arl_base)) {
- arl_base = arl_create("arcstats", NULL, 60);
-
- arl_expect(arl_base, "hits", &arcstats.hits);
- arl_expect(arl_base, "misses", &arcstats.misses);
- arl_expect(arl_base, "demand_data_hits", &arcstats.demand_data_hits);
- arl_expect(arl_base, "demand_data_misses", &arcstats.demand_data_misses);
- arl_expect(arl_base, "demand_metadata_hits", &arcstats.demand_metadata_hits);
- arl_expect(arl_base, "demand_metadata_misses", &arcstats.demand_metadata_misses);
- arl_expect(arl_base, "prefetch_data_hits", &arcstats.prefetch_data_hits);
- arl_expect(arl_base, "prefetch_data_misses", &arcstats.prefetch_data_misses);
- arl_expect(arl_base, "prefetch_metadata_hits", &arcstats.prefetch_metadata_hits);
- arl_expect(arl_base, "prefetch_metadata_misses", &arcstats.prefetch_metadata_misses);
- arl_expect(arl_base, "mru_hits", &arcstats.mru_hits);
- arl_expect(arl_base, "mru_ghost_hits", &arcstats.mru_ghost_hits);
- arl_expect(arl_base, "mfu_hits", &arcstats.mfu_hits);
- arl_expect(arl_base, "mfu_ghost_hits", &arcstats.mfu_ghost_hits);
- arl_expect(arl_base, "deleted", &arcstats.deleted);
- arl_expect(arl_base, "mutex_miss", &arcstats.mutex_miss);
- arl_expect(arl_base, "evict_skip", &arcstats.evict_skip);
- arl_expect(arl_base, "evict_not_enough", &arcstats.evict_not_enough);
- arl_expect(arl_base, "evict_l2_cached", &arcstats.evict_l2_cached);
- arl_expect(arl_base, "evict_l2_eligible", &arcstats.evict_l2_eligible);
- arl_expect(arl_base, "evict_l2_ineligible", &arcstats.evict_l2_ineligible);
- arl_expect(arl_base, "evict_l2_skip", &arcstats.evict_l2_skip);
- arl_expect(arl_base, "hash_elements", &arcstats.hash_elements);
- arl_expect(arl_base, "hash_elements_max", &arcstats.hash_elements_max);
- arl_expect(arl_base, "hash_collisions", &arcstats.hash_collisions);
- arl_expect(arl_base, "hash_chains", &arcstats.hash_chains);
- arl_expect(arl_base, "hash_chain_max", &arcstats.hash_chain_max);
- arl_expect(arl_base, "p", &arcstats.p);
- arl_expect(arl_base, "c", &arcstats.c);
- arl_expect(arl_base, "c_min", &arcstats.c_min);
- arl_expect(arl_base, "c_max", &arcstats.c_max);
- arl_expect(arl_base, "size", &arcstats.size);
- arl_expect(arl_base, "hdr_size", &arcstats.hdr_size);
- arl_expect(arl_base, "data_size", &arcstats.data_size);
- arl_expect(arl_base, "metadata_size", &arcstats.metadata_size);
- arl_expect(arl_base, "other_size", &arcstats.other_size);
- arl_expect(arl_base, "anon_size", &arcstats.anon_size);
- arl_expect(arl_base, "anon_evictable_data", &arcstats.anon_evictable_data);
- arl_expect(arl_base, "anon_evictable_metadata", &arcstats.anon_evictable_metadata);
- arl_expect(arl_base, "mru_size", &arcstats.mru_size);
- arl_expect(arl_base, "mru_evictable_data", &arcstats.mru_evictable_data);
- arl_expect(arl_base, "mru_evictable_metadata", &arcstats.mru_evictable_metadata);
- arl_expect(arl_base, "mru_ghost_size", &arcstats.mru_ghost_size);
- arl_expect(arl_base, "mru_ghost_evictable_data", &arcstats.mru_ghost_evictable_data);
- arl_expect(arl_base, "mru_ghost_evictable_metadata", &arcstats.mru_ghost_evictable_metadata);
- arl_expect(arl_base, "mfu_size", &arcstats.mfu_size);
- arl_expect(arl_base, "mfu_evictable_data", &arcstats.mfu_evictable_data);
- arl_expect(arl_base, "mfu_evictable_metadata", &arcstats.mfu_evictable_metadata);
- arl_expect(arl_base, "mfu_ghost_size", &arcstats.mfu_ghost_size);
- arl_expect(arl_base, "mfu_ghost_evictable_data", &arcstats.mfu_ghost_evictable_data);
- arl_expect(arl_base, "mfu_ghost_evictable_metadata", &arcstats.mfu_ghost_evictable_metadata);
- arl_expect(arl_base, "l2_hits", &arcstats.l2_hits);
- arl_expect(arl_base, "l2_misses", &arcstats.l2_misses);
- arl_expect(arl_base, "l2_feeds", &arcstats.l2_feeds);
- arl_expect(arl_base, "l2_rw_clash", &arcstats.l2_rw_clash);
- arl_expect(arl_base, "l2_read_bytes", &arcstats.l2_read_bytes);
- arl_expect(arl_base, "l2_write_bytes", &arcstats.l2_write_bytes);
- arl_expect(arl_base, "l2_writes_sent", &arcstats.l2_writes_sent);
- arl_expect(arl_base, "l2_writes_done", &arcstats.l2_writes_done);
- arl_expect(arl_base, "l2_writes_error", &arcstats.l2_writes_error);
- arl_expect(arl_base, "l2_writes_lock_retry", &arcstats.l2_writes_lock_retry);
- arl_expect(arl_base, "l2_evict_lock_retry", &arcstats.l2_evict_lock_retry);
- arl_expect(arl_base, "l2_evict_reading", &arcstats.l2_evict_reading);
- arl_expect(arl_base, "l2_evict_l1cached", &arcstats.l2_evict_l1cached);
- arl_expect(arl_base, "l2_free_on_write", &arcstats.l2_free_on_write);
- arl_expect(arl_base, "l2_cdata_free_on_write", &arcstats.l2_cdata_free_on_write);
- arl_expect(arl_base, "l2_abort_lowmem", &arcstats.l2_abort_lowmem);
- arl_expect(arl_base, "l2_cksum_bad", &arcstats.l2_cksum_bad);
- arl_expect(arl_base, "l2_io_error", &arcstats.l2_io_error);
- arl_expect(arl_base, "l2_size", &arcstats.l2_size);
- arl_expect(arl_base, "l2_asize", &arcstats.l2_asize);
- arl_expect(arl_base, "l2_hdr_size", &arcstats.l2_hdr_size);
- arl_expect(arl_base, "l2_compress_successes", &arcstats.l2_compress_successes);
- arl_expect(arl_base, "l2_compress_zeros", &arcstats.l2_compress_zeros);
- arl_expect(arl_base, "l2_compress_failures", &arcstats.l2_compress_failures);
- arl_expect(arl_base, "memory_throttle_count", &arcstats.memory_throttle_count);
- arl_expect(arl_base, "duplicate_buffers", &arcstats.duplicate_buffers);
- arl_expect(arl_base, "duplicate_buffers_size", &arcstats.duplicate_buffers_size);
- arl_expect(arl_base, "duplicate_reads", &arcstats.duplicate_reads);
- arl_expect(arl_base, "memory_direct_count", &arcstats.memory_direct_count);
- arl_expect(arl_base, "memory_indirect_count", &arcstats.memory_indirect_count);
- arl_expect(arl_base, "arc_no_grow", &arcstats.arc_no_grow);
- arl_expect(arl_base, "arc_tempreserve", &arcstats.arc_tempreserve);
- arl_expect(arl_base, "arc_loaned_bytes", &arcstats.arc_loaned_bytes);
- arl_expect(arl_base, "arc_prune", &arcstats.arc_prune);
- arl_expect(arl_base, "arc_meta_used", &arcstats.arc_meta_used);
- arl_expect(arl_base, "arc_meta_limit", &arcstats.arc_meta_limit);
- arl_expect(arl_base, "arc_meta_max", &arcstats.arc_meta_max);
- arl_expect(arl_base, "arc_meta_min", &arcstats.arc_meta_min);
- arl_expect(arl_base, "arc_need_free", &arcstats.arc_need_free);
- arl_expect(arl_base, "arc_sys_free", &arcstats.arc_sys_free);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, ZFS_PROC_ARCSTATS);
- ff = procfile_open(config_get("plugin:proc:" ZFS_PROC_ARCSTATS, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff))
- return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff))
- return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- arl_begin(arl_base);
-
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 3)) {
- if(unlikely(words)) error("Cannot read " ZFS_PROC_ARCSTATS " line %zu. Expected 3 params, read %zu.", l, words);
- continue;
- }
-
- const char *key = procfile_lineword(ff, l, 0);
- const char *value = procfile_lineword(ff, l, 2);
-
- if(unlikely(arcstats.l2exist == -1)) {
- if(key[0] == 'l' && key[1] == '2' && key[2] == '_')
- arcstats.l2exist = 1;
- }
-
- if(unlikely(arl_check(arl_base, key, value))) break;
- }
-
- if(unlikely(arcstats.l2exist == -1))
- arcstats.l2exist = 0;
-
- generate_charts_arcstats("proc", update_every);
- generate_charts_arc_summary("proc", update_every);
-
- return 0;
-}
diff --git a/src/proc_stat.c b/src/proc_stat.c
deleted file mode 100644
index d1aefb73e..000000000
--- a/src/proc_stat.c
+++ /dev/null
@@ -1,557 +0,0 @@
-#include "common.h"
-
-struct per_core_single_number_file {
- char found:1;
- const char *filename;
- int fd;
- collected_number value;
- RRDDIM *rd;
-};
-
-#define CORE_THROTTLE_COUNT_INDEX 0
-#define PACKAGE_THROTTLE_COUNT_INDEX 1
-#define SCALING_CUR_FREQ_INDEX 2
-#define PER_CORE_FILES 3
-
-struct cpu_chart {
- const char *id;
-
- RRDSET *st;
- RRDDIM *rd_user;
- RRDDIM *rd_nice;
- RRDDIM *rd_system;
- RRDDIM *rd_idle;
- RRDDIM *rd_iowait;
- RRDDIM *rd_irq;
- RRDDIM *rd_softirq;
- RRDDIM *rd_steal;
- RRDDIM *rd_guest;
- RRDDIM *rd_guest_nice;
-
- struct per_core_single_number_file files[PER_CORE_FILES];
-};
-
-static int keep_per_core_fds_open = CONFIG_BOOLEAN_YES;
-
-static int read_per_core_files(struct cpu_chart *all_cpu_charts, size_t len, size_t index) {
- char buf[50 + 1];
- size_t x, files_read = 0, files_nonzero = 0;
-
- for(x = 0; x < len ; x++) {
- struct per_core_single_number_file *f = &all_cpu_charts[x].files[index];
-
- f->found = 0;
-
- if(unlikely(!f->filename))
- continue;
-
- if(unlikely(f->fd == -1)) {
- f->fd = open(f->filename, O_RDONLY);
- if (unlikely(f->fd == -1)) {
- error("Cannot open file '%s'", f->filename);
- continue;
- }
- }
-
- ssize_t ret = read(f->fd, buf, 50);
- if(unlikely(ret < 0)) {
- // cannot read that file
-
- error("Cannot read file '%s'", f->filename);
- close(f->fd);
- f->fd = -1;
- continue;
- }
- else {
- // successful read
-
- // terminate the buffer
- buf[ret] = '\0';
-
- if(unlikely(keep_per_core_fds_open != CONFIG_BOOLEAN_YES)) {
- close(f->fd);
- f->fd = -1;
- }
- else if(lseek(f->fd, 0, SEEK_SET) == -1) {
- error("Cannot seek in file '%s'", f->filename);
- close(f->fd);
- f->fd = -1;
- }
- }
-
- files_read++;
- f->found = 1;
-
- f->value = str2ll(buf, NULL);
- // info("read '%s', parsed as " COLLECTED_NUMBER_FORMAT, buf, f->value);
- if(likely(f->value != 0))
- files_nonzero++;
- }
-
- if(files_read == 0)
- return -1;
-
- if(files_nonzero == 0)
- return 0;
-
- return (int)files_nonzero;
-}
-
-static void chart_per_core_files(struct cpu_chart *all_cpu_charts, size_t len, size_t index, RRDSET *st, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm) {
- size_t x;
- for(x = 0; x < len ; x++) {
- struct per_core_single_number_file *f = &all_cpu_charts[x].files[index];
-
- if(unlikely(!f->found))
- continue;
-
- if(unlikely(!f->rd))
- f->rd = rrddim_add(st, all_cpu_charts[x].id, NULL, multiplier, divisor, algorithm);
-
- rrddim_set_by_pointer(st, f->rd, f->value);
- }
-}
-
-int do_proc_stat(int update_every, usec_t dt) {
- (void)dt;
-
- static struct cpu_chart *all_cpu_charts = NULL;
- static size_t all_cpu_charts_size = 0;
- static procfile *ff = NULL;
- static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1, do_core_throttle_count = -1, do_package_throttle_count = -1, do_scaling_cur_freq = -1;
- static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
- static char *core_throttle_count_filename = NULL, *package_throttle_count_filename = NULL, *scaling_cur_freq_filename = NULL;
-
- if(unlikely(do_cpu == -1)) {
- do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", CONFIG_BOOLEAN_YES);
- do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", CONFIG_BOOLEAN_YES);
- do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", CONFIG_BOOLEAN_YES);
- do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", CONFIG_BOOLEAN_YES);
- do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", CONFIG_BOOLEAN_YES);
- do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", CONFIG_BOOLEAN_YES);
-
- // give sane defaults based on the number of processors
- if(processors > 50) {
- // the system has too many processors
- keep_per_core_fds_open = CONFIG_BOOLEAN_NO;
- do_core_throttle_count = CONFIG_BOOLEAN_NO;
- do_package_throttle_count = CONFIG_BOOLEAN_NO;
- do_scaling_cur_freq = CONFIG_BOOLEAN_NO;
- }
- else {
- // the system has a reasonable number of processors
- keep_per_core_fds_open = CONFIG_BOOLEAN_YES;
- do_core_throttle_count = CONFIG_BOOLEAN_AUTO;
- do_package_throttle_count = CONFIG_BOOLEAN_NO;
- do_scaling_cur_freq = CONFIG_BOOLEAN_NO;
- }
-
- keep_per_core_fds_open = config_get_boolean("plugin:proc:/proc/stat", "keep per core files open", keep_per_core_fds_open);
- do_core_throttle_count = config_get_boolean_ondemand("plugin:proc:/proc/stat", "core_throttle_count", do_core_throttle_count);
- do_package_throttle_count = config_get_boolean_ondemand("plugin:proc:/proc/stat", "package_throttle_count", do_package_throttle_count);
- do_scaling_cur_freq = config_get_boolean_ondemand("plugin:proc:/proc/stat", "scaling_cur_freq", do_scaling_cur_freq);
-
- hash_intr = simple_hash("intr");
- hash_ctxt = simple_hash("ctxt");
- hash_processes = simple_hash("processes");
- hash_procs_running = simple_hash("procs_running");
- hash_procs_blocked = simple_hash("procs_blocked");
-
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/thermal_throttle/core_throttle_count");
- core_throttle_count_filename = config_get("plugin:proc:/proc/stat", "core_throttle_count filename to monitor", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/thermal_throttle/package_throttle_count");
- package_throttle_count_filename = config_get("plugin:proc:/proc/stat", "package_throttle_count filename to monitor", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/cpufreq/scaling_cur_freq");
- scaling_cur_freq_filename = config_get("plugin:proc:/proc/stat", "scaling_cur_freq filename to monitor", filename);
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/stat");
- ff = procfile_open(config_get("plugin:proc:/proc/stat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
- size_t words;
-
- unsigned long long processes = 0, running = 0 , blocked = 0;
-
- for(l = 0; l < lines ;l++) {
- char *row_key = procfile_lineword(ff, l, 0);
- uint32_t hash = simple_hash(row_key);
-
- // faster strncmp(row_key, "cpu", 3) == 0
- if(likely(row_key[0] == 'c' && row_key[1] == 'p' && row_key[2] == 'u')) {
- words = procfile_linewords(ff, l);
- if(unlikely(words < 9)) {
- error("Cannot read /proc/stat cpu line. Expected 9 params, read %zu.", words);
- continue;
- }
-
- size_t core = (row_key[3] == '\0') ? 0 : str2ul(&row_key[3]) + 1;
-
- if(likely((core == 0 && do_cpu) || (core > 0 && do_cpu_cores))) {
- char *id;
- unsigned long long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
-
- id = row_key;
- user = str2ull(procfile_lineword(ff, l, 1));
- nice = str2ull(procfile_lineword(ff, l, 2));
- system = str2ull(procfile_lineword(ff, l, 3));
- idle = str2ull(procfile_lineword(ff, l, 4));
- iowait = str2ull(procfile_lineword(ff, l, 5));
- irq = str2ull(procfile_lineword(ff, l, 6));
- softirq = str2ull(procfile_lineword(ff, l, 7));
- steal = str2ull(procfile_lineword(ff, l, 8));
-
- guest = str2ull(procfile_lineword(ff, l, 9));
- user -= guest;
-
- guest_nice = str2ull(procfile_lineword(ff, l, 10));
- nice -= guest_nice;
-
- char *title, *type, *context, *family;
- long priority;
-
- if(core >= all_cpu_charts_size) {
- size_t old_cpu_charts_size = all_cpu_charts_size;
- all_cpu_charts_size = core + 1;
- all_cpu_charts = reallocz(all_cpu_charts, sizeof(struct cpu_chart) * all_cpu_charts_size);
- memset(&all_cpu_charts[old_cpu_charts_size], 0, sizeof(struct cpu_chart) * (all_cpu_charts_size - old_cpu_charts_size));
- }
- struct cpu_chart *cpu_chart = &all_cpu_charts[core];
-
- if(unlikely(!cpu_chart->st)) {
- cpu_chart->id = strdupz(id);
-
- if(core == 0) {
- title = "Total CPU utilization";
- type = "system";
- context = "system.cpu";
- family = id;
- priority = 100;
- }
- else {
- title = "Core utilization";
- type = "cpu";
- context = "cpu.cpu";
- family = "utilization";
- priority = 1000;
-
- // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
- // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/stats/time_in_state
-
- char filename[FILENAME_MAX + 1];
- struct stat stbuf;
-
- if(do_core_throttle_count != CONFIG_BOOLEAN_NO) {
- snprintfz(filename, FILENAME_MAX, core_throttle_count_filename, id);
- if (stat(filename, &stbuf) == 0) {
- cpu_chart->files[CORE_THROTTLE_COUNT_INDEX].filename = strdupz(filename);
- cpu_chart->files[CORE_THROTTLE_COUNT_INDEX].fd = -1;
- do_core_throttle_count = CONFIG_BOOLEAN_YES;
- }
- }
-
- if(do_package_throttle_count != CONFIG_BOOLEAN_NO) {
- snprintfz(filename, FILENAME_MAX, package_throttle_count_filename, id);
- if (stat(filename, &stbuf) == 0) {
- cpu_chart->files[PACKAGE_THROTTLE_COUNT_INDEX].filename = strdupz(filename);
- cpu_chart->files[PACKAGE_THROTTLE_COUNT_INDEX].fd = -1;
- do_package_throttle_count = CONFIG_BOOLEAN_YES;
- }
- }
-
- if(do_scaling_cur_freq != CONFIG_BOOLEAN_NO) {
- snprintfz(filename, FILENAME_MAX, scaling_cur_freq_filename, id);
- if (stat(filename, &stbuf) == 0) {
- cpu_chart->files[SCALING_CUR_FREQ_INDEX].filename = strdupz(filename);
- cpu_chart->files[SCALING_CUR_FREQ_INDEX].fd = -1;
- do_scaling_cur_freq = CONFIG_BOOLEAN_YES;
- }
- }
- }
-
- cpu_chart->st = rrdset_create_localhost(
- type
- , id
- , NULL
- , family
- , context
- , title
- , "percentage"
- , "proc"
- , "stat"
- , priority
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- long multiplier = 1;
- long divisor = 1; // sysconf(_SC_CLK_TCK);
-
- cpu_chart->rd_guest_nice = rrddim_add(cpu_chart->st, "guest_nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_guest = rrddim_add(cpu_chart->st, "guest", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_steal = rrddim_add(cpu_chart->st, "steal", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_softirq = rrddim_add(cpu_chart->st, "softirq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_irq = rrddim_add(cpu_chart->st, "irq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_user = rrddim_add(cpu_chart->st, "user", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_system = rrddim_add(cpu_chart->st, "system", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_nice = rrddim_add(cpu_chart->st, "nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_iowait = rrddim_add(cpu_chart->st, "iowait", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- cpu_chart->rd_idle = rrddim_add(cpu_chart->st, "idle", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rrddim_hide(cpu_chart->st, "idle");
- }
- else rrdset_next(cpu_chart->st);
-
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_user, user);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_nice, nice);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_system, system);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_idle, idle);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_iowait, iowait);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_irq, irq);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_softirq, softirq);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_steal, steal);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest, guest);
- rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest_nice, guest_nice);
- rrdset_done(cpu_chart->st);
- }
- }
- else if(unlikely(hash == hash_intr && strcmp(row_key, "intr") == 0)) {
- if(likely(do_interrupts)) {
- static RRDSET *st_intr = NULL;
- static RRDDIM *rd_interrupts = NULL;
- unsigned long long value = str2ull(procfile_lineword(ff, l, 1));
-
- if(unlikely(!st_intr)) {
- st_intr = rrdset_create_localhost(
- "system"
- , "intr"
- , NULL
- , "interrupts"
- , NULL
- , "CPU Interrupts"
- , "interrupts/s"
- , "proc"
- , "stat"
- , 900
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL);
-
- rd_interrupts = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_intr);
-
- rrddim_set_by_pointer(st_intr, rd_interrupts, value);
- rrdset_done(st_intr);
- }
- }
- else if(unlikely(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0)) {
- if(likely(do_context)) {
- static RRDSET *st_ctxt = NULL;
- static RRDDIM *rd_switches = NULL;
- unsigned long long value = str2ull(procfile_lineword(ff, l, 1));
-
- if(unlikely(!st_ctxt)) {
- st_ctxt = rrdset_create_localhost(
- "system"
- , "ctxt"
- , NULL
- , "processes"
- , NULL
- , "CPU Context Switches"
- , "context switches/s"
- , "proc"
- , "stat"
- , 800
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_switches = rrddim_add(st_ctxt, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_ctxt);
-
- rrddim_set_by_pointer(st_ctxt, rd_switches, value);
- rrdset_done(st_ctxt);
- }
- }
- else if(unlikely(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0)) {
- processes = str2ull(procfile_lineword(ff, l, 1));
- }
- else if(unlikely(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0)) {
- running = str2ull(procfile_lineword(ff, l, 1));
- }
- else if(unlikely(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0)) {
- blocked = str2ull(procfile_lineword(ff, l, 1));
- }
- }
-
- // --------------------------------------------------------------------
-
- if(likely(do_forks)) {
- static RRDSET *st_forks = NULL;
- static RRDDIM *rd_started = NULL;
-
- if(unlikely(!st_forks)) {
- st_forks = rrdset_create_localhost(
- "system"
- , "forks"
- , NULL
- , "processes"
- , NULL
- , "Started Processes"
- , "processes/s"
- , "proc"
- , "stat"
- , 700
- , update_every
- , RRDSET_TYPE_LINE
- );
- rrdset_flag_set(st_forks, RRDSET_FLAG_DETAIL);
-
- rd_started = rrddim_add(st_forks, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_forks);
-
- rrddim_set_by_pointer(st_forks, rd_started, processes);
- rrdset_done(st_forks);
- }
-
- // --------------------------------------------------------------------
-
- if(likely(do_processes)) {
- static RRDSET *st_processes = NULL;
- static RRDDIM *rd_running = NULL;
- static RRDDIM *rd_blocked = NULL;
-
- if(unlikely(!st_processes)) {
- st_processes = rrdset_create_localhost(
- "system"
- , "processes"
- , NULL
- , "processes"
- , NULL
- , "System Processes"
- , "processes"
- , "proc"
- , "stat"
- , 600
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_running = rrddim_add(st_processes, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_blocked = rrddim_add(st_processes, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st_processes);
-
- rrddim_set_by_pointer(st_processes, rd_running, running);
- rrddim_set_by_pointer(st_processes, rd_blocked, blocked);
- rrdset_done(st_processes);
- }
-
- if(likely(all_cpu_charts_size > 1)) {
- if(likely(do_core_throttle_count != CONFIG_BOOLEAN_NO)) {
- int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX);
- if(likely(r != -1 && (do_core_throttle_count == CONFIG_BOOLEAN_YES || r > 0))) {
- do_core_throttle_count = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_core_throttle_count = NULL;
-
- if (unlikely(!st_core_throttle_count))
- st_core_throttle_count = rrdset_create_localhost(
- "cpu"
- , "core_throttling"
- , NULL
- , "throttling"
- , "cpu.core_throttling"
- , "Core Thermal Throttling Events"
- , "events/s"
- , "proc"
- , "stat"
- , 5001
- , update_every
- , RRDSET_TYPE_LINE
- );
- else
- rrdset_next(st_core_throttle_count);
-
- chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX, st_core_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrdset_done(st_core_throttle_count);
- }
- }
-
- if(likely(do_package_throttle_count != CONFIG_BOOLEAN_NO)) {
- int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX);
- if(likely(r != -1 && (do_package_throttle_count == CONFIG_BOOLEAN_YES || r > 0))) {
- do_package_throttle_count = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_package_throttle_count = NULL;
-
- if(unlikely(!st_package_throttle_count))
- st_package_throttle_count = rrdset_create_localhost(
- "cpu"
- , "package_throttling"
- , NULL
- , "throttling"
- , "cpu.package_throttling"
- , "Package Thermal Throttling Events"
- , "events/s"
- , "proc"
- , "stat"
- , 5002
- , update_every
- , RRDSET_TYPE_LINE
- );
- else
- rrdset_next(st_package_throttle_count);
-
- chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX, st_package_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrdset_done(st_package_throttle_count);
- }
- }
-
- if(likely(do_scaling_cur_freq != CONFIG_BOOLEAN_NO)) {
- int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, SCALING_CUR_FREQ_INDEX);
- if(likely(r != -1 && (do_scaling_cur_freq == CONFIG_BOOLEAN_YES || r > 0))) {
- do_scaling_cur_freq = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_scaling_cur_freq = NULL;
-
- if(unlikely(!st_scaling_cur_freq))
- st_scaling_cur_freq = rrdset_create_localhost(
- "cpu"
- , "scaling_cur_freq"
- , NULL
- , "cpufreq"
- , "cpu.scaling_cur_freq"
- , "Per CPU Core, Current CPU Scaling Frequency"
- , "MHz"
- , "proc"
- , "stat"
- , 5003
- , update_every
- , RRDSET_TYPE_LINE
- );
- else
- rrdset_next(st_scaling_cur_freq);
-
- chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, SCALING_CUR_FREQ_INDEX, st_scaling_cur_freq, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- rrdset_done(st_scaling_cur_freq);
- }
- }
- }
-
- return 0;
-}
diff --git a/src/proc_sys_kernel_random_entropy_avail.c b/src/proc_sys_kernel_random_entropy_avail.c
deleted file mode 100644
index ca4d7657c..000000000
--- a/src/proc_sys_kernel_random_entropy_avail.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "common.h"
-
-int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sys/kernel/random/entropy_avail");
- ff = procfile_open(config_get("plugin:proc:/proc/sys/kernel/random/entropy_avail", "filename to monitor", filename), "", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- unsigned long long entropy = str2ull(procfile_lineword(ff, 0, 0));
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if(unlikely(!st)) {
- st = rrdset_create_localhost(
- "system"
- , "entropy"
- , NULL
- , "entropy"
- , NULL
- , "Available Entropy"
- , "entropy"
- , "proc"
- , "sys/kernel/random/entropy_avail"
- , 1000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "entropy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, entropy);
- rrdset_done(st);
-
- return 0;
-}
diff --git a/src/proc_uptime.c b/src/proc_uptime.c
deleted file mode 100644
index 259de4760..000000000
--- a/src/proc_uptime.c
+++ /dev/null
@@ -1,103 +0,0 @@
-#include "common.h"
-
-static inline collected_number uptime_from_boottime(void) {
-#ifdef CLOCK_BOOTTIME_IS_AVAILABLE
- return now_boottime_usec() / 1000;
-#else
- error("uptime cannot be read from CLOCK_BOOTTIME on this system.");
- return 0;
-#endif
-}
-
-static procfile *read_proc_uptime_ff = NULL;
-static inline collected_number read_proc_uptime(void) {
- if(unlikely(!read_proc_uptime_ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/uptime");
-
- read_proc_uptime_ff = procfile_open(config_get("plugin:proc:/proc/uptime", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!read_proc_uptime_ff)) return 0;
- }
-
- read_proc_uptime_ff = procfile_readall(read_proc_uptime_ff);
- if(unlikely(!read_proc_uptime_ff)) return 0;
-
- if(unlikely(procfile_lines(read_proc_uptime_ff) < 1)) {
- error("/proc/uptime has no lines.");
- return 0;
- }
- if(unlikely(procfile_linewords(read_proc_uptime_ff, 0) < 1)) {
- error("/proc/uptime has less than 1 word in it.");
- return 0;
- }
-
- return (collected_number)(strtold(procfile_lineword(read_proc_uptime_ff, 0, 0), NULL) * 1000.0);
-}
-
-int do_proc_uptime(int update_every, usec_t dt) {
- (void)dt;
-
- static int use_boottime = -1;
-
- if(unlikely(use_boottime == -1)) {
- collected_number uptime_boottime = uptime_from_boottime();
- collected_number uptime_proc = read_proc_uptime();
-
- long long delta = (long long)uptime_boottime - (long long)uptime_proc;
- if(delta < 0) delta = -delta;
-
- if(delta <= 1000 && uptime_boottime != 0) {
- procfile_close(read_proc_uptime_ff);
- info("Using now_boottime_usec() for uptime (dt is %lld ms)", delta);
- use_boottime = 1;
- }
- else if(uptime_proc != 0) {
- info("Using /proc/uptime for uptime (dt is %lld ms)", delta);
- use_boottime = 0;
- }
- else {
- error("Cannot find any way to read uptime on this system.");
- return 1;
- }
- }
-
- collected_number uptime;
- if(use_boottime)
- uptime = uptime_from_boottime();
- else
- uptime = read_proc_uptime();
-
-
- // --------------------------------------------------------------------
-
- static RRDSET *st = NULL;
- static RRDDIM *rd = NULL;
-
- if(unlikely(!st)) {
-
- st = rrdset_create_localhost(
- "system"
- , "uptime"
- , NULL
- , "uptime"
- , NULL
- , "System Uptime"
- , "seconds"
- , "proc"
- , "uptime"
- , 1000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd = rrddim_add(st, "uptime", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st);
-
- rrddim_set_by_pointer(st, rd, uptime);
-
- rrdset_done(st);
-
- return 0;
-}
diff --git a/src/proc_vmstat.c b/src/proc_vmstat.c
deleted file mode 100644
index 52e88d888..000000000
--- a/src/proc_vmstat.c
+++ /dev/null
@@ -1,255 +0,0 @@
-#include "common.h"
-
-int do_proc_vmstat(int update_every, usec_t dt) {
- (void)dt;
-
- static procfile *ff = NULL;
- static int do_swapio = -1, do_io = -1, do_pgfaults = -1, do_numa = -1;
- static int has_numa = -1;
-
- static ARL_BASE *arl_base = NULL;
- static unsigned long long numa_foreign = 0ULL;
- static unsigned long long numa_hint_faults = 0ULL;
- static unsigned long long numa_hint_faults_local = 0ULL;
- static unsigned long long numa_huge_pte_updates = 0ULL;
- static unsigned long long numa_interleave = 0ULL;
- static unsigned long long numa_local = 0ULL;
- static unsigned long long numa_other = 0ULL;
- static unsigned long long numa_pages_migrated = 0ULL;
- static unsigned long long numa_pte_updates = 0ULL;
- static unsigned long long pgfault = 0ULL;
- static unsigned long long pgmajfault = 0ULL;
- static unsigned long long pgpgin = 0ULL;
- static unsigned long long pgpgout = 0ULL;
- static unsigned long long pswpin = 0ULL;
- static unsigned long long pswpout = 0ULL;
-
- if(unlikely(!arl_base)) {
- do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_BOOLEAN_AUTO);
- do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
- do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);
- do_numa = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_BOOLEAN_AUTO);
-
-
- arl_base = arl_create("vmstat", NULL, 60);
- arl_expect(arl_base, "pgfault", &pgfault);
- arl_expect(arl_base, "pgmajfault", &pgmajfault);
- arl_expect(arl_base, "pgpgin", &pgpgin);
- arl_expect(arl_base, "pgpgout", &pgpgout);
- arl_expect(arl_base, "pswpin", &pswpin);
- arl_expect(arl_base, "pswpout", &pswpout);
-
- if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && get_numa_node_count() >= 2)) {
- arl_expect(arl_base, "numa_foreign", &numa_foreign);
- arl_expect(arl_base, "numa_hint_faults_local", &numa_hint_faults_local);
- arl_expect(arl_base, "numa_hint_faults", &numa_hint_faults);
- arl_expect(arl_base, "numa_huge_pte_updates", &numa_huge_pte_updates);
- arl_expect(arl_base, "numa_interleave", &numa_interleave);
- arl_expect(arl_base, "numa_local", &numa_local);
- arl_expect(arl_base, "numa_other", &numa_other);
- arl_expect(arl_base, "numa_pages_migrated", &numa_pages_migrated);
- arl_expect(arl_base, "numa_pte_updates", &numa_pte_updates);
- }
- else {
- // Do not expect numa metrics when they are not needed.
- // By not adding them, the ARL will stop processing the file
- // when all the expected metrics are collected.
- // Also ARL will not parse their values.
- has_numa = 0;
- do_numa = CONFIG_BOOLEAN_NO;
- }
- }
-
- if(unlikely(!ff)) {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/vmstat");
- ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) return 1;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
-
- size_t lines = procfile_lines(ff), l;
-
- arl_begin(arl_base);
- for(l = 0; l < lines ;l++) {
- size_t words = procfile_linewords(ff, l);
- if(unlikely(words < 2)) {
- if(unlikely(words)) error("Cannot read /proc/vmstat line %zu. Expected 2 params, read %zu.", l, words);
- continue;
- }
-
- if(unlikely(arl_check(arl_base,
- procfile_lineword(ff, l, 0),
- procfile_lineword(ff, l, 1)))) break;
- }
-
- // --------------------------------------------------------------------
-
- if(pswpin || pswpout || do_swapio == CONFIG_BOOLEAN_YES) {
- do_swapio = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_swapio = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_swapio)) {
- st_swapio = rrdset_create_localhost(
- "system"
- , "swapio"
- , NULL
- , "swap"
- , NULL
- , "Swap I/O"
- , "kilobytes/s"
- , "proc"
- , "vmstat"
- , 250
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_swapio);
-
- rrddim_set_by_pointer(st_swapio, rd_in, pswpin);
- rrddim_set_by_pointer(st_swapio, rd_out, pswpout);
- rrdset_done(st_swapio);
- }
-
- // --------------------------------------------------------------------
-
- if(do_io) {
- static RRDSET *st_io = NULL;
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
-
- if(unlikely(!st_io)) {
- st_io = rrdset_create_localhost(
- "system"
- , "pgpgio"
- , NULL
- , "disk"
- , NULL
- , "Memory Paged from/to disk"
- , "kilobytes/s"
- , "proc"
- , "vmstat"
- , 151
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_in = rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_io);
-
- rrddim_set_by_pointer(st_io, rd_in, pgpgin);
- rrddim_set_by_pointer(st_io, rd_out, pgpgout);
- rrdset_done(st_io);
- }
-
- // --------------------------------------------------------------------
-
- if(do_pgfaults) {
- static RRDSET *st_pgfaults = NULL;
- static RRDDIM *rd_minor = NULL, *rd_major = NULL;
-
- if(unlikely(!st_pgfaults)) {
- st_pgfaults = rrdset_create_localhost(
- "mem"
- , "pgfaults"
- , NULL
- , "system"
- , NULL
- , "Memory Page Faults"
- , "page faults/s"
- , "proc"
- , "vmstat"
- , NETDATA_CHART_PRIO_MEM_SYSTEM_PGFAULTS
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_pgfaults, RRDSET_FLAG_DETAIL);
-
- rd_minor = rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_major = rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_pgfaults);
-
- rrddim_set_by_pointer(st_pgfaults, rd_minor, pgfault);
- rrddim_set_by_pointer(st_pgfaults, rd_major, pgmajfault);
- rrdset_done(st_pgfaults);
- }
-
- // --------------------------------------------------------------------
-
- // Ondemand criteria for NUMA. Since this won't change at run time, we
- // check it only once. We check whether the node count is >= 2 because
- // single-node systems have uninteresting statistics (since all accesses
- // are local).
- if(unlikely(has_numa == -1))
-
- has_numa = (numa_local || numa_foreign || numa_interleave || numa_other || numa_pte_updates ||
- numa_huge_pte_updates || numa_hint_faults || numa_hint_faults_local || numa_pages_migrated) ? 1 : 0;
-
- if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && has_numa)) {
- do_numa = CONFIG_BOOLEAN_YES;
-
- static RRDSET *st_numa = NULL;
- static RRDDIM *rd_local = NULL, *rd_foreign = NULL, *rd_interleave = NULL, *rd_other = NULL, *rd_pte_updates = NULL, *rd_huge_pte_updates = NULL, *rd_hint_faults = NULL, *rd_hint_faults_local = NULL, *rd_pages_migrated = NULL;
-
- if(unlikely(!st_numa)) {
- st_numa = rrdset_create_localhost(
- "mem"
- , "numa"
- , NULL
- , "numa"
- , NULL
- , "NUMA events"
- , "events/s"
- , "proc"
- , "vmstat"
- , NETDATA_CHART_PRIO_MEM_NUMA
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(st_numa, RRDSET_FLAG_DETAIL);
-
- // These depend on CONFIG_NUMA in the kernel.
- rd_local = rrddim_add(st_numa, "local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_foreign = rrddim_add(st_numa, "foreign", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_interleave = rrddim_add(st_numa, "interleave", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_other = rrddim_add(st_numa, "other", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- // The following stats depend on CONFIG_NUMA_BALANCING in the
- // kernel.
- rd_pte_updates = rrddim_add(st_numa, "pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_huge_pte_updates = rrddim_add(st_numa, "huge_pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_hint_faults = rrddim_add(st_numa, "hint_faults", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_hint_faults_local = rrddim_add(st_numa, "hint_faults_local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_pages_migrated = rrddim_add(st_numa, "pages_migrated", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(st_numa);
-
- rrddim_set_by_pointer(st_numa, rd_local, numa_local);
- rrddim_set_by_pointer(st_numa, rd_foreign, numa_foreign);
- rrddim_set_by_pointer(st_numa, rd_interleave, numa_interleave);
- rrddim_set_by_pointer(st_numa, rd_other, numa_other);
-
- rrddim_set_by_pointer(st_numa, rd_pte_updates, numa_pte_updates);
- rrddim_set_by_pointer(st_numa, rd_huge_pte_updates, numa_huge_pte_updates);
- rrddim_set_by_pointer(st_numa, rd_hint_faults, numa_hint_faults);
- rrddim_set_by_pointer(st_numa, rd_hint_faults_local, numa_hint_faults_local);
- rrddim_set_by_pointer(st_numa, rd_pages_migrated, numa_pages_migrated);
-
- rrdset_done(st_numa);
- }
-
- return 0;
-}
-
diff --git a/src/procfile.c b/src/procfile.c
deleted file mode 100644
index 044f975b5..000000000
--- a/src/procfile.c
+++ /dev/null
@@ -1,468 +0,0 @@
-#include "common.h"
-#include "procfile.h"
-
-#define PF_PREFIX "PROCFILE"
-
-#define PFWORDS_INCREASE_STEP 200
-#define PFLINES_INCREASE_STEP 10
-#define PROCFILE_INCREMENT_BUFFER 512
-
-int procfile_adaptive_initial_allocation = 0;
-
-// if adaptive allocation is set, these store the
-// max values we have seen so far
-size_t procfile_max_lines = PFLINES_INCREASE_STEP;
-size_t procfile_max_words = PFWORDS_INCREASE_STEP;
-size_t procfile_max_allocation = PROCFILE_INCREMENT_BUFFER;
-
-
-// ----------------------------------------------------------------------------
-
-char *procfile_filename(procfile *ff) {
- if(ff->filename[0]) return ff->filename;
-
- char buffer[FILENAME_MAX + 1];
- snprintfz(buffer, FILENAME_MAX, "/proc/self/fd/%d", ff->fd);
-
- ssize_t l = readlink(buffer, ff->filename, FILENAME_MAX);
- if(unlikely(l == -1))
- snprintfz(ff->filename, FILENAME_MAX, "unknown filename for fd %d", ff->fd);
- else
- ff->filename[l] = '\0';
-
- // on non-linux systems, something like this will be needed
- // fcntl(ff->fd, F_GETPATH, ff->filename)
-
- return ff->filename;
-}
-
-// ----------------------------------------------------------------------------
-// An array of words
-
-static inline void pfwords_add(procfile *ff, char *str) {
- // debug(D_PROCFILE, PF_PREFIX ": adding word No %d: '%s'", fw->len, str);
-
- pfwords *fw = ff->words;
- if(unlikely(fw->len == fw->size)) {
- // debug(D_PROCFILE, PF_PREFIX ": expanding words");
-
- ff->words = fw = reallocz(fw, sizeof(pfwords) + (fw->size + PFWORDS_INCREASE_STEP) * sizeof(char *));
- fw->size += PFWORDS_INCREASE_STEP;
- }
-
- fw->words[fw->len++] = str;
-}
-
-NEVERNULL
-static inline pfwords *pfwords_new(void) {
- // debug(D_PROCFILE, PF_PREFIX ": initializing words");
-
- size_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFWORDS_INCREASE_STEP;
-
- pfwords *new = mallocz(sizeof(pfwords) + size * sizeof(char *));
- new->len = 0;
- new->size = size;
- return new;
-}
-
-static inline void pfwords_reset(pfwords *fw) {
- // debug(D_PROCFILE, PF_PREFIX ": reseting words");
- fw->len = 0;
-}
-
-static inline void pfwords_free(pfwords *fw) {
- // debug(D_PROCFILE, PF_PREFIX ": freeing words");
-
- freez(fw);
-}
-
-
-// ----------------------------------------------------------------------------
-// An array of lines
-
-NEVERNULL
-static inline size_t *pflines_add(procfile *ff) {
- // debug(D_PROCFILE, PF_PREFIX ": adding line %d at word %d", fl->len, first_word);
-
- pflines *fl = ff->lines;
- if(unlikely(fl->len == fl->size)) {
- // debug(D_PROCFILE, PF_PREFIX ": expanding lines");
-
- ff->lines = fl = reallocz(fl, sizeof(pflines) + (fl->size + PFLINES_INCREASE_STEP) * sizeof(ffline));
- fl->size += PFLINES_INCREASE_STEP;
- }
-
- ffline *ffl = &fl->lines[fl->len++];
- ffl->words = 0;
- ffl->first = ff->words->len;
-
- return &ffl->words;
-}
-
-NEVERNULL
-static inline pflines *pflines_new(void) {
- // debug(D_PROCFILE, PF_PREFIX ": initializing lines");
-
- size_t size = (unlikely(procfile_adaptive_initial_allocation)) ? procfile_max_words : PFLINES_INCREASE_STEP;
-
- pflines *new = mallocz(sizeof(pflines) + size * sizeof(ffline));
- new->len = 0;
- new->size = size;
- return new;
-}
-
-static inline void pflines_reset(pflines *fl) {
- // debug(D_PROCFILE, PF_PREFIX ": reseting lines");
-
- fl->len = 0;
-}
-
-static inline void pflines_free(pflines *fl) {
- // debug(D_PROCFILE, PF_PREFIX ": freeing lines");
-
- freez(fl);
-}
-
-
-// ----------------------------------------------------------------------------
-// The procfile
-
-void procfile_close(procfile *ff) {
- if(unlikely(!ff)) return;
-
- debug(D_PROCFILE, PF_PREFIX ": Closing file '%s'", procfile_filename(ff));
-
- if(likely(ff->lines)) pflines_free(ff->lines);
- if(likely(ff->words)) pfwords_free(ff->words);
-
- if(likely(ff->fd != -1)) close(ff->fd);
- freez(ff);
-}
-
-NOINLINE
-static void procfile_parser(procfile *ff) {
- // debug(D_PROCFILE, PF_PREFIX ": Parsing file '%s'", ff->filename);
-
- char *s = ff->data // our current position
- , *e = &ff->data[ff->len] // the terminating null
- , *t = ff->data; // the first character of a word (or quoted / parenthesized string)
-
- // the look up array to find our type of character
- PF_CHAR_TYPE *separators = ff->separators;
-
- char quote = 0; // the quote character - only when in quoted string
- size_t opened = 0; // counts the number of open parenthesis
-
- size_t *line_words = pflines_add(ff);
-
- while(s < e) {
- PF_CHAR_TYPE ct = separators[(unsigned char)(*s)];
-
- // this is faster than a switch()
- // read more here: http://lazarenko.me/switch/
- if(likely(ct == PF_CHAR_IS_WORD)) {
- s++;
- }
- else if(likely(ct == PF_CHAR_IS_SEPARATOR)) {
- if(!quote && !opened) {
- if (s != t) {
- // separator, but we have word before it
- *s = '\0';
- pfwords_add(ff, t);
- (*line_words)++;
- t = ++s;
- }
- else {
- // separator at the beginning
- // skip it
- t = ++s;
- }
- }
- else {
- // we are inside a quote or parenthesized string
- s++;
- }
- }
- else if(likely(ct == PF_CHAR_IS_NEWLINE)) {
- // end of line
-
- *s = '\0';
- pfwords_add(ff, t);
- (*line_words)++;
- t = ++s;
-
- // debug(D_PROCFILE, PF_PREFIX ": ended line %d with %d words", l, ff->lines->lines[l].words);
-
- line_words = pflines_add(ff);
- }
- else if(likely(ct == PF_CHAR_IS_QUOTE)) {
- if(unlikely(!quote && s == t)) {
- // quote opened at the beginning
- quote = *s;
- t = ++s;
- }
- else if(unlikely(quote && quote == *s)) {
- // quote closed
- quote = 0;
-
- *s = '\0';
- pfwords_add(ff, t);
- (*line_words)++;
- t = ++s;
- }
- else
- s++;
- }
- else if(likely(ct == PF_CHAR_IS_OPEN)) {
- if(s == t) {
- opened++;
- t = ++s;
- }
- else if(opened) {
- opened++;
- s++;
- }
- else
- s++;
- }
- else if(likely(ct == PF_CHAR_IS_CLOSE)) {
- if(opened) {
- opened--;
-
- if(!opened) {
- *s = '\0';
- pfwords_add(ff, t);
- (*line_words)++;
- t = ++s;
- }
- else
- s++;
- }
- else
- s++;
- }
- else
- fatal("Internal Error: procfile_readall() does not handle all the cases.");
- }
-
- if(likely(s > t && t < e)) {
- // the last word
- if(unlikely(ff->len >= ff->size)) {
- // we are going to loose the last byte
- s = &ff->data[ff->size - 1];
- }
-
- *s = '\0';
- pfwords_add(ff, t);
- (*line_words)++;
- // t = ++s;
- }
-}
-
-procfile *procfile_readall(procfile *ff) {
- // debug(D_PROCFILE, PF_PREFIX ": Reading file '%s'.", ff->filename);
-
- ff->len = 0; // zero the used size
- ssize_t r = 1; // read at least once
- while(r > 0) {
- ssize_t s = ff->len;
- ssize_t x = ff->size - s;
-
- if(unlikely(!x)) {
- debug(D_PROCFILE, PF_PREFIX ": Expanding data buffer for file '%s'.", procfile_filename(ff));
- ff = reallocz(ff, sizeof(procfile) + ff->size + PROCFILE_INCREMENT_BUFFER);
- ff->size += PROCFILE_INCREMENT_BUFFER;
- }
-
- debug(D_PROCFILE, "Reading file '%s', from position %zd with length %zd", procfile_filename(ff), s, (ssize_t)(ff->size - s));
- r = read(ff->fd, &ff->data[s], ff->size - s);
- if(unlikely(r == -1)) {
- if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot read from file '%s' on fd %d", procfile_filename(ff), ff->fd);
- procfile_close(ff);
- return NULL;
- }
-
- ff->len += r;
- }
-
- // debug(D_PROCFILE, "Rewinding file '%s'", ff->filename);
- if(unlikely(lseek(ff->fd, 0, SEEK_SET) == -1)) {
- if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot rewind on file '%s'.", procfile_filename(ff));
- procfile_close(ff);
- return NULL;
- }
-
- pflines_reset(ff->lines);
- pfwords_reset(ff->words);
- procfile_parser(ff);
-
- if(unlikely(procfile_adaptive_initial_allocation)) {
- if(unlikely(ff->len > procfile_max_allocation)) procfile_max_allocation = ff->len;
- if(unlikely(ff->lines->len > procfile_max_lines)) procfile_max_lines = ff->lines->len;
- if(unlikely(ff->words->len > procfile_max_words)) procfile_max_words = ff->words->len;
- }
-
- // debug(D_PROCFILE, "File '%s' updated.", ff->filename);
- return ff;
-}
-
-NOINLINE
-static void procfile_set_separators(procfile *ff, const char *separators) {
- static PF_CHAR_TYPE def[256];
- static char initilized = 0;
-
- if(unlikely(!initilized)) {
- // this is thread safe
- // if initialized is zero, multiple threads may be executing
- // this code at the same time, setting in def[] the exact same values
- int i = 256;
- while(i--) {
- if(unlikely(i == '\n' || i == '\r'))
- def[i] = PF_CHAR_IS_NEWLINE;
-
- else if(unlikely(isspace(i) || !isprint(i)))
- def[i] = PF_CHAR_IS_SEPARATOR;
-
- else
- def[i] = PF_CHAR_IS_WORD;
- }
-
- initilized = 1;
- }
-
- // copy the default
- PF_CHAR_TYPE *ffs = ff->separators, *ffd = def, *ffe = &def[256];
- while(ffd != ffe)
- *ffs++ = *ffd++;
-
- // set the separators
- if(unlikely(!separators))
- separators = " \t=|";
-
- ffs = ff->separators;
- const char *s = separators;
- while(*s)
- ffs[(int)*s++] = PF_CHAR_IS_SEPARATOR;
-}
-
-void procfile_set_quotes(procfile *ff, const char *quotes) {
- PF_CHAR_TYPE *ffs = ff->separators;
-
- // remove all quotes
- int i = 256;
- while(i--)
- if(unlikely(ffs[i] == PF_CHAR_IS_QUOTE))
- ffs[i] = PF_CHAR_IS_WORD;
-
- // if nothing given, return
- if(unlikely(!quotes || !*quotes))
- return;
-
- // set the quotes
- const char *s = quotes;
- while(*s)
- ffs[(int)*s++] = PF_CHAR_IS_QUOTE;
-}
-
-void procfile_set_open_close(procfile *ff, const char *open, const char *close) {
- PF_CHAR_TYPE *ffs = ff->separators;
-
- // remove all open/close
- int i = 256;
- while(i--)
- if(unlikely(ffs[i] == PF_CHAR_IS_OPEN || ffs[i] == PF_CHAR_IS_CLOSE))
- ffs[i] = PF_CHAR_IS_WORD;
-
- // if nothing given, return
- if(unlikely(!open || !*open || !close || !*close))
- return;
-
- // set the openings
- const char *s = open;
- while(*s)
- ffs[(int)*s++] = PF_CHAR_IS_OPEN;
-
- // set the closings
- s = close;
- while(*s)
- ffs[(int)*s++] = PF_CHAR_IS_CLOSE;
-}
-
-procfile *procfile_open(const char *filename, const char *separators, uint32_t flags) {
- debug(D_PROCFILE, PF_PREFIX ": Opening file '%s'", filename);
-
- int fd = open(filename, O_RDONLY, 0666);
- if(unlikely(fd == -1)) {
- if(unlikely(!(flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot open file '%s'", filename);
- return NULL;
- }
-
- // info("PROCFILE: opened '%s' on fd %d", filename, fd);
-
- size_t size = (unlikely(procfile_adaptive_initial_allocation)) ? procfile_max_allocation : PROCFILE_INCREMENT_BUFFER;
- procfile *ff = mallocz(sizeof(procfile) + size);
-
- //strncpyz(ff->filename, filename, FILENAME_MAX);
- ff->filename[0] = '\0';
-
- ff->fd = fd;
- ff->size = size;
- ff->len = 0;
- ff->flags = flags;
-
- ff->lines = pflines_new();
- ff->words = pfwords_new();
-
- procfile_set_separators(ff, separators);
-
- debug(D_PROCFILE, "File '%s' opened.", filename);
- return ff;
-}
-
-procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators, uint32_t flags) {
- if(unlikely(!ff)) return procfile_open(filename, separators, flags);
-
- if(likely(ff->fd != -1)) {
- // info("PROCFILE: closing fd %d", ff->fd);
- close(ff->fd);
- }
-
- ff->fd = open(filename, O_RDONLY, 0666);
- if(unlikely(ff->fd == -1)) {
- procfile_close(ff);
- return NULL;
- }
-
- // info("PROCFILE: opened '%s' on fd %d", filename, ff->fd);
-
- //strncpyz(ff->filename, filename, FILENAME_MAX);
- ff->filename[0] = '\0';
- ff->flags = flags;
-
- // do not do the separators again if NULL is given
- if(likely(separators)) procfile_set_separators(ff, separators);
-
- return ff;
-}
-
-// ----------------------------------------------------------------------------
-// example parsing of procfile data
-
-void procfile_print(procfile *ff) {
- size_t lines = procfile_lines(ff), l;
- char *s;
-
- debug(D_PROCFILE, "File '%s' with %zu lines and %zu words", procfile_filename(ff), ff->lines->len, ff->words->len);
-
- for(l = 0; likely(l < lines) ;l++) {
- size_t words = procfile_linewords(ff, l);
-
- debug(D_PROCFILE, " line %zu starts at word %zu and has %zu words", l, ff->lines->lines[l].first, ff->lines->lines[l].words);
-
- size_t w;
- for(w = 0; likely(w < words) ;w++) {
- s = procfile_lineword(ff, l, w);
- debug(D_PROCFILE, " [%zu.%zu] '%s'", l, w, s);
- }
- }
-}
diff --git a/src/procfile.h b/src/procfile.h
deleted file mode 100644
index 012c6efe1..000000000
--- a/src/procfile.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * procfile is a library for reading kernel files from /proc
- *
- * The idea is this:
- *
- * - every file is opened once with procfile_open().
- *
- * - to read updated contents, we rewind it (lseek() to 0) and read again
- * with procfile_readall().
- *
- * - for every file, we use a buffer that is adjusted to fit its entire
- * contents in memory, allowing us to read it with a single read() call.
- * (this provides atomicity / consistency on the data read from the kernel)
- *
- * - once the data are read, we update two arrays of pointers:
- * - a words array, pointing to each word in the data read
- * - a lines array, pointing to the first word for each line
- *
- * This is highly optimized. Both arrays are automatically adjusted to
- * fit all contents and are updated in a single pass on the data:
- * - a raspberry Pi can process 5.000+ files / sec.
- * - a J1900 celeron processor can process 23.000+ files / sec.
-*/
-
-
-#ifndef NETDATA_PROCFILE_H
-#define NETDATA_PROCFILE_H 1
-
-// ----------------------------------------------------------------------------
-// An array of words
-
-typedef struct {
- size_t len; // used entries
- size_t size; // capacity
- char *words[]; // array of pointers
-} pfwords;
-
-
-// ----------------------------------------------------------------------------
-// An array of lines
-
-typedef struct {
- size_t words; // how many words this line has
- size_t first; // the id of the first word of this line
- // in the words array
-} ffline;
-
-typedef struct {
- size_t len; // used entries
- size_t size; // capacity
- ffline lines[]; // array of lines
-} pflines;
-
-
-// ----------------------------------------------------------------------------
-// The procfile
-
-#define PROCFILE_FLAG_DEFAULT 0x00000000
-#define PROCFILE_FLAG_NO_ERROR_ON_FILE_IO 0x00000001
-
-typedef enum procfile_separator {
- PF_CHAR_IS_SEPARATOR,
- PF_CHAR_IS_NEWLINE,
- PF_CHAR_IS_WORD,
- PF_CHAR_IS_QUOTE,
- PF_CHAR_IS_OPEN,
- PF_CHAR_IS_CLOSE
-} PF_CHAR_TYPE;
-
-typedef struct {
- char filename[FILENAME_MAX + 1]; // not populated until profile_filename() is called
-
- uint32_t flags;
- int fd; // the file desriptor
- size_t len; // the bytes we have placed into data
- size_t size; // the bytes we have allocated for data
- pflines *lines;
- pfwords *words;
- PF_CHAR_TYPE separators[256];
- char data[]; // allocated buffer to keep file contents
-} procfile;
-
-// close the proc file and free all related memory
-extern void procfile_close(procfile *ff);
-
-// (re)read and parse the proc file
-extern procfile *procfile_readall(procfile *ff);
-
-// open a /proc or /sys file
-extern procfile *procfile_open(const char *filename, const char *separators, uint32_t flags);
-
-// re-open a file
-// if separators == NULL, the last separators are used
-extern procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators, uint32_t flags);
-
-// example walk-through a procfile parsed file
-extern void procfile_print(procfile *ff);
-
-extern void procfile_set_quotes(procfile *ff, const char *quotes);
-extern void procfile_set_open_close(procfile *ff, const char *open, const char *close);
-
-extern char *procfile_filename(procfile *ff);
-
-// ----------------------------------------------------------------------------
-
-// set this to 1, to have procfile adapt its initial buffer allocation to the max allocation used so far
-extern int procfile_adaptive_initial_allocation;
-
-// return the number of lines present
-#define procfile_lines(ff) ((ff)->lines->len)
-
-// return the number of words of the Nth line
-#define procfile_linewords(ff, line) (((line) < procfile_lines(ff)) ? (ff)->lines->lines[(line)].words : 0)
-
-// return the Nth word of the file, or empty string
-#define procfile_word(ff, word) (((word) < (ff)->words->len) ? (ff)->words->words[(word)] : "")
-
-// return the first word of the Nth line, or empty string
-#define procfile_line(ff, line) (((line) < procfile_lines(ff)) ? procfile_word((ff), (ff)->lines->lines[(line)].first) : "")
-
-// return the Nth word of the current line
-#define procfile_lineword(ff, line, word) (((line) < procfile_lines(ff) && (word) < procfile_linewords((ff), (line))) ? procfile_word((ff), (ff)->lines->lines[(line)].first + (word)) : "")
-
-#endif /* NETDATA_PROCFILE_H */
diff --git a/src/registry.c b/src/registry.c
deleted file mode 100644
index bbc2ef366..000000000
--- a/src/registry.c
+++ /dev/null
@@ -1,414 +0,0 @@
-#include "common.h"
-
-#include "registry_internals.h"
-
-#define REGISTRY_STATUS_OK "ok"
-#define REGISTRY_STATUS_FAILED "failed"
-#define REGISTRY_STATUS_DISABLED "disabled"
-
-// ----------------------------------------------------------------------------
-// REGISTRY concurrency locking
-
-static inline void registry_lock(void) {
- netdata_mutex_lock(&registry.lock);
-}
-
-static inline void registry_unlock(void) {
- netdata_mutex_unlock(&registry.lock);
-}
-
-
-// ----------------------------------------------------------------------------
-// COOKIES
-
-static void registry_set_cookie(struct web_client *w, const char *guid) {
- char edate[100];
- time_t et = now_realtime_sec() + registry.persons_expiration;
- struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
- strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
-
- snprintfz(w->cookie1, NETDATA_WEB_REQUEST_COOKIE_SIZE, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", guid, edate);
-
- if(registry.registry_domain && registry.registry_domain[0])
- snprintfz(w->cookie2, NETDATA_WEB_REQUEST_COOKIE_SIZE, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", guid, registry.registry_domain, edate);
-}
-
-static inline void registry_set_person_cookie(struct web_client *w, REGISTRY_PERSON *p) {
- registry_set_cookie(w, p->guid);
-}
-
-
-// ----------------------------------------------------------------------------
-// JSON GENERATION
-
-static inline void registry_json_header(RRDHOST *host, struct web_client *w, const char *action, const char *status) {
- buffer_flush(w->response.data);
- w->response.data->contenttype = CT_APPLICATION_JSON;
- buffer_sprintf(w->response.data, "{\n\t\"action\": \"%s\",\n\t\"status\": \"%s\",\n\t\"hostname\": \"%s\",\n\t\"machine_guid\": \"%s\"",
- action, status, host->registry_hostname, host->machine_guid);
-}
-
-static inline void registry_json_footer(struct web_client *w) {
- buffer_strcat(w->response.data, "\n}\n");
-}
-
-static inline int registry_json_disabled(RRDHOST *host, struct web_client *w, const char *action) {
- registry_json_header(host, w, action, REGISTRY_STATUS_DISABLED);
-
- buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"",
- registry.registry_to_announce);
-
- registry_json_footer(w);
- return 200;
-}
-
-
-// ----------------------------------------------------------------------------
-// CALLBACKS FOR WALKING THROUGH REGISTRY OBJECTS
-
-// structure used be the callbacks below
-struct registry_json_walk_person_urls_callback {
- REGISTRY_PERSON *p;
- REGISTRY_MACHINE *m;
- struct web_client *w;
- int count;
-};
-
-// callback for rendering PERSON_URLs
-static int registry_json_person_url_callback(void *entry, void *data) {
- REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)entry;
- struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
- struct web_client *w = c->w;
-
- if(unlikely(c->count++))
- buffer_strcat(w->response.data, ",");
-
- buffer_sprintf(w->response.data, "\n\t\t[ \"%s\", \"%s\", %u000, %u, \"%s\" ]",
- pu->machine->guid, pu->url->url, pu->last_t, pu->usages, pu->machine_name);
-
- return 0;
-}
-
-// callback for rendering MACHINE_URLs
-static int registry_json_machine_url_callback(void *entry, void *data) {
- REGISTRY_MACHINE_URL *mu = (REGISTRY_MACHINE_URL *)entry;
- struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
- struct web_client *w = c->w;
- REGISTRY_MACHINE *m = c->m;
-
- if(unlikely(c->count++))
- buffer_strcat(w->response.data, ",");
-
- buffer_sprintf(w->response.data, "\n\t\t[ \"%s\", \"%s\", %u000, %u ]",
- m->guid, mu->url->url, mu->last_t, mu->usages);
-
- return 1;
-}
-
-// ----------------------------------------------------------------------------
-
-// structure used be the callbacks below
-struct registry_person_url_callback_verify_machine_exists_data {
- REGISTRY_MACHINE *m;
- int count;
-};
-
-static inline int registry_person_url_callback_verify_machine_exists(void *entry, void *data) {
- struct registry_person_url_callback_verify_machine_exists_data *d = (struct registry_person_url_callback_verify_machine_exists_data *)data;
- REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)entry;
- REGISTRY_MACHINE *m = d->m;
-
- if(pu->machine == m)
- d->count++;
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// public HELLO request
-
-int registry_request_hello_json(RRDHOST *host, struct web_client *w) {
- registry_json_header(host, w, "hello", REGISTRY_STATUS_OK);
-
- buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"",
- registry.registry_to_announce);
-
- registry_json_footer(w);
- return 200;
-}
-
-// ----------------------------------------------------------------------------
-//public ACCESS request
-
-#define REGISTRY_VERIFY_COOKIES_GUID "give-me-back-this-cookie-now--please"
-
-// the main method for registering an access
-int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when) {
- if(unlikely(!registry.enabled))
- return registry_json_disabled(host, w, "access");
-
- // ------------------------------------------------------------------------
- // verify the browser supports cookies
-
- if(registry.verify_cookies_redirects > 0 && !person_guid[0]) {
- buffer_flush(w->response.data);
- registry_set_cookie(w, REGISTRY_VERIFY_COOKIES_GUID);
- w->response.data->contenttype = CT_APPLICATION_JSON;
- buffer_sprintf(w->response.data, "{ \"status\": \"redirect\", \"registry\": \"%s\" }", registry.registry_to_announce);
- return 200;
- }
-
- if(unlikely(person_guid[0] && !strcmp(person_guid, REGISTRY_VERIFY_COOKIES_GUID)))
- person_guid[0] = '\0';
-
- // ------------------------------------------------------------------------
-
- registry_lock();
-
- REGISTRY_PERSON *p = registry_request_access(person_guid, machine_guid, url, name, when);
- if(!p) {
- registry_json_header(host, w, "access", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 412;
- }
-
- // set the cookie
- registry_set_person_cookie(w, p);
-
- // generate the response
- registry_json_header(host, w, "access", REGISTRY_STATUS_OK);
-
- buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\",\n\t\"urls\": [", p->guid);
- struct registry_json_walk_person_urls_callback c = { p, NULL, w, 0 };
- avl_traverse(&p->person_urls, registry_json_person_url_callback, &c);
- buffer_strcat(w->response.data, "\n\t]\n");
-
- registry_json_footer(w);
- registry_unlock();
- return 200;
-}
-
-// ----------------------------------------------------------------------------
-// public DELETE request
-
-// the main method for deleting a URL from a person
-int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) {
- if(!registry.enabled)
- return registry_json_disabled(host, w, "delete");
-
- registry_lock();
-
- REGISTRY_PERSON *p = registry_request_delete(person_guid, machine_guid, url, delete_url, when);
- if(!p) {
- registry_json_header(host, w, "delete", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 412;
- }
-
- // generate the response
- registry_json_header(host, w, "delete", REGISTRY_STATUS_OK);
- registry_json_footer(w);
- registry_unlock();
- return 200;
-}
-
-// ----------------------------------------------------------------------------
-// public SEARCH request
-
-// the main method for searching the URLs of a netdata
-int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) {
- if(!registry.enabled)
- return registry_json_disabled(host, w, "search");
-
- registry_lock();
-
- REGISTRY_MACHINE *m = registry_request_machine(person_guid, machine_guid, url, request_machine, when);
- if(!m) {
- registry_json_header(host, w, "search", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 404;
- }
-
- registry_json_header(host, w, "search", REGISTRY_STATUS_OK);
-
- buffer_strcat(w->response.data, ",\n\t\"urls\": [");
- struct registry_json_walk_person_urls_callback c = { NULL, m, w, 0 };
- dictionary_get_all(m->machine_urls, registry_json_machine_url_callback, &c);
- buffer_strcat(w->response.data, "\n\t]\n");
-
- registry_json_footer(w);
- registry_unlock();
- return 200;
-}
-
-// ----------------------------------------------------------------------------
-// SWITCH REQUEST
-
-// the main method for switching user identity
-int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when) {
- if(!registry.enabled)
- return registry_json_disabled(host, w, "switch");
-
- (void)url;
- (void)when;
-
- registry_lock();
-
- REGISTRY_PERSON *op = registry_person_find(person_guid);
- if(!op) {
- registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 430;
- }
-
- REGISTRY_PERSON *np = registry_person_find(new_person_guid);
- if(!np) {
- registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 431;
- }
-
- REGISTRY_MACHINE *m = registry_machine_find(machine_guid);
- if(!m) {
- registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 432;
- }
-
- struct registry_person_url_callback_verify_machine_exists_data data = { m, 0 };
-
- // verify the old person has access to this machine
- avl_traverse(&op->person_urls, registry_person_url_callback_verify_machine_exists, &data);
- if(!data.count) {
- registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 433;
- }
-
- // verify the new person has access to this machine
- data.count = 0;
- avl_traverse(&np->person_urls, registry_person_url_callback_verify_machine_exists, &data);
- if(!data.count) {
- registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED);
- registry_json_footer(w);
- registry_unlock();
- return 434;
- }
-
- // set the cookie of the new person
- // the user just switched identity
- registry_set_person_cookie(w, np);
-
- // generate the response
- registry_json_header(host, w, "switch", REGISTRY_STATUS_OK);
- buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\"", np->guid);
- registry_json_footer(w);
-
- registry_unlock();
- return 200;
-}
-
-// ----------------------------------------------------------------------------
-// STATISTICS
-
-void registry_statistics(void) {
- if(!registry.enabled) return;
-
- static RRDSET *sts = NULL, *stc = NULL, *stm = NULL;
-
- if(unlikely(!sts)) {
- sts = rrdset_create_localhost(
- "netdata"
- , "registry_sessions"
- , NULL
- , "registry"
- , NULL
- , "NetData Registry Sessions"
- , "session"
- , "registry"
- , "stats"
- , 131000
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(sts, "sessions", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(sts);
-
- rrddim_set(sts, "sessions", registry.usages_count);
- rrdset_done(sts);
-
- // ------------------------------------------------------------------------
-
- if(unlikely(!stc)) {
- stc = rrdset_create_localhost(
- "netdata"
- , "registry_entries"
- , NULL
- , "registry"
- , NULL
- , "NetData Registry Entries"
- , "entries"
- , "registry"
- , "stats"
- , 131100
- , localhost->rrd_update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(stc, "persons", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stc, "machines", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stc, "urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stc, "persons_urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stc, "machines_urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(stc);
-
- rrddim_set(stc, "persons", registry.persons_count);
- rrddim_set(stc, "machines", registry.machines_count);
- rrddim_set(stc, "urls", registry.urls_count);
- rrddim_set(stc, "persons_urls", registry.persons_urls_count);
- rrddim_set(stc, "machines_urls", registry.machines_urls_count);
- rrdset_done(stc);
-
- // ------------------------------------------------------------------------
-
- if(unlikely(!stm)) {
- stm = rrdset_create_localhost(
- "netdata"
- , "registry_mem"
- , NULL
- , "registry"
- , NULL
- , "NetData Registry Memory"
- , "KB"
- , "registry"
- , "stats"
- , 131300
- , localhost->rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(stm, "persons", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stm, "machines", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stm, "urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stm, "persons_urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(stm, "machines_urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(stm);
-
- rrddim_set(stm, "persons", registry.persons_memory + registry.persons_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
- rrddim_set(stm, "machines", registry.machines_memory + registry.machines_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
- rrddim_set(stm, "urls", registry.urls_memory);
- rrddim_set(stm, "persons_urls", registry.persons_urls_memory);
- rrddim_set(stm, "machines_urls", registry.machines_urls_memory + registry.machines_count * sizeof(DICTIONARY) + registry.machines_urls_count * sizeof(NAME_VALUE));
- rrdset_done(stm);
-}
diff --git a/src/registry.h b/src/registry.h
deleted file mode 100644
index 9aa241564..000000000
--- a/src/registry.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * netdata registry
- *
- * this header file describes the public interface
- * to the netdata registry
- *
- * only these high level functions are exposed
- *
- */
-
-// ----------------------------------------------------------------------------
-// TODO
-//
-// 1. the default tracking cookie expires in 1 year, but the persons are not
-// removed from the db - this means the database only grows - ideally the
-// database should be cleaned in registry_db_save() for both on-disk and
-// on-memory entries.
-//
-// Cleanup:
-// i. Find all the PERSONs that have expired cookie
-// ii. For each of their PERSON_URLs:
-// - decrement the linked MACHINE links
-// - if the linked MACHINE has no other links, remove the linked MACHINE too
-// - remove the PERSON_URL
-//
-// 2. add protection to prevent abusing the registry by flooding it with
-// requests to fill the memory and crash it.
-//
-// Possible protections:
-// - limit the number of URLs per person
-// - limit the number of URLs per machine
-// - limit the number of persons
-// - limit the number of machines
-// - [DONE] limit the size of URLs
-// - [DONE] limit the size of PERSON_URL names
-// - limit the number of requests that add data to the registry,
-// per client IP per hour
-//
-// 3. lower memory requirements
-//
-// - embed avl structures directly into registry objects, instead of DICTIONARY
-// [DONE for PERSON_URLs, PENDING for MACHINE_URLs]
-// - store GUIDs in memory as UUID instead of char *
-// - do not track persons using the demo machines only
-// (i.e. start tracking them only when they access a non-demo machine)
-// - [DONE] do not track custom dashboards by default
-
-
-#ifndef NETDATA_REGISTRY_H
-#define NETDATA_REGISTRY_H 1
-
-#define NETDATA_REGISTRY_COOKIE_NAME "netdata_registry_id"
-
-// initialize the registry
-// should only happen when netdata starts
-extern int registry_init(void);
-
-// free all data held by the registry
-// should only happen when netdata exits
-extern void registry_free(void);
-
-// HTTP requests handled by the registry
-extern int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when);
-extern int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when);
-extern int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when);
-extern int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when);
-extern int registry_request_hello_json(RRDHOST *host, struct web_client *w);
-
-// update the registry monitoring charts
-extern void registry_statistics(void);
-
-extern char *registry_get_this_machine_guid(void);
-extern char *registry_get_this_machine_hostname(void);
-
-extern int regenerate_guid(const char *guid, char *result);
-
-#endif /* NETDATA_REGISTRY_H */
diff --git a/src/registry_db.c b/src/registry_db.c
deleted file mode 100644
index de6c634c3..000000000
--- a/src/registry_db.c
+++ /dev/null
@@ -1,343 +0,0 @@
-#include "registry_internals.h"
-
-int registry_db_should_be_saved(void) {
- debug(D_REGISTRY, "log entries %llu, max %llu", registry.log_count, registry.save_registry_every_entries);
- return registry.log_count > registry.save_registry_every_entries;
-}
-
-// ----------------------------------------------------------------------------
-// INTERNAL FUNCTIONS FOR SAVING REGISTRY OBJECTS
-
-static int registry_machine_save_url(void *entry, void *file) {
- REGISTRY_MACHINE_URL *mu = entry;
- FILE *fp = file;
-
- debug(D_REGISTRY, "Registry: registry_machine_save_url('%s')", mu->url->url);
-
- int ret = fprintf(fp, "V\t%08x\t%08x\t%08x\t%02x\t%s\n",
- mu->first_t,
- mu->last_t,
- mu->usages,
- mu->flags,
- mu->url->url
- );
-
- // error handling is done at registry_db_save()
-
- return ret;
-}
-
-static int registry_machine_save(void *entry, void *file) {
- REGISTRY_MACHINE *m = entry;
- FILE *fp = file;
-
- debug(D_REGISTRY, "Registry: registry_machine_save('%s')", m->guid);
-
- int ret = fprintf(fp, "M\t%08x\t%08x\t%08x\t%s\n",
- m->first_t,
- m->last_t,
- m->usages,
- m->guid
- );
-
- if(ret >= 0) {
- int ret2 = dictionary_get_all(m->machine_urls, registry_machine_save_url, fp);
- if(ret2 < 0) return ret2;
- ret += ret2;
- }
-
- // error handling is done at registry_db_save()
-
- return ret;
-}
-
-static inline int registry_person_save_url(void *entry, void *file) {
- REGISTRY_PERSON_URL *pu = entry;
- FILE *fp = file;
-
- debug(D_REGISTRY, "Registry: registry_person_save_url('%s')", pu->url->url);
-
- int ret = fprintf(fp, "U\t%08x\t%08x\t%08x\t%02x\t%s\t%s\t%s\n",
- pu->first_t,
- pu->last_t,
- pu->usages,
- pu->flags,
- pu->machine->guid,
- pu->machine_name,
- pu->url->url
- );
-
- // error handling is done at registry_db_save()
-
- return ret;
-}
-
-static inline int registry_person_save(void *entry, void *file) {
- REGISTRY_PERSON *p = entry;
- FILE *fp = file;
-
- debug(D_REGISTRY, "Registry: registry_person_save('%s')", p->guid);
-
- int ret = fprintf(fp, "P\t%08x\t%08x\t%08x\t%s\n",
- p->first_t,
- p->last_t,
- p->usages,
- p->guid
- );
-
- if(ret >= 0) {
- //int ret2 = dictionary_get_all(p->person_urls, registry_person_save_url, fp);
- int ret2 = avl_traverse(&p->person_urls, registry_person_save_url, fp);
- if (ret2 < 0) return ret2;
- ret += ret2;
- }
-
- // error handling is done at registry_db_save()
-
- return ret;
-}
-
-// ----------------------------------------------------------------------------
-// SAVE THE REGISTRY DATABASE
-
-int registry_db_save(void) {
- if(unlikely(!registry.enabled))
- return -1;
-
- if(unlikely(!registry_db_should_be_saved()))
- return -2;
-
- error_log_limit_unlimited();
-
- char tmp_filename[FILENAME_MAX + 1];
- char old_filename[FILENAME_MAX + 1];
-
- snprintfz(old_filename, FILENAME_MAX, "%s.old", registry.db_filename);
- snprintfz(tmp_filename, FILENAME_MAX, "%s.tmp", registry.db_filename);
-
- debug(D_REGISTRY, "Registry: Creating file '%s'", tmp_filename);
- FILE *fp = fopen(tmp_filename, "w");
- if(!fp) {
- error("Registry: Cannot create file: %s", tmp_filename);
- error_log_limit_reset();
- return -1;
- }
-
- // dictionary_get_all() has its own locking, so this is safe to do
-
- debug(D_REGISTRY, "Saving all machines");
- int bytes1 = dictionary_get_all(registry.machines, registry_machine_save, fp);
- if(bytes1 < 0) {
- error("Registry: Cannot save registry machines - return value %d", bytes1);
- fclose(fp);
- error_log_limit_reset();
- return bytes1;
- }
- debug(D_REGISTRY, "Registry: saving machines took %d bytes", bytes1);
-
- debug(D_REGISTRY, "Saving all persons");
- int bytes2 = dictionary_get_all(registry.persons, registry_person_save, fp);
- if(bytes2 < 0) {
- error("Registry: Cannot save registry persons - return value %d", bytes2);
- fclose(fp);
- error_log_limit_reset();
- return bytes2;
- }
- debug(D_REGISTRY, "Registry: saving persons took %d bytes", bytes2);
-
- // save the totals
- fprintf(fp, "T\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\n",
- registry.persons_count,
- registry.machines_count,
- registry.usages_count + 1, // this is required - it is lost on db rotation
- registry.urls_count,
- registry.persons_urls_count,
- registry.machines_urls_count
- );
-
- fclose(fp);
-
- errno = 0;
-
- // remove the .old db
- debug(D_REGISTRY, "Registry: Removing old db '%s'", old_filename);
- if(unlink(old_filename) == -1 && errno != ENOENT)
- error("Registry: cannot remove old registry file '%s'", old_filename);
-
- // rename the db to .old
- debug(D_REGISTRY, "Registry: Link current db '%s' to .old: '%s'", registry.db_filename, old_filename);
- if(link(registry.db_filename, old_filename) == -1 && errno != ENOENT)
- error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", registry.db_filename, old_filename);
-
- else {
- // remove the database (it is saved in .old)
- debug(D_REGISTRY, "Registry: removing db '%s'", registry.db_filename);
- if (unlink(registry.db_filename) == -1 && errno != ENOENT)
- error("Registry: cannot remove old registry file '%s'", registry.db_filename);
-
- // move the .tmp to make it active
- debug(D_REGISTRY, "Registry: linking tmp db '%s' to active db '%s'", tmp_filename, registry.db_filename);
- if (link(tmp_filename, registry.db_filename) == -1) {
- error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename,
- registry.db_filename);
-
- // move the .old back
- debug(D_REGISTRY, "Registry: linking old db '%s' to active db '%s'", old_filename, registry.db_filename);
- if(link(old_filename, registry.db_filename) == -1)
- error("Registry: cannot move file '%s' to '%s'. Recovering the old registry DB failed!", old_filename, registry.db_filename);
- }
- else {
- debug(D_REGISTRY, "Registry: removing tmp db '%s'", tmp_filename);
- if(unlink(tmp_filename) == -1)
- error("Registry: cannot remove tmp registry file '%s'", tmp_filename);
-
- // it has been moved successfully
- // discard the current registry log
- registry_log_recreate();
- registry.log_count = 0;
- }
- }
-
- // continue operations
- error_log_limit_reset();
-
- return -1;
-}
-
-// ----------------------------------------------------------------------------
-// LOAD THE REGISTRY DATABASE
-
-size_t registry_db_load(void) {
- char *s, buf[4096 + 1];
- REGISTRY_PERSON *p = NULL;
- REGISTRY_MACHINE *m = NULL;
- REGISTRY_URL *u = NULL;
- size_t line = 0;
-
- debug(D_REGISTRY, "Registry: loading active db from: '%s'", registry.db_filename);
- FILE *fp = fopen(registry.db_filename, "r");
- if(!fp) {
- error("Registry: cannot open registry file: '%s'", registry.db_filename);
- return 0;
- }
-
- size_t len = 0;
- buf[4096] = '\0';
- while((s = fgets_trim_len(buf, 4096, fp, &len))) {
- line++;
-
- debug(D_REGISTRY, "Registry: read line %zu to length %zu: %s", line, len, s);
- switch(*s) {
- case 'T': // totals
- if(unlikely(len != 103 || s[1] != '\t' || s[18] != '\t' || s[35] != '\t' || s[52] != '\t' || s[69] != '\t' || s[86] != '\t' || s[103] != '\0')) {
- error("Registry totals line %zu is wrong (len = %zu).", line, len);
- continue;
- }
- registry.persons_count = strtoull(&s[2], NULL, 16);
- registry.machines_count = strtoull(&s[19], NULL, 16);
- registry.usages_count = strtoull(&s[36], NULL, 16);
- registry.urls_count = strtoull(&s[53], NULL, 16);
- registry.persons_urls_count = strtoull(&s[70], NULL, 16);
- registry.machines_urls_count = strtoull(&s[87], NULL, 16);
- break;
-
- case 'P': // person
- m = NULL;
- // verify it is valid
- if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) {
- error("Registry person line %zu is wrong (len = %zu).", line, len);
- continue;
- }
-
- s[1] = s[10] = s[19] = s[28] = '\0';
- p = registry_person_allocate(&s[29], strtoul(&s[2], NULL, 16));
- p->last_t = (uint32_t)strtoul(&s[11], NULL, 16);
- p->usages = (uint32_t)strtoul(&s[20], NULL, 16);
- debug(D_REGISTRY, "Registry loaded person '%s', first: %u, last: %u, usages: %u", p->guid, p->first_t, p->last_t, p->usages);
- break;
-
- case 'M': // machine
- p = NULL;
- // verify it is valid
- if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) {
- error("Registry person line %zu is wrong (len = %zu).", line, len);
- continue;
- }
-
- s[1] = s[10] = s[19] = s[28] = '\0';
- m = registry_machine_allocate(&s[29], strtoul(&s[2], NULL, 16));
- m->last_t = (uint32_t)strtoul(&s[11], NULL, 16);
- m->usages = (uint32_t)strtoul(&s[20], NULL, 16);
- debug(D_REGISTRY, "Registry loaded machine '%s', first: %u, last: %u, usages: %u", m->guid, m->first_t, m->last_t, m->usages);
- break;
-
- case 'U': // person URL
- if(unlikely(!p)) {
- error("Registry: ignoring line %zu, no person loaded: %s", line, s);
- continue;
- }
-
- // verify it is valid
- if(len < 69 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t' || s[68] != '\t') {
- error("Registry person URL line %zu is wrong (len = %zu).", line, len);
- continue;
- }
-
- s[1] = s[10] = s[19] = s[28] = s[31] = s[68] = '\0';
-
- // skip the name to find the url
- char *url = &s[69];
- while(*url && *url != '\t') url++;
- if(!*url) {
- error("Registry person URL line %zu does not have a url.", line);
- continue;
- }
- *url++ = '\0';
-
- // u = registry_url_allocate_nolock(url, strlen(url));
- u = registry_url_get(url, strlen(url));
-
- time_t first_t = strtoul(&s[2], NULL, 16);
-
- m = registry_machine_find(&s[32]);
- if(!m) m = registry_machine_allocate(&s[32], first_t);
-
- REGISTRY_PERSON_URL *pu = registry_person_url_allocate(p, m, u, &s[69], strlen(&s[69]), first_t);
- pu->last_t = (uint32_t)strtoul(&s[11], NULL, 16);
- pu->usages = (uint32_t)strtoul(&s[20], NULL, 16);
- pu->flags = (uint8_t)strtoul(&s[29], NULL, 16);
- debug(D_REGISTRY, "Registry loaded person URL '%s' with name '%s' of machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, pu->machine_name, m->guid, pu->first_t, pu->last_t, pu->usages, pu->flags);
- break;
-
- case 'V': // machine URL
- if(unlikely(!m)) {
- error("Registry: ignoring line %zu, no machine loaded: %s", line, s);
- continue;
- }
-
- // verify it is valid
- if(len < 32 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t') {
- error("Registry person URL line %zu is wrong (len = %zu).", line, len);
- continue;
- }
-
- s[1] = s[10] = s[19] = s[28] = s[31] = '\0';
- // u = registry_url_allocate_nolock(&s[32], strlen(&s[32]));
- u = registry_url_get(&s[32], strlen(&s[32]));
-
- REGISTRY_MACHINE_URL *mu = registry_machine_url_allocate(m, u, strtoul(&s[2], NULL, 16));
- mu->last_t = (uint32_t)strtoul(&s[11], NULL, 16);
- mu->usages = (uint32_t)strtoul(&s[20], NULL, 16);
- mu->flags = (uint8_t)strtoul(&s[29], NULL, 16);
- debug(D_REGISTRY, "Registry loaded machine URL '%s', machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, m->guid, mu->first_t, mu->last_t, mu->usages, mu->flags);
- break;
-
- default:
- error("Registry: ignoring line %zu of filename '%s': %s.", line, registry.db_filename, s);
- break;
- }
- }
- fclose(fp);
-
- return line;
-}
diff --git a/src/registry_init.c b/src/registry_init.c
deleted file mode 100644
index 654f66d12..000000000
--- a/src/registry_init.c
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "registry_internals.h"
-
-int registry_init(void) {
- char filename[FILENAME_MAX + 1];
-
- // registry enabled?
- if(web_server_mode != WEB_SERVER_MODE_NONE) {
- registry.enabled = config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0);
- }
- else {
- info("Registry is disabled - use the central netdata");
- config_set_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0);
- registry.enabled = 0;
- }
-
- // pathnames
- snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir);
- registry.pathname = config_get(CONFIG_SECTION_REGISTRY, "registry db directory", filename);
- if(mkdir(registry.pathname, 0770) == -1 && errno != EEXIST)
- fatal("Cannot create directory '%s'.", registry.pathname);
-
- // filenames
- snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname);
- registry.machine_guid_filename = config_get(CONFIG_SECTION_REGISTRY, "netdata unique id file", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname);
- registry.db_filename = config_get(CONFIG_SECTION_REGISTRY, "registry db file", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname);
- registry.log_filename = config_get(CONFIG_SECTION_REGISTRY, "registry log file", filename);
-
- // configuration options
- registry.save_registry_every_entries = (unsigned long long)config_get_number(CONFIG_SECTION_REGISTRY, "registry save db every new entries", 1000000);
- registry.persons_expiration = config_get_number(CONFIG_SECTION_REGISTRY, "registry expire idle persons days", 365) * 86400;
- registry.registry_domain = config_get(CONFIG_SECTION_REGISTRY, "registry domain", "");
- registry.registry_to_announce = config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io");
- registry.hostname = config_get(CONFIG_SECTION_REGISTRY, "registry hostname", netdata_configured_hostname);
- registry.verify_cookies_redirects = config_get_boolean(CONFIG_SECTION_REGISTRY, "verify browser cookies support", 1);
-
- setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1);
- setenv("NETDATA_REGISTRY_URL", registry.registry_to_announce, 1);
-
- registry.max_url_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL length", 1024);
- if(registry.max_url_length < 10) {
- registry.max_url_length = 10;
- config_set_number(CONFIG_SECTION_REGISTRY, "max URL length", (long long)registry.max_url_length);
- }
-
- registry.max_name_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL name length", 50);
- if(registry.max_name_length < 10) {
- registry.max_name_length = 10;
- config_set_number(CONFIG_SECTION_REGISTRY, "max URL name length", (long long)registry.max_name_length);
- }
-
- // initialize entries counters
- registry.persons_count = 0;
- registry.machines_count = 0;
- registry.usages_count = 0;
- registry.urls_count = 0;
- registry.persons_urls_count = 0;
- registry.machines_urls_count = 0;
-
- // initialize memory counters
- registry.persons_memory = 0;
- registry.machines_memory = 0;
- registry.urls_memory = 0;
- registry.persons_urls_memory = 0;
- registry.machines_urls_memory = 0;
-
- // initialize locks
- netdata_mutex_init(&registry.lock);
-
- // create dictionaries
- registry.persons = dictionary_create(DICTIONARY_FLAGS);
- registry.machines = dictionary_create(DICTIONARY_FLAGS);
- avl_init(&registry.registry_urls_root_index, registry_url_compare);
-
- // load the registry database
- if(registry.enabled) {
- registry_log_open();
- registry_db_load();
- registry_log_load();
-
- if(unlikely(registry_db_should_be_saved()))
- registry_db_save();
- }
-
- return 0;
-}
-
-void registry_free(void) {
- if(!registry.enabled) return;
-
- // we need to destroy the dictionaries ourselves
- // since the dictionaries use memory we allocated
-
- while(registry.persons->values_index.root) {
- REGISTRY_PERSON *p = ((NAME_VALUE *)registry.persons->values_index.root)->value;
- registry_person_del(p);
- }
-
- while(registry.machines->values_index.root) {
- REGISTRY_MACHINE *m = ((NAME_VALUE *)registry.machines->values_index.root)->value;
-
- // fprintf(stderr, "\nMACHINE: '%s', first: %u, last: %u, usages: %u\n", m->guid, m->first_t, m->last_t, m->usages);
-
- while(m->machine_urls->values_index.root) {
- REGISTRY_MACHINE_URL *mu = ((NAME_VALUE *)m->machine_urls->values_index.root)->value;
-
- // fprintf(stderr, "\tURL: '%s', first: %u, last: %u, usages: %u, flags: 0x%02x\n", mu->url->url, mu->first_t, mu->last_t, mu->usages, mu->flags);
-
- //debug(D_REGISTRY, "Registry: destroying persons dictionary from url '%s'", mu->url->url);
- //dictionary_destroy(mu->persons);
-
- debug(D_REGISTRY, "Registry: deleting url '%s' from person '%s'", mu->url->url, m->guid);
- dictionary_del(m->machine_urls, mu->url->url);
-
- debug(D_REGISTRY, "Registry: unlinking url '%s' from machine", mu->url->url);
- registry_url_unlink(mu->url);
-
- debug(D_REGISTRY, "Registry: freeing machine url");
- freez(mu);
- }
-
- debug(D_REGISTRY, "Registry: deleting machine '%s' from machines registry", m->guid);
- dictionary_del(registry.machines, m->guid);
-
- debug(D_REGISTRY, "Registry: destroying URL dictionary of machine '%s'", m->guid);
- dictionary_destroy(m->machine_urls);
-
- debug(D_REGISTRY, "Registry: freeing machine '%s'", m->guid);
- freez(m);
- }
-
- // and free the memory of remaining dictionary structures
-
- debug(D_REGISTRY, "Registry: destroying persons dictionary");
- dictionary_destroy(registry.persons);
-
- debug(D_REGISTRY, "Registry: destroying machines dictionary");
- dictionary_destroy(registry.machines);
-}
-
diff --git a/src/registry_internals.c b/src/registry_internals.c
deleted file mode 100644
index 44b0a1513..000000000
--- a/src/registry_internals.c
+++ /dev/null
@@ -1,322 +0,0 @@
-#include "registry_internals.h"
-
-struct registry registry;
-
-// ----------------------------------------------------------------------------
-// common functions
-
-// parse a GUID and re-generated to be always lower case
-// this is used as a protection against the variations of GUIDs
-int regenerate_guid(const char *guid, char *result) {
- uuid_t uuid;
- if(unlikely(uuid_parse(guid, uuid) == -1)) {
- info("Registry: GUID '%s' is not a valid GUID.", guid);
- return -1;
- }
- else {
- uuid_unparse_lower(uuid, result);
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(strcmp(guid, result) != 0)
- info("GUID '%s' and re-generated GUID '%s' differ!", guid, result);
-#endif /* NETDATA_INTERNAL_CHECKS */
- }
-
- return 0;
-}
-
-// make sure the names of the machines / URLs do not contain any tabs
-// (which are used as our separator in the database files)
-// and are properly trimmed (before and after)
-static inline char *registry_fix_machine_name(char *name, size_t *len) {
- char *s = name?name:"";
-
- // skip leading spaces
- while(*s && isspace(*s)) s++;
-
- // make sure all spaces are a SPACE
- char *t = s;
- while(*t) {
- if(unlikely(isspace(*t)))
- *t = ' ';
-
- t++;
- }
-
- // remove trailing spaces
- while(--t >= s) {
- if(*t == ' ')
- *t = '\0';
- else
- break;
- }
- t++;
-
- if(likely(len))
- *len = (t - s);
-
- return s;
-}
-
-static inline char *registry_fix_url(char *url, size_t *len) {
- size_t l = 0;
- char *s = registry_fix_machine_name(url, &l);
-
- // protection from too big URLs
- if(l > registry.max_url_length) {
- l = registry.max_url_length;
- s[l] = '\0';
- }
-
- if(len) *len = l;
- return s;
-}
-
-
-// ----------------------------------------------------------------------------
-// HELPERS
-
-// verify the person, the machine and the URL exist in our DB
-REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_guid, char *url, REGISTRY_PERSON **pp, REGISTRY_MACHINE **mm) {
- char pbuf[GUID_LEN + 1], mbuf[GUID_LEN + 1];
-
- if(!person_guid || !*person_guid || !machine_guid || !*machine_guid || !url || !*url) {
- info("Registry Request Verification: invalid request! person: '%s', machine '%s', url '%s'", person_guid?person_guid:"UNSET", machine_guid?machine_guid:"UNSET", url?url:"UNSET");
- return NULL;
- }
-
- // normalize the url
- url = registry_fix_url(url, NULL);
-
- // make sure the person GUID is valid
- if(regenerate_guid(person_guid, pbuf) == -1) {
- info("Registry Request Verification: invalid person GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
- return NULL;
- }
- person_guid = pbuf;
-
- // make sure the machine GUID is valid
- if(regenerate_guid(machine_guid, mbuf) == -1) {
- info("Registry Request Verification: invalid machine GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
- return NULL;
- }
- machine_guid = mbuf;
-
- // make sure the machine exists
- REGISTRY_MACHINE *m = registry_machine_find(machine_guid);
- if(!m) {
- info("Registry Request Verification: machine not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
- return NULL;
- }
- if(mm) *mm = m;
-
- // make sure the person exist
- REGISTRY_PERSON *p = registry_person_find(person_guid);
- if(!p) {
- info("Registry Request Verification: person not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
- return NULL;
- }
- if(pp) *pp = p;
-
- REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, url);
- if(!pu) {
- info("Registry Request Verification: URL not found for person, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
- return NULL;
- }
- return pu;
-}
-
-
-// ----------------------------------------------------------------------------
-// REGISTRY REQUESTS
-
-REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when) {
- debug(D_REGISTRY, "registry_request_access('%s', '%s', '%s'): NEW REQUEST", (person_guid)?person_guid:"", machine_guid, url);
-
- REGISTRY_MACHINE *m = registry_machine_get(machine_guid, when);
- if(!m) return NULL;
-
- // make sure the name is valid
- size_t namelen;
- name = registry_fix_machine_name(name, &namelen);
-
- size_t urllen;
- url = registry_fix_url(url, &urllen);
-
- REGISTRY_PERSON *p = registry_person_get(person_guid, when);
-
- REGISTRY_URL *u = registry_url_get(url, urllen);
- registry_person_link_to_url(p, m, u, name, namelen, when);
- registry_machine_link_to_url(m, u, when);
-
- registry_log('A', p, m, u, name);
-
- registry.usages_count++;
-
- return p;
-}
-
-REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) {
- (void) when;
-
- REGISTRY_PERSON *p = NULL;
- REGISTRY_MACHINE *m = NULL;
- REGISTRY_PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m);
- if(!pu || !p || !m) return NULL;
-
- // normalize the url
- delete_url = registry_fix_url(delete_url, NULL);
-
- // make sure the user is not deleting the url it uses
- if(!strcmp(delete_url, pu->url->url)) {
- info("Registry Delete Request: delete URL is the one currently accessed, person: '%s', machine '%s', url '%s', delete url '%s'"
- , p->guid, m->guid, pu->url->url, delete_url);
- return NULL;
- }
-
- REGISTRY_PERSON_URL *dpu = registry_person_url_index_find(p, delete_url);
- if(!dpu) {
- info("Registry Delete Request: URL not found for person: '%s', machine '%s', url '%s', delete url '%s'", p->guid
- , m->guid, pu->url->url, delete_url);
- return NULL;
- }
-
- registry_log('D', p, m, pu->url, dpu->url->url);
- registry_person_unlink_from_url(p, dpu);
-
- return p;
-}
-
-
-// a structure to pass to the dictionary_get_all() callback handler
-struct machine_request_callback_data {
- REGISTRY_MACHINE *find_this_machine;
- REGISTRY_PERSON_URL *result;
-};
-
-// the callback function
-// this will be run for every PERSON_URL of this PERSON
-static int machine_request_callback(void *entry, void *data) {
- REGISTRY_PERSON_URL *mypu = (REGISTRY_PERSON_URL *)entry;
- struct machine_request_callback_data *myrdata = (struct machine_request_callback_data *)data;
-
- if(mypu->machine == myrdata->find_this_machine) {
- myrdata->result = mypu;
- return -1; // this will also stop the walk through
- }
-
- return 0; // continue
-}
-
-REGISTRY_MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) {
- (void)when;
-
- char mbuf[GUID_LEN + 1];
-
- REGISTRY_PERSON *p = NULL;
- REGISTRY_MACHINE *m = NULL;
- REGISTRY_PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m);
- if(!pu || !p || !m) return NULL;
-
- // make sure the machine GUID is valid
- if(regenerate_guid(request_machine, mbuf) == -1) {
- info("Registry Machine URLs request: invalid machine GUID, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine);
- return NULL;
- }
- request_machine = mbuf;
-
- // make sure the machine exists
- m = registry_machine_find(request_machine);
- if(!m) {
- info("Registry Machine URLs request: machine not found, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, machine_guid, pu->url->url, request_machine);
- return NULL;
- }
-
- // Verify the user has in the past accessed this machine
- // We will walk through the PERSON_URLs to find the machine
- // linking to our machine
-
- // a structure to pass to the dictionary_get_all() callback handler
- struct machine_request_callback_data rdata = { m, NULL };
-
- // request a walk through on the dictionary
- avl_traverse(&p->person_urls, machine_request_callback, &rdata);
-
- if(rdata.result)
- return m;
-
- return NULL;
-}
-
-
-// ----------------------------------------------------------------------------
-// REGISTRY THIS MACHINE UNIQUE ID
-
-static inline int is_machine_guid_blacklisted(const char *guid) {
- // these are machine GUIDs that have been included in distribution packages.
- // we blacklist them here, so that the next version of netdata will generate
- // new ones.
-
- if(!strcmp(guid, "8a795b0c-2311-11e6-8563-000c295076a6")
- || !strcmp(guid, "4aed1458-1c3e-11e6-a53f-000c290fc8f5")
- ) {
- error("Blacklisted machine GUID '%s' found.", guid);
- return 1;
- }
-
- return 0;
-}
-
-char *registry_get_this_machine_hostname(void) {
- return registry.hostname;
-}
-
-char *registry_get_this_machine_guid(void) {
- static char guid[GUID_LEN + 1] = "";
-
- if(likely(guid[0]))
- return guid;
-
- // read it from disk
- int fd = open(registry.machine_guid_filename, O_RDONLY);
- if(fd != -1) {
- char buf[GUID_LEN + 1];
- if(read(fd, buf, GUID_LEN) != GUID_LEN)
- error("Failed to read machine GUID from '%s'", registry.machine_guid_filename);
- else {
- buf[GUID_LEN] = '\0';
- if(regenerate_guid(buf, guid) == -1) {
- error("Failed to validate machine GUID '%s' from '%s'. Ignoring it - this might mean this netdata will appear as duplicate in the registry.",
- buf, registry.machine_guid_filename);
-
- guid[0] = '\0';
- }
- else if(is_machine_guid_blacklisted(guid))
- guid[0] = '\0';
- }
- close(fd);
- }
-
- // generate a new one?
- if(!guid[0]) {
- uuid_t uuid;
-
- uuid_generate_time(uuid);
- uuid_unparse_lower(uuid, guid);
- guid[GUID_LEN] = '\0';
-
- // save it
- fd = open(registry.machine_guid_filename, O_WRONLY|O_CREAT|O_TRUNC, 444);
- if(fd == -1)
- fatal("Cannot create unique machine id file '%s'. Please fix this.", registry.machine_guid_filename);
-
- if(write(fd, guid, GUID_LEN) != GUID_LEN)
- fatal("Cannot write the unique machine id file '%s'. Please fix this.", registry.machine_guid_filename);
-
- close(fd);
- }
-
- setenv("NETDATA_REGISTRY_UNIQUE_ID", guid, 1);
-
- return guid;
-}
diff --git a/src/registry_internals.h b/src/registry_internals.h
deleted file mode 100644
index cceaf292b..000000000
--- a/src/registry_internals.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "common.h"
-
-#ifndef NETDATA_REGISTRY_INTERNALS_H_H
-#define NETDATA_REGISTRY_INTERNALS_H_H
-
-#define REGISTRY_URL_FLAGS_DEFAULT 0x00
-#define REGISTRY_URL_FLAGS_EXPIRED 0x01
-
-#define DICTIONARY_FLAGS (DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE | DICTIONARY_FLAG_NAME_LINK_DONT_CLONE | DICTIONARY_FLAG_SINGLE_THREADED)
-
-// ----------------------------------------------------------------------------
-// COMMON structures
-
-struct registry {
- int enabled;
-
- // entries counters / statistics
- unsigned long long persons_count;
- unsigned long long machines_count;
- unsigned long long usages_count;
- unsigned long long urls_count;
- unsigned long long persons_urls_count;
- unsigned long long machines_urls_count;
- unsigned long long log_count;
-
- // memory counters / statistics
- unsigned long long persons_memory;
- unsigned long long machines_memory;
- unsigned long long urls_memory;
- unsigned long long persons_urls_memory;
- unsigned long long machines_urls_memory;
-
- // configuration
- unsigned long long save_registry_every_entries;
- char *registry_domain;
- char *hostname;
- char *registry_to_announce;
- time_t persons_expiration; // seconds to expire idle persons
- int verify_cookies_redirects;
-
- size_t max_url_length;
- size_t max_name_length;
-
- // file/path names
- char *pathname;
- char *db_filename;
- char *log_filename;
- char *machine_guid_filename;
-
- // open files
- FILE *log_fp;
-
- // the database
- DICTIONARY *persons; // dictionary of REGISTRY_PERSON *, with key the REGISTRY_PERSON.guid
- DICTIONARY *machines; // dictionary of REGISTRY_MACHINE *, with key the REGISTRY_MACHINE.guid
-
- avl_tree registry_urls_root_index;
-
- netdata_mutex_t lock;
-};
-
-#include "registry_url.h"
-#include "registry_machine.h"
-#include "registry_person.h"
-#include "registry.h"
-
-extern struct registry registry;
-
-// REGISTRY LOW-LEVEL REQUESTS (in registry-internals.c)
-extern REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when);
-extern REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when);
-extern REGISTRY_MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when);
-
-// REGISTRY LOG (in registry_log.c)
-extern void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name);
-extern int registry_log_open(void);
-extern void registry_log_close(void);
-extern void registry_log_recreate(void);
-extern ssize_t registry_log_load(void);
-
-// REGISTRY DB (in registry_db.c)
-extern int registry_db_save(void);
-extern size_t registry_db_load(void);
-extern int registry_db_should_be_saved(void);
-
-#endif //NETDATA_REGISTRY_INTERNALS_H_H
diff --git a/src/registry_log.c b/src/registry_log.c
deleted file mode 100644
index cca43b09f..000000000
--- a/src/registry_log.c
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "registry_internals.h"
-
-void registry_log(char action, REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name) {
- if(likely(registry.log_fp)) {
- if(unlikely(fprintf(registry.log_fp, "%c\t%08x\t%s\t%s\t%s\t%s\n",
- action,
- p->last_t,
- p->guid,
- m->guid,
- name,
- u->url) < 0))
- error("Registry: failed to save log. Registry data may be lost in case of abnormal restart.");
-
- // we increase the counter even on failures
- // so that the registry will be saved periodically
- registry.log_count++;
-
- // this must be outside the log_lock(), or a deadlock will happen.
- // registry_db_save() checks the same inside the log_lock, so only
- // one thread will save the db
- if(unlikely(registry_db_should_be_saved()))
- registry_db_save();
- }
-}
-
-int registry_log_open(void) {
- if(registry.log_fp)
- fclose(registry.log_fp);
-
- registry.log_fp = fopen(registry.log_filename, "a");
- if(registry.log_fp) {
- if (setvbuf(registry.log_fp, NULL, _IOLBF, 0) != 0)
- error("Cannot set line buffering on registry log file.");
- return 0;
- }
-
- error("Cannot open registry log file '%s'. Registry data will be lost in case of netdata or server crash.", registry.log_filename);
- return -1;
-}
-
-void registry_log_close(void) {
- if(registry.log_fp) {
- fclose(registry.log_fp);
- registry.log_fp = NULL;
- }
-}
-
-void registry_log_recreate(void) {
- if(registry.log_fp != NULL) {
- registry_log_close();
-
- // open it with truncate
- registry.log_fp = fopen(registry.log_filename, "w");
- if(registry.log_fp) fclose(registry.log_fp);
- else error("Cannot truncate registry log '%s'", registry.log_filename);
-
- registry.log_fp = NULL;
- registry_log_open();
- }
-}
-
-ssize_t registry_log_load(void) {
- ssize_t line = -1;
-
- // closing the log is required here
- // otherwise we will append to it the values we read
- registry_log_close();
-
- debug(D_REGISTRY, "Registry: loading active db from: %s", registry.log_filename);
- FILE *fp = fopen(registry.log_filename, "r");
- if(!fp)
- error("Registry: cannot open registry file: %s", registry.log_filename);
- else {
- char *s, buf[4096 + 1];
- line = 0;
- size_t len = 0;
-
- while ((s = fgets_trim_len(buf, 4096, fp, &len))) {
- line++;
-
- switch (s[0]) {
- case 'A': // accesses
- case 'D': // deletes
-
- // verify it is valid
- if (unlikely(len < 85 || s[1] != '\t' || s[10] != '\t' || s[47] != '\t' || s[84] != '\t')) {
- error("Registry: log line %zd is wrong (len = %zu).", line, len);
- continue;
- }
- s[1] = s[10] = s[47] = s[84] = '\0';
-
- // get the variables
- time_t when = strtoul(&s[2], NULL, 16);
- char *person_guid = &s[11];
- char *machine_guid = &s[48];
- char *name = &s[85];
-
- // skip the name to find the url
- char *url = name;
- while(*url && *url != '\t') url++;
- if(!*url) {
- error("Registry: log line %zd does not have a url.", line);
- continue;
- }
- *url++ = '\0';
-
- // make sure the person exists
- // without this, a new person guid will be created
- REGISTRY_PERSON *p = registry_person_find(person_guid);
- if(!p) p = registry_person_allocate(person_guid, when);
-
- if(s[0] == 'A')
- registry_request_access(p->guid, machine_guid, url, name, when);
- else
- registry_request_delete(p->guid, machine_guid, url, name, when);
-
- registry.log_count++;
- break;
-
- default:
- error("Registry: ignoring line %zd of filename '%s': %s.", line, registry.log_filename, s);
- break;
- }
- }
-
- fclose(fp);
- }
-
- // open the log again
- registry_log_open();
-
- return line;
-}
diff --git a/src/registry_machine.c b/src/registry_machine.c
deleted file mode 100644
index 6dc8200d3..000000000
--- a/src/registry_machine.c
+++ /dev/null
@@ -1,101 +0,0 @@
-#include "registry_internals.h"
-
-// ----------------------------------------------------------------------------
-// MACHINE
-
-REGISTRY_MACHINE *registry_machine_find(const char *machine_guid) {
- debug(D_REGISTRY, "Registry: registry_machine_find('%s')", machine_guid);
- return dictionary_get(registry.machines, machine_guid);
-}
-
-REGISTRY_MACHINE_URL *registry_machine_url_allocate(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when) {
- debug(D_REGISTRY, "registry_machine_url_allocate('%s', '%s'): allocating %zu bytes", m->guid, u->url, sizeof(REGISTRY_MACHINE_URL));
-
- REGISTRY_MACHINE_URL *mu = mallocz(sizeof(REGISTRY_MACHINE_URL));
-
- mu->first_t = mu->last_t = (uint32_t)when;
- mu->usages = 1;
- mu->url = u;
- mu->flags = REGISTRY_URL_FLAGS_DEFAULT;
-
- registry.machines_urls_memory += sizeof(REGISTRY_MACHINE_URL);
-
- debug(D_REGISTRY, "registry_machine_url_allocate('%s', '%s'): indexing URL in machine", m->guid, u->url);
- dictionary_set(m->machine_urls, u->url, mu, sizeof(REGISTRY_MACHINE_URL));
-
- registry_url_link(u);
-
- return mu;
-}
-
-REGISTRY_MACHINE *registry_machine_allocate(const char *machine_guid, time_t when) {
- debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating new machine, sizeof(MACHINE)=%zu", machine_guid, sizeof(REGISTRY_MACHINE));
-
- REGISTRY_MACHINE *m = mallocz(sizeof(REGISTRY_MACHINE));
-
- strncpyz(m->guid, machine_guid, GUID_LEN);
-
- debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating dictionary of urls", machine_guid);
- m->machine_urls = dictionary_create(DICTIONARY_FLAGS);
-
- m->first_t = m->last_t = (uint32_t)when;
- m->usages = 0;
-
- registry.machines_memory += sizeof(REGISTRY_MACHINE);
-
- registry.machines_count++;
- dictionary_set(registry.machines, m->guid, m, sizeof(REGISTRY_MACHINE));
-
- return m;
-}
-
-// 1. validate machine GUID
-// 2. if it is valid, find it or create it and return it
-// 3. if it is not valid, return NULL
-REGISTRY_MACHINE *registry_machine_get(const char *machine_guid, time_t when) {
- REGISTRY_MACHINE *m = NULL;
-
- if(likely(machine_guid && *machine_guid)) {
- // validate it is a GUID
- char buf[GUID_LEN + 1];
- if(unlikely(regenerate_guid(machine_guid, buf) == -1))
- info("Registry: machine guid '%s' is not a valid guid. Ignoring it.", machine_guid);
- else {
- machine_guid = buf;
- m = registry_machine_find(machine_guid);
- if(!m) m = registry_machine_allocate(machine_guid, when);
- }
- }
-
- return m;
-}
-
-
-// ----------------------------------------------------------------------------
-// LINKING OF OBJECTS
-
-REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when) {
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): searching for URL in machine", m->guid, u->url);
-
- REGISTRY_MACHINE_URL *mu = dictionary_get(m->machine_urls, u->url);
- if(!mu) {
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): not found", m->guid, u->url);
- mu = registry_machine_url_allocate(m, u, when);
- registry.machines_urls_count++;
- }
- else {
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): found", m->guid, u->url);
- mu->usages++;
- if(likely(mu->last_t < (uint32_t)when)) mu->last_t = (uint32_t)when;
- }
-
- m->usages++;
- if(likely(m->last_t < (uint32_t)when)) m->last_t = (uint32_t)when;
-
- if(mu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): accessing an expired URL.", m->guid, u->url);
- mu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
- }
-
- return mu;
-}
diff --git a/src/registry_machine.h b/src/registry_machine.h
deleted file mode 100644
index be824d168..000000000
--- a/src/registry_machine.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef NETDATA_REGISTRY_MACHINE_H
-#define NETDATA_REGISTRY_MACHINE_H
-
-#include "registry_internals.h"
-
-// ----------------------------------------------------------------------------
-// MACHINE structures
-
-// For each MACHINE-URL pair we keep this
-struct registry_machine_url {
- REGISTRY_URL *url; // de-duplicated URL
-
- uint8_t flags;
-
- uint32_t first_t; // the first time we saw this
- uint32_t last_t; // the last time we saw this
- uint32_t usages; // how many times this has been accessed
-};
-typedef struct registry_machine_url REGISTRY_MACHINE_URL;
-
-// A machine
-struct registry_machine {
- char guid[GUID_LEN + 1]; // the GUID
-
- uint32_t links; // the number of REGISTRY_PERSON_URL linked to this machine
-
- DICTIONARY *machine_urls; // MACHINE_URL *
-
- uint32_t first_t; // the first time we saw this
- uint32_t last_t; // the last time we saw this
- uint32_t usages; // how many times this has been accessed
-};
-typedef struct registry_machine REGISTRY_MACHINE;
-
-extern REGISTRY_MACHINE *registry_machine_find(const char *machine_guid);
-extern REGISTRY_MACHINE_URL *registry_machine_url_allocate(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when);
-extern REGISTRY_MACHINE *registry_machine_allocate(const char *machine_guid, time_t when);
-extern REGISTRY_MACHINE *registry_machine_get(const char *machine_guid, time_t when);
-extern REGISTRY_MACHINE_URL *registry_machine_link_to_url(REGISTRY_MACHINE *m, REGISTRY_URL *u, time_t when);
-
-#endif //NETDATA_REGISTRY_MACHINE_H
diff --git a/src/registry_person.c b/src/registry_person.c
deleted file mode 100644
index d8b6cd98a..000000000
--- a/src/registry_person.c
+++ /dev/null
@@ -1,264 +0,0 @@
-#include "registry_internals.h"
-
-// ----------------------------------------------------------------------------
-// PERSON_URL INDEX
-
-int person_url_compare(void *a, void *b) {
- register uint32_t hash1 = ((REGISTRY_PERSON_URL *)a)->url->hash;
- register uint32_t hash2 = ((REGISTRY_PERSON_URL *)b)->url->hash;
-
- if(hash1 < hash2) return -1;
- else if(hash1 > hash2) return 1;
- else return strcmp(((REGISTRY_PERSON_URL *)a)->url->url, ((REGISTRY_PERSON_URL *)b)->url->url);
-}
-
-inline REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, const char *url) {
- debug(D_REGISTRY, "Registry: registry_person_url_index_find('%s', '%s')", p->guid, url);
-
- char buf[sizeof(REGISTRY_URL) + strlen(url)];
-
- REGISTRY_URL *u = (REGISTRY_URL *)&buf;
- strcpy(u->url, url);
- u->hash = simple_hash(u->url);
-
- REGISTRY_PERSON_URL tpu = { .url = u };
-
- REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)avl_search(&p->person_urls, (void *)&tpu);
- return pu;
-}
-
-inline REGISTRY_PERSON_URL *registry_person_url_index_add(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
- debug(D_REGISTRY, "Registry: registry_person_url_index_add('%s', '%s')", p->guid, pu->url->url);
- REGISTRY_PERSON_URL *tpu = (REGISTRY_PERSON_URL *)avl_insert(&(p->person_urls), (avl *)(pu));
- if(tpu != pu)
- error("Registry: registry_person_url_index_add('%s', '%s') already exists as '%s'", p->guid, pu->url->url, tpu->url->url);
-
- return tpu;
-}
-
-inline REGISTRY_PERSON_URL *registry_person_url_index_del(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
- debug(D_REGISTRY, "Registry: registry_person_url_index_del('%s', '%s')", p->guid, pu->url->url);
- REGISTRY_PERSON_URL *tpu = (REGISTRY_PERSON_URL *)avl_remove(&(p->person_urls), (avl *)(pu));
- if(!tpu)
- error("Registry: registry_person_url_index_del('%s', '%s') deleted nothing", p->guid, pu->url->url);
- else if(tpu != pu)
- error("Registry: registry_person_url_index_del('%s', '%s') deleted wrong URL '%s'", p->guid, pu->url->url, tpu->url->url);
-
- return tpu;
-}
-
-// ----------------------------------------------------------------------------
-// PERSON_URL
-
-REGISTRY_PERSON_URL *registry_person_url_allocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when) {
- debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url, sizeof(REGISTRY_PERSON_URL) + namelen);
-
- // protection from too big names
- if(namelen > registry.max_name_length)
- namelen = registry.max_name_length;
-
- REGISTRY_PERSON_URL *pu = mallocz(sizeof(REGISTRY_PERSON_URL) + namelen);
-
- // a simple strcpy() should do the job
- // but I prefer to be safe, since the caller specified urllen
- strncpyz(pu->machine_name, name, namelen);
-
- pu->machine = m;
- pu->first_t = pu->last_t = (uint32_t)when;
- pu->usages = 1;
- pu->url = u;
- pu->flags = REGISTRY_URL_FLAGS_DEFAULT;
- m->links++;
-
- registry.persons_urls_memory += sizeof(REGISTRY_PERSON_URL) + namelen;
-
- debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, u->url);
- REGISTRY_PERSON_URL *tpu = registry_person_url_index_add(p, pu);
- if(tpu != pu) {
- error("Registry: Attempted to add duplicate person url '%s' with name '%s' to person '%s'", u->url, name, p->guid);
- free(pu);
- pu = tpu;
- }
- else
- registry_url_link(u);
-
- return pu;
-}
-
-void registry_person_url_free(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
- debug(D_REGISTRY, "registry_person_url_free('%s', '%s')", p->guid, pu->url->url);
-
- REGISTRY_PERSON_URL *tpu = registry_person_url_index_del(p, pu);
- if(tpu) {
- registry_url_unlink(tpu->url);
- tpu->machine->links--;
- registry.persons_urls_memory -= sizeof(REGISTRY_PERSON_URL) + strlen(tpu->machine_name);
- freez(tpu);
- }
-}
-
-// this function is needed to change the name of a PERSON_URL
-REGISTRY_PERSON_URL *registry_person_url_reallocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when, REGISTRY_PERSON_URL *pu) {
- debug(D_REGISTRY, "registry_person_url_reallocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url, sizeof(REGISTRY_PERSON_URL) + namelen);
-
- // keep a backup
- REGISTRY_PERSON_URL pu2 = {
- .first_t = pu->first_t,
- .last_t = pu->last_t,
- .usages = pu->usages,
- .flags = pu->flags,
- .machine = pu->machine,
- .machine_name = ""
- };
-
- // remove the existing one from the index
- registry_person_url_free(p, pu);
- pu = &pu2;
-
- // allocate a new one
- REGISTRY_PERSON_URL *tpu = registry_person_url_allocate(p, m, u, name, namelen, when);
- tpu->first_t = pu->first_t;
- tpu->last_t = pu->last_t;
- tpu->usages = pu->usages;
- tpu->flags = pu->flags;
-
- return tpu;
-}
-
-
-// ----------------------------------------------------------------------------
-// PERSON
-
-REGISTRY_PERSON *registry_person_find(const char *person_guid) {
- debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid);
- return dictionary_get(registry.persons, person_guid);
-}
-
-REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when) {
- debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(REGISTRY_PERSON));
-
- REGISTRY_PERSON *p = mallocz(sizeof(REGISTRY_PERSON));
- if(!person_guid) {
- for(;;) {
- uuid_t uuid;
- uuid_generate(uuid);
- uuid_unparse_lower(uuid, p->guid);
-
- debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid);
- if (!dictionary_get(registry.persons, p->guid)) {
- debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid);
- break;
- }
- else
- info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid);
- }
- }
- else
- strncpyz(p->guid, person_guid, GUID_LEN);
-
- debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): creating dictionary of urls", p->guid);
- avl_init(&p->person_urls, person_url_compare);
-
- p->first_t = p->last_t = (uint32_t)when;
- p->usages = 0;
-
- registry.persons_memory += sizeof(REGISTRY_PERSON);
-
- registry.persons_count++;
- dictionary_set(registry.persons, p->guid, p, sizeof(REGISTRY_PERSON));
-
- return p;
-}
-
-
-// 1. validate person GUID
-// 2. if it is valid, find it
-// 3. if it is not valid, create a new one
-// 4. return it
-REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when) {
- debug(D_REGISTRY, "Registry: registry_person_get('%s'): creating dictionary of urls", person_guid);
-
- REGISTRY_PERSON *p = NULL;
-
- if(person_guid && *person_guid) {
- char buf[GUID_LEN + 1];
- // validate it is a GUID
- if(unlikely(regenerate_guid(person_guid, buf) == -1))
- info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid);
- else {
- person_guid = buf;
- p = registry_person_find(person_guid);
- }
- }
-
- if(!p) p = registry_person_allocate(NULL, when);
-
- return p;
-}
-
-void registry_person_del(REGISTRY_PERSON *p) {
- debug(D_REGISTRY, "Registry: registry_person_del('%s'): creating dictionary of urls", p->guid);
-
- while(p->person_urls.root)
- registry_person_unlink_from_url(p, (REGISTRY_PERSON_URL *)p->person_urls.root);
-
- debug(D_REGISTRY, "Registry: deleting person '%s' from persons registry", p->guid);
- dictionary_del(registry.persons, p->guid);
-
- debug(D_REGISTRY, "Registry: freeing person '%s'", p->guid);
- freez(p);
-}
-
-// ----------------------------------------------------------------------------
-// LINKING OF OBJECTS
-
-REGISTRY_PERSON_URL *registry_person_link_to_url(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when) {
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, u->url);
-
- REGISTRY_PERSON_URL *pu = registry_person_url_index_find(p, u->url);
- if(!pu) {
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url);
- pu = registry_person_url_allocate(p, m, u, name, namelen, when);
- registry.persons_urls_count++;
- }
- else {
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url);
- pu->usages++;
- if(likely(pu->last_t < (uint32_t)when)) pu->last_t = (uint32_t)when;
-
- if(pu->machine != m) {
- REGISTRY_MACHINE_URL *mu = dictionary_get(pu->machine->machine_urls, u->url);
- if(mu) {
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.",
- p->guid, m->guid, u->url, pu->machine->guid);
- mu->flags |= REGISTRY_URL_FLAGS_EXPIRED;
- }
- else {
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - but the URL is not linked to the old machine.",
- p->guid, m->guid, u->url, pu->machine->guid);
- }
-
- pu->machine->links--;
- pu->machine = m;
- }
-
- if(strcmp(pu->machine_name, name) != 0) {
- // the name of the PERSON_URL has changed !
- pu = registry_person_url_reallocate(p, m, u, name, namelen, when, pu);
- }
- }
-
- p->usages++;
- if(likely(p->last_t < (uint32_t)when)) p->last_t = (uint32_t)when;
-
- if(pu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): accessing an expired URL. Re-enabling URL.", p->guid, m->guid, u->url);
- pu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
- }
-
- return pu;
-}
-
-void registry_person_unlink_from_url(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) {
- registry_person_url_free(p, pu);
-}
diff --git a/src/registry_person.h b/src/registry_person.h
deleted file mode 100644
index 5f6cc2443..000000000
--- a/src/registry_person.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef NETDATA_REGISTRY_PERSON_H
-#define NETDATA_REGISTRY_PERSON_H
-
-#include "registry_internals.h"
-
-// ----------------------------------------------------------------------------
-// PERSON structures
-
-// for each PERSON-URL pair we keep this
-struct registry_person_url {
- avl avl; // binary tree node
-
- REGISTRY_URL *url; // de-duplicated URL
- REGISTRY_MACHINE *machine; // link the MACHINE of this URL
-
- uint8_t flags;
-
- uint32_t first_t; // the first time we saw this
- uint32_t last_t; // the last time we saw this
- uint32_t usages; // how many times this has been accessed
-
- char machine_name[1]; // the name of the machine, as known by the user
- // dynamically allocated to fit properly
-};
-typedef struct registry_person_url REGISTRY_PERSON_URL;
-
-// A person
-struct registry_person {
- char guid[GUID_LEN + 1]; // the person GUID
-
- avl_tree person_urls; // dictionary of PERSON_URLs
-
- uint32_t first_t; // the first time we saw this
- uint32_t last_t; // the last time we saw this
- uint32_t usages; // how many times this has been accessed
-
- //uint32_t flags;
- //char *email;
-};
-typedef struct registry_person REGISTRY_PERSON;
-
-// PERSON_URL
-extern REGISTRY_PERSON_URL *registry_person_url_index_find(REGISTRY_PERSON *p, const char *url);
-extern REGISTRY_PERSON_URL *registry_person_url_index_add(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) NEVERNULL WARNUNUSED;
-extern REGISTRY_PERSON_URL *registry_person_url_index_del(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu) WARNUNUSED;
-
-extern REGISTRY_PERSON_URL *registry_person_url_allocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when);
-extern REGISTRY_PERSON_URL *registry_person_url_reallocate(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when, REGISTRY_PERSON_URL *pu);
-
-// PERSON
-extern REGISTRY_PERSON *registry_person_find(const char *person_guid);
-extern REGISTRY_PERSON *registry_person_allocate(const char *person_guid, time_t when);
-extern REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when);
-extern void registry_person_del(REGISTRY_PERSON *p);
-
-// LINKING PERSON -> PERSON_URL
-extern REGISTRY_PERSON_URL *registry_person_link_to_url(REGISTRY_PERSON *p, REGISTRY_MACHINE *m, REGISTRY_URL *u, char *name, size_t namelen, time_t when);
-extern void registry_person_unlink_from_url(REGISTRY_PERSON *p, REGISTRY_PERSON_URL *pu);
-
-#endif //NETDATA_REGISTRY_PERSON_H
diff --git a/src/registry_url.c b/src/registry_url.c
deleted file mode 100644
index 52d36a898..000000000
--- a/src/registry_url.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include "registry_internals.h"
-
-// ----------------------------------------------------------------------------
-// REGISTRY_URL
-
-int registry_url_compare(void *a, void *b) {
- if(((REGISTRY_URL *)a)->hash < ((REGISTRY_URL *)b)->hash) return -1;
- else if(((REGISTRY_URL *)a)->hash > ((REGISTRY_URL *)b)->hash) return 1;
- else return strcmp(((REGISTRY_URL *)a)->url, ((REGISTRY_URL *)b)->url);
-}
-
-inline REGISTRY_URL *registry_url_index_add(REGISTRY_URL *u) {
- return (REGISTRY_URL *)avl_insert(&(registry.registry_urls_root_index), (avl *)(u));
-}
-
-inline REGISTRY_URL *registry_url_index_del(REGISTRY_URL *u) {
- return (REGISTRY_URL *)avl_remove(&(registry.registry_urls_root_index), (avl *)(u));
-}
-
-REGISTRY_URL *registry_url_get(const char *url, size_t urllen) {
- // protection from too big URLs
- if(urllen > registry.max_url_length)
- urllen = registry.max_url_length;
-
- debug(D_REGISTRY, "Registry: registry_url_get('%s', %zu)", url, urllen);
-
- char buf[sizeof(REGISTRY_URL) + urllen]; // no need for +1, 1 is already in REGISTRY_URL
- REGISTRY_URL *n = (REGISTRY_URL *)&buf[0];
- n->len = (uint16_t)urllen;
- strncpyz(n->url, url, n->len);
- n->hash = simple_hash(n->url);
-
- REGISTRY_URL *u = (REGISTRY_URL *)avl_search(&(registry.registry_urls_root_index), (avl *)n);
- if(!u) {
- debug(D_REGISTRY, "Registry: registry_url_get('%s', %zu): allocating %zu bytes", url, urllen, sizeof(REGISTRY_URL) + urllen);
- u = callocz(1, sizeof(REGISTRY_URL) + urllen); // no need for +1, 1 is already in REGISTRY_URL
-
- // a simple strcpy() should do the job
- // but I prefer to be safe, since the caller specified urllen
- u->len = (uint16_t)urllen;
- strncpyz(u->url, url, u->len);
- u->links = 0;
- u->hash = simple_hash(u->url);
-
- registry.urls_memory += sizeof(REGISTRY_URL) + urllen; // no need for +1, 1 is already in REGISTRY_URL
-
- debug(D_REGISTRY, "Registry: registry_url_get('%s'): indexing it", url);
- n = registry_url_index_add(u);
- if(n != u) {
- error("INTERNAL ERROR: registry_url_get(): url '%s' already exists in the registry as '%s'", u->url, n->url);
- free(u);
- u = n;
- }
- else
- registry.urls_count++;
- }
-
- return u;
-}
-
-void registry_url_link(REGISTRY_URL *u) {
- u->links++;
- debug(D_REGISTRY, "Registry: registry_url_link('%s'): URL has now %u links", u->url, u->links);
-}
-
-void registry_url_unlink(REGISTRY_URL *u) {
- u->links--;
- if(!u->links) {
- debug(D_REGISTRY, "Registry: registry_url_unlink('%s'): No more links for this URL", u->url);
- REGISTRY_URL *n = registry_url_index_del(u);
- if(!n) {
- error("INTERNAL ERROR: registry_url_unlink('%s'): cannot find url in index", u->url);
- }
- else {
- if(n != u) {
- error("INTERNAL ERROR: registry_url_unlink('%s'): deleted different url '%s'", u->url, n->url);
- }
-
- registry.urls_memory -= sizeof(REGISTRY_URL) + n->len; // no need for +1, 1 is already in REGISTRY_URL
- freez(n);
- }
- }
- else
- debug(D_REGISTRY, "Registry: registry_url_unlink('%s'): URL has %u links left", u->url, u->links);
-}
diff --git a/src/registry_url.h b/src/registry_url.h
deleted file mode 100644
index 5ac52f5a5..000000000
--- a/src/registry_url.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef NETDATA_REGISTRY_URL_H
-#define NETDATA_REGISTRY_URL_H
-
-#include "registry_internals.h"
-
-// ----------------------------------------------------------------------------
-// URL structures
-// Save memory by de-duplicating URLs
-// so instead of storing URLs all over the place
-// we store them here and we keep pointers elsewhere
-
-struct registry_url {
- avl avl;
- uint32_t hash; // the index hash
-
- uint32_t links; // the number of links to this URL - when none is left, we free it
-
- uint16_t len; // the length of the URL in bytes
- char url[1]; // the URL - dynamically allocated to more size
-};
-typedef struct registry_url REGISTRY_URL;
-
-// REGISTRY_URL INDEX
-extern int registry_url_compare(void *a, void *b);
-extern REGISTRY_URL *registry_url_index_del(REGISTRY_URL *u) WARNUNUSED;
-extern REGISTRY_URL *registry_url_index_add(REGISTRY_URL *u) NEVERNULL WARNUNUSED;
-
-// REGISTRY_URL MANAGEMENT
-extern REGISTRY_URL *registry_url_get(const char *url, size_t urllen) NEVERNULL;
-extern void registry_url_link(REGISTRY_URL *u);
-extern void registry_url_unlink(REGISTRY_URL *u);
-
-#endif //NETDATA_REGISTRY_URL_H
diff --git a/src/rrd.c b/src/rrd.c
deleted file mode 100644
index 3be2d8e41..000000000
--- a/src/rrd.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#define NETDATA_RRD_INTERNALS 1
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// globals
-
-/*
-// if not zero it gives the time (in seconds) to remove un-updated dimensions
-// DO NOT ENABLE
-// if dimensions are removed, the chart generation will have to run again
-int rrd_delete_unupdated_dimensions = 0;
-*/
-
-int default_rrd_update_every = UPDATE_EVERY;
-int default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES;
-RRD_MEMORY_MODE default_rrd_memory_mode = RRD_MEMORY_MODE_SAVE;
-int gap_when_lost_iterations_above = 1;
-
-
-// ----------------------------------------------------------------------------
-// RRD - memory modes
-
-inline const char *rrd_memory_mode_name(RRD_MEMORY_MODE id) {
- switch(id) {
- case RRD_MEMORY_MODE_RAM:
- return RRD_MEMORY_MODE_RAM_NAME;
-
- case RRD_MEMORY_MODE_MAP:
- return RRD_MEMORY_MODE_MAP_NAME;
-
- case RRD_MEMORY_MODE_NONE:
- return RRD_MEMORY_MODE_NONE_NAME;
-
- case RRD_MEMORY_MODE_SAVE:
- return RRD_MEMORY_MODE_SAVE_NAME;
-
- case RRD_MEMORY_MODE_ALLOC:
- return RRD_MEMORY_MODE_ALLOC_NAME;
- }
-
- return RRD_MEMORY_MODE_SAVE_NAME;
-}
-
-RRD_MEMORY_MODE rrd_memory_mode_id(const char *name) {
- if(unlikely(!strcmp(name, RRD_MEMORY_MODE_RAM_NAME)))
- return RRD_MEMORY_MODE_RAM;
-
- else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_MAP_NAME)))
- return RRD_MEMORY_MODE_MAP;
-
- else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_NONE_NAME)))
- return RRD_MEMORY_MODE_NONE;
-
- else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_ALLOC_NAME)))
- return RRD_MEMORY_MODE_ALLOC;
-
- return RRD_MEMORY_MODE_SAVE;
-}
-
-
-// ----------------------------------------------------------------------------
-// RRD - algorithms types
-
-RRD_ALGORITHM rrd_algorithm_id(const char *name) {
- if(strcmp(name, RRD_ALGORITHM_INCREMENTAL_NAME) == 0)
- return RRD_ALGORITHM_INCREMENTAL;
-
- else if(strcmp(name, RRD_ALGORITHM_ABSOLUTE_NAME) == 0)
- return RRD_ALGORITHM_ABSOLUTE;
-
- else if(strcmp(name, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL_NAME) == 0)
- return RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL;
-
- else if(strcmp(name, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL_NAME) == 0)
- return RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL;
-
- else
- return RRD_ALGORITHM_ABSOLUTE;
-}
-
-const char *rrd_algorithm_name(RRD_ALGORITHM algorithm) {
- switch(algorithm) {
- case RRD_ALGORITHM_ABSOLUTE:
- default:
- return RRD_ALGORITHM_ABSOLUTE_NAME;
-
- case RRD_ALGORITHM_INCREMENTAL:
- return RRD_ALGORITHM_INCREMENTAL_NAME;
-
- case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL:
- return RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL_NAME;
-
- case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL:
- return RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL_NAME;
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// RRD - chart types
-
-inline RRDSET_TYPE rrdset_type_id(const char *name) {
- if(unlikely(strcmp(name, RRDSET_TYPE_AREA_NAME) == 0))
- return RRDSET_TYPE_AREA;
-
- else if(unlikely(strcmp(name, RRDSET_TYPE_STACKED_NAME) == 0))
- return RRDSET_TYPE_STACKED;
-
- else // if(unlikely(strcmp(name, RRDSET_TYPE_LINE_NAME) == 0))
- return RRDSET_TYPE_LINE;
-}
-
-const char *rrdset_type_name(RRDSET_TYPE chart_type) {
- switch(chart_type) {
- case RRDSET_TYPE_LINE:
- default:
- return RRDSET_TYPE_LINE_NAME;
-
- case RRDSET_TYPE_AREA:
- return RRDSET_TYPE_AREA_NAME;
-
- case RRDSET_TYPE_STACKED:
- return RRDSET_TYPE_STACKED_NAME;
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// RRD - cache directory
-
-char *rrdset_cache_dir(RRDHOST *host, const char *id, const char *config_section) {
- char *ret = NULL;
-
- char b[FILENAME_MAX + 1];
- char n[FILENAME_MAX + 1];
- rrdset_strncpyz_name(b, id, FILENAME_MAX);
-
- snprintfz(n, FILENAME_MAX, "%s/%s", host->cache_dir, b);
- ret = config_get(config_section, "cache directory", n);
-
- if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
- int r = mkdir(ret, 0775);
- if(r != 0 && errno != EEXIST)
- error("Cannot create directory '%s'", ret);
- }
-
- return ret;
-}
diff --git a/src/rrd.h b/src/rrd.h
deleted file mode 100644
index d17daacd2..000000000
--- a/src/rrd.h
+++ /dev/null
@@ -1,747 +0,0 @@
-#ifndef NETDATA_RRD_H
-#define NETDATA_RRD_H 1
-
-#define UPDATE_EVERY 1
-#define UPDATE_EVERY_MAX 3600
-
-#define RRD_DEFAULT_HISTORY_ENTRIES 3600
-#define RRD_HISTORY_ENTRIES_MAX (86400*365)
-
-extern int default_rrd_update_every;
-extern int default_rrd_history_entries;
-extern int gap_when_lost_iterations_above;
-
-#define RRD_ID_LENGTH_MAX 200
-
-#define RRDSET_MAGIC "NETDATA RRD SET FILE V019"
-#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V019"
-
-typedef long long total_number;
-#define TOTAL_NUMBER_FORMAT "%lld"
-
-typedef struct rrdhost RRDHOST;
-
-// ----------------------------------------------------------------------------
-// chart types
-
-typedef enum rrdset_type {
- RRDSET_TYPE_LINE = 0,
- RRDSET_TYPE_AREA = 1,
- RRDSET_TYPE_STACKED = 2
-} RRDSET_TYPE;
-
-#define RRDSET_TYPE_LINE_NAME "line"
-#define RRDSET_TYPE_AREA_NAME "area"
-#define RRDSET_TYPE_STACKED_NAME "stacked"
-
-RRDSET_TYPE rrdset_type_id(const char *name);
-const char *rrdset_type_name(RRDSET_TYPE chart_type);
-
-
-// ----------------------------------------------------------------------------
-// memory mode
-
-typedef enum rrd_memory_mode {
- RRD_MEMORY_MODE_NONE = 0,
- RRD_MEMORY_MODE_RAM = 1,
- RRD_MEMORY_MODE_MAP = 2,
- RRD_MEMORY_MODE_SAVE = 3,
- RRD_MEMORY_MODE_ALLOC = 4
-} RRD_MEMORY_MODE;
-
-#define RRD_MEMORY_MODE_NONE_NAME "none"
-#define RRD_MEMORY_MODE_RAM_NAME "ram"
-#define RRD_MEMORY_MODE_MAP_NAME "map"
-#define RRD_MEMORY_MODE_SAVE_NAME "save"
-#define RRD_MEMORY_MODE_ALLOC_NAME "alloc"
-
-extern RRD_MEMORY_MODE default_rrd_memory_mode;
-
-extern const char *rrd_memory_mode_name(RRD_MEMORY_MODE id);
-extern RRD_MEMORY_MODE rrd_memory_mode_id(const char *name);
-
-
-// ----------------------------------------------------------------------------
-// algorithms types
-
-typedef enum rrd_algorithm {
- RRD_ALGORITHM_ABSOLUTE = 0,
- RRD_ALGORITHM_INCREMENTAL = 1,
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL = 2,
- RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL = 3
-} RRD_ALGORITHM;
-
-#define RRD_ALGORITHM_ABSOLUTE_NAME "absolute"
-#define RRD_ALGORITHM_INCREMENTAL_NAME "incremental"
-#define RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row"
-#define RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row"
-
-extern RRD_ALGORITHM rrd_algorithm_id(const char *name);
-extern const char *rrd_algorithm_name(RRD_ALGORITHM algorithm);
-
-// ----------------------------------------------------------------------------
-// RRD FAMILY
-
-struct rrdfamily {
- avl avl;
-
- const char *family;
- uint32_t hash_family;
-
- size_t use_count;
-
- avl_tree_lock rrdvar_root_index;
-};
-typedef struct rrdfamily RRDFAMILY;
-
-
-// ----------------------------------------------------------------------------
-// flags
-// use this for configuration flags, not for state control
-// flags are set/unset in a manner that is not thread safe
-// and may lead to missing information.
-
-typedef enum rrddim_flags {
- RRDDIM_FLAG_NONE = 0,
- RRDDIM_FLAG_HIDDEN = 1 << 0, // this dimension will not be offered to callers
- RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = 1 << 1 // do not offer RESET or OVERFLOW info to callers
-} RRDDIM_FLAGS;
-
-#ifdef HAVE_C___ATOMIC
-#define rrddim_flag_check(rd, flag) (__atomic_load_n(&((rd)->flags), __ATOMIC_SEQ_CST) & (flag))
-#define rrddim_flag_set(rd, flag) __atomic_or_fetch(&((rd)->flags), (flag), __ATOMIC_SEQ_CST)
-#define rrddim_flag_clear(rd, flag) __atomic_and_fetch(&((rd)->flags), ~(flag), __ATOMIC_SEQ_CST)
-#else
-#define rrddim_flag_check(rd, flag) ((rd)->flags & (flag))
-#define rrddim_flag_set(rd, flag) (rd)->flags |= (flag)
-#define rrddim_flag_clear(rd, flag) (rd)->flags &= ~(flag)
-#endif
-
-
-// ----------------------------------------------------------------------------
-// RRD DIMENSION - this is a metric
-
-struct rrddim {
- // ------------------------------------------------------------------------
- // binary indexing structures
-
- avl avl; // the binary index - this has to be first member!
-
- // ------------------------------------------------------------------------
- // the dimension definition
-
- const char *id; // the id of this dimension (for internal identification)
- const char *name; // the name of this dimension (as presented to user)
- // this is a pointer to the config structure
- // since the config always has a higher priority
- // (the user overwrites the name of the charts)
- // DO NOT FREE THIS - IT IS ALLOCATED IN CONFIG
-
- RRD_ALGORITHM algorithm; // the algorithm that is applied to add new collected values
- RRD_MEMORY_MODE rrd_memory_mode; // the memory mode for this dimension
-
- collected_number multiplier; // the multiplier of the collected values
- collected_number divisor; // the divider of the collected values
-
- uint32_t flags; // configuration flags for the dimension
-
- // ------------------------------------------------------------------------
- // members for temporary data we need for calculations
-
- uint32_t hash; // a simple hash of the id, to speed up searching / indexing
- // instead of strcmp() every item in the binary index
- // we first compare the hashes
-
- uint32_t hash_name; // a simple hash of the name
-
- char *cache_filename; // the filename we load/save from/to this set
-
- size_t collections_counter; // the number of times we added values to this rrdim
- size_t unused[10];
-
- int updated:1; // 1 when the dimension has been updated since the last processing
- int exposed:1; // 1 when set what have sent this dimension to the central netdata
-
- struct timeval last_collected_time; // when was this dimension last updated
- // this is actual date time we updated the last_collected_value
- // THIS IS DIFFERENT FROM THE SAME MEMBER OF RRDSET
-
- calculated_number calculated_value; // the current calculated value, after applying the algorithm - resets to zero after being used
- calculated_number last_calculated_value; // the last calculated value processed
-
- calculated_number last_stored_value; // the last value as stored in the database (after interpolation)
-
- collected_number collected_value; // the current value, as collected - resets to 0 after being used
- collected_number last_collected_value; // the last value that was collected, after being processed
-
- // the *_volume members are used to calculate the accuracy of the rounding done by the
- // storage number - they are printed to debug.log when debug is enabled for a set.
- calculated_number collected_volume; // the sum of all collected values so far
- calculated_number stored_volume; // the sum of all stored values so far
-
- struct rrddim *next; // linking of dimensions within the same data set
- struct rrdset *rrdset;
-
- // ------------------------------------------------------------------------
- // members for checking the data when loading from disk
-
- long entries; // how many entries this dimension has in ram
- // this is the same to the entries of the data set
- // we set it here, to check the data when we load it from disk.
-
- int update_every; // every how many seconds is this updated
-
- size_t memsize; // the memory allocated for this dimension
-
- char magic[sizeof(RRDDIMENSION_MAGIC) + 1]; // a string to be saved, used to identify our data file
-
- struct rrddimvar *variables;
-
- // ------------------------------------------------------------------------
- // the values stored in this dimension, using our floating point numbers
-
- storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER
-};
-typedef struct rrddim RRDDIM;
-
-// ----------------------------------------------------------------------------
-// these loop macros make sure the linked list is accessed with the right lock
-
-#define rrddim_foreach_read(rd, st) \
- for((rd) = (st)->dimensions, rrdset_check_rdlock(st); (rd) ; (rd) = (rd)->next)
-
-#define rrddim_foreach_write(rd, st) \
- for((rd) = (st)->dimensions, rrdset_check_wrlock(st); (rd) ; (rd) = (rd)->next)
-
-
-// ----------------------------------------------------------------------------
-// RRDSET - this is a chart
-
-// use this for configuration flags, not for state control
-// flags are set/unset in a manner that is not thread safe
-// and may lead to missing information.
-
-typedef enum rrdset_flags {
- RRDSET_FLAG_ENABLED = 1 << 0, // enables or disables a chart
- RRDSET_FLAG_DETAIL = 1 << 1, // if set, the data set should be considered as a detail of another
- // (the master data set should be the one that has the same family and is not detail)
- RRDSET_FLAG_DEBUG = 1 << 2, // enables or disables debugging for a chart
- RRDSET_FLAG_OBSOLETE = 1 << 3, // this is marked by the collector/module as obsolete
- RRDSET_FLAG_BACKEND_SEND = 1 << 4, // if set, this chart should be sent to backends
- RRDSET_FLAG_BACKEND_IGNORE = 1 << 5, // if set, this chart should not be sent to backends
- RRDSET_FLAG_EXPOSED_UPSTREAM = 1 << 6, // if set, we have sent this chart to netdata master (streaming)
- RRDSET_FLAG_STORE_FIRST = 1 << 7, // if set, do not eliminate the first collection during interpolation
- RRDSET_FLAG_HETEROGENEOUS = 1 << 8, // if set, the chart is not homogeneous (dimensions in it have multiple algorithms, multipliers or dividers)
- RRDSET_FLAG_HOMEGENEOUS_CHECK= 1 << 9, // if set, the chart should be checked to determine if the dimensions as homogeneous
- RRDSET_FLAG_HIDDEN = 1 << 10, // if set, do not show this chart on the dashboard, but use it for backends
-} RRDSET_FLAGS;
-
-#ifdef HAVE_C___ATOMIC
-#define rrdset_flag_check(st, flag) (__atomic_load_n(&((st)->flags), __ATOMIC_SEQ_CST) & (flag))
-#define rrdset_flag_set(st, flag) __atomic_or_fetch(&((st)->flags), flag, __ATOMIC_SEQ_CST)
-#define rrdset_flag_clear(st, flag) __atomic_and_fetch(&((st)->flags), ~flag, __ATOMIC_SEQ_CST)
-#else
-#define rrdset_flag_check(st, flag) ((st)->flags & (flag))
-#define rrdset_flag_set(st, flag) (st)->flags |= (flag)
-#define rrdset_flag_clear(st, flag) (st)->flags &= ~(flag)
-#endif
-
-struct rrdset {
- // ------------------------------------------------------------------------
- // binary indexing structures
-
- avl avl; // the index, with key the id - this has to be first!
- avl avlname; // the index, with key the name
-
- // ------------------------------------------------------------------------
- // the set configuration
-
- char id[RRD_ID_LENGTH_MAX + 1]; // id of the data set
-
- const char *name; // the name of this dimension (as presented to user)
- // this is a pointer to the config structure
- // since the config always has a higher priority
- // (the user overwrites the name of the charts)
-
- char *config_section; // the config section for the chart
-
- char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
- char *family; // grouping sets under the same family
- char *title; // title shown to user
- char *units; // units of measurement
-
- char *context; // the template of this data set
- uint32_t hash_context; // the hash of the chart's context
-
- RRDSET_TYPE chart_type; // line, area, stacked
-
- int update_every; // every how many seconds is this updated?
-
- long entries; // total number of entries in the data set
-
- long current_entry; // the entry that is currently being updated
- // it goes around in a round-robin fashion
-
- uint32_t flags; // configuration flags
-
- int gap_when_lost_iterations_above; // after how many lost iterations a gap should be stored
- // netdata will interpolate values for gaps lower than this
-
- long priority; // the sorting priority of this chart
-
-
- // ------------------------------------------------------------------------
- // members for temporary data we need for calculations
-
- RRD_MEMORY_MODE rrd_memory_mode; // if set to 1, this is memory mapped
-
- char *cache_dir; // the directory to store dimensions
- char cache_filename[FILENAME_MAX+1]; // the filename to store this set
-
- 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
-
- time_t last_accessed_time; // the last time this RRDSET has been accessed
- time_t upstream_resync_time; // the timestamp up to which we should resync clock upstream
-
- char *plugin_name; // the name of the plugin that generated this
- char *module_name; // the name of the plugin module that generated this
-
- size_t unused[6];
-
- uint32_t hash; // a simple hash on the id, to speed up searching
- // we first compare hashes, and only if the hashes are equal we do string comparisons
-
- uint32_t hash_name; // a simple hash on the name
-
- usec_t usec_since_last_update; // the time in microseconds since the last collection of data
-
- struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
- struct timeval last_collected_time; // when did this data set last collected values
-
- total_number collected_total; // used internally to calculate percentages
- total_number last_collected_total; // used internally to calculate percentages
-
- RRDFAMILY *rrdfamily; // pointer to RRDFAMILY this chart belongs to
- RRDHOST *rrdhost; // pointer to RRDHOST this chart belongs to
-
- struct rrdset *next; // linking of rrdsets
-
- // ------------------------------------------------------------------------
- // local variables
-
- calculated_number green; // green threshold for this chart
- calculated_number red; // red threshold for this chart
-
- avl_tree_lock rrdvar_root_index; // RRDVAR index for this chart
- RRDSETVAR *variables; // RRDSETVAR linked list for this chart (one RRDSETVAR, many RRDVARs)
- RRDCALC *alarms; // RRDCALC linked list for this chart
-
- // ------------------------------------------------------------------------
- // members for checking the data when loading from disk
-
- unsigned long memsize; // how much mem we have allocated for this (without dimensions)
-
- char magic[sizeof(RRDSET_MAGIC) + 1]; // our magic
-
- // ------------------------------------------------------------------------
- // the dimensions
-
- avl_tree_lock dimensions_index; // the root of the dimensions index
- RRDDIM *dimensions; // the actual data for every dimension
-
-};
-typedef struct rrdset RRDSET;
-
-#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
-
-#define rrdset_foreach_read(st, host) \
- for((st) = (host)->rrdset_root, rrdhost_check_rdlock(host); st ; (st) = (st)->next)
-
-#define rrdset_foreach_write(st, host) \
- for((st) = (host)->rrdset_root, rrdhost_check_wrlock(host); st ; (st) = (st)->next)
-
-
-// ----------------------------------------------------------------------------
-// RRDHOST flags
-// use this for configuration flags, not for state control
-// flags are set/unset in a manner that is not thread safe
-// and may lead to missing information.
-
-typedef enum rrdhost_flags {
- RRDHOST_FLAG_ORPHAN = 1 << 0, // this host is orphan (not receiving data)
- RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS = 1 << 1, // delete files of obsolete charts
- RRDHOST_FLAG_DELETE_ORPHAN_HOST = 1 << 2, // delete the entire host when orphan
- RRDHOST_FLAG_BACKEND_SEND = 1 << 3, // send it to backends
- RRDHOST_FLAG_BACKEND_DONT_SEND = 1 << 4, // don't send it to backends
-} RRDHOST_FLAGS;
-
-#ifdef HAVE_C___ATOMIC
-#define rrdhost_flag_check(host, flag) (__atomic_load_n(&((host)->flags), __ATOMIC_SEQ_CST) & (flag))
-#define rrdhost_flag_set(host, flag) __atomic_or_fetch(&((host)->flags), flag, __ATOMIC_SEQ_CST)
-#define rrdhost_flag_clear(host, flag) __atomic_and_fetch(&((host)->flags), ~flag, __ATOMIC_SEQ_CST)
-#else
-#define rrdhost_flag_check(host, flag) ((host)->flags & (flag))
-#define rrdhost_flag_set(host, flag) (host)->flags |= (flag)
-#define rrdhost_flag_clear(host, flag) (host)->flags &= ~(flag)
-#endif
-
-#ifdef NETDATA_INTERNAL_CHECKS
-#define rrdset_debug(st, fmt, args...) do { if(unlikely(debug_flags & D_RRD_STATS && rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) \
- debug_int(__FILE__, __FUNCTION__, __LINE__, "%s: " fmt, st->name, ##args); } while(0)
-#else
-#define rrdset_debug(st, fmt, args...) debug_dummy()
-#endif
-
-
-// ----------------------------------------------------------------------------
-// RRD HOST
-
-struct rrdhost {
- avl avl; // the index of hosts
-
- // ------------------------------------------------------------------------
- // host information
-
- char *hostname; // the hostname of this host
- uint32_t hash_hostname; // the hostname hash
-
- char *registry_hostname; // the registry hostname for this host
-
- char machine_guid[GUID_LEN + 1]; // the unique ID of this host
- uint32_t hash_machine_guid; // the hash of the unique ID
-
- const char *os; // the O/S type of the host
- const char *tags; // tags for this host
- const char *timezone; // the timezone of the host
-
- uint32_t flags; // flags about this RRDHOST
-
- int rrd_update_every; // the update frequency of the host
- long rrd_history_entries; // the number of history entries for the host's charts
- RRD_MEMORY_MODE rrd_memory_mode; // the memory more for the charts of this host
-
- char *cache_dir; // the directory to save RRD cache files
- char *varlib_dir; // the directory to save health log
-
- char *program_name; // the program name that collects metrics for this host
- char *program_version; // the program version that collects metrics for this host
-
- // ------------------------------------------------------------------------
- // streaming of data to remote hosts - rrdpush
-
- int rrdpush_send_enabled:1; // 1 when this host sends metrics to another netdata
- char *rrdpush_send_destination; // where to send metrics to
- char *rrdpush_send_api_key; // the api key at the receiving netdata
-
- // the following are state information for the threading
- // streaming metrics from this netdata to an upstream netdata
- volatile int rrdpush_sender_spawn:1; // 1 when the sender thread has been spawn
- netdata_thread_t rrdpush_sender_thread; // the sender thread
-
- volatile int rrdpush_sender_connected:1; // 1 when the sender is ready to push metrics
- int rrdpush_sender_socket; // the fd of the socket to the remote host, or -1
-
- volatile int rrdpush_sender_error_shown:1; // 1 when we have logged a communication error
- volatile int rrdpush_sender_join:1; // 1 when we have to join the sending thread
-
- // metrics may be collected asynchronously
- // these synchronize all the threads willing the write to our sending buffer
- netdata_mutex_t rrdpush_sender_buffer_mutex; // exclusive access to rrdpush_sender_buffer
- int rrdpush_sender_pipe[2]; // collector to sender thread signaling
- BUFFER *rrdpush_sender_buffer; // collector fills it, sender sends it
-
-
- // ------------------------------------------------------------------------
- // streaming of data from remote hosts - rrdpush
-
- volatile size_t connected_senders; // when remote hosts are streaming to this
- // host, this is the counter of connected clients
-
- time_t senders_disconnected_time; // the time the last sender was disconnected
-
- // ------------------------------------------------------------------------
- // health monitoring options
-
- int health_enabled:1; // 1 when this host has health enabled
- time_t health_delay_up_to; // a timestamp to delay alarms processing up to
- char *health_default_exec; // the full path of the alarms notifications program
- char *health_default_recipient; // the default recipient for all alarms
- char *health_log_filename; // the alarms event log filename
- size_t health_log_entries_written; // the number of alarm events writtern to the alarms event log
- FILE *health_log_fp; // the FILE pointer to the open alarms event log file
-
- // all RRDCALCs are primarily allocated and linked here
- // RRDCALCs may be linked to charts at any point
- // (charts may or may not exist when these are loaded)
- RRDCALC *alarms;
-
- ALARM_LOG health_log; // alarms historical events (event log)
- uint32_t health_last_processed_id; // the last processed health id from the log
- uint32_t health_max_unique_id; // the max alarm log unique id given for the host
- uint32_t health_max_alarm_id; // the max alarm id given for the host
-
- // templates of alarms
- // these are used to create alarms when charts
- // are created or renamed, that match them
- RRDCALCTEMPLATE *templates;
-
-
- // ------------------------------------------------------------------------
- // the charts of the host
-
- RRDSET *rrdset_root; // the host charts
-
-
- // ------------------------------------------------------------------------
- // locks
-
- netdata_rwlock_t rrdhost_rwlock; // lock for this RRDHOST (protects rrdset_root linked list)
-
- // ------------------------------------------------------------------------
- // indexes
-
- 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)
-
- avl_tree_lock rrdfamily_root_index; // the host's chart families index
- avl_tree_lock rrdvar_root_index; // the host's chart variables index
-
- struct rrdhost *next;
-};
-extern RRDHOST *localhost;
-
-#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
-
-#define rrdhost_foreach_read(var) \
- for((var) = localhost, rrd_check_rdlock(); var ; (var) = (var)->next)
-
-#define rrdhost_foreach_write(var) \
- for((var) = localhost, rrd_check_wrlock(); var ; (var) = (var)->next)
-
-
-// ----------------------------------------------------------------------------
-// global lock for all RRDHOSTs
-
-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)
-
-// ----------------------------------------------------------------------------
-
-extern size_t rrd_hosts_available;
-extern time_t rrdhost_free_orphan_time;
-
-extern void rrd_init(char *hostname);
-
-extern RRDHOST *rrdhost_find_by_hostname(const char *hostname, uint32_t hash);
-extern RRDHOST *rrdhost_find_by_guid(const char *guid, uint32_t hash);
-
-extern RRDHOST *rrdhost_find_or_create(
- const char *hostname
- , const char *registry_hostname
- , const char *guid
- , const char *os
- , const char *timezone
- , const char *tags
- , const char *program_name
- , const char *program_version
- , int update_every
- , long history
- , RRD_MEMORY_MODE mode
- , int health_enabled
- , int rrdpush_enabled
- , char *rrdpush_destination
- , char *rrdpush_api_key
-);
-
-#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
-#define rrdhost_check_wrlock(host) (void)0
-#define rrdset_check_rdlock(st) (void)0
-#define rrdset_check_wrlock(st) (void)0
-#define rrd_check_rdlock() (void)0
-#define rrd_check_wrlock() (void)0
-#endif
-
-// ----------------------------------------------------------------------------
-// RRDSET functions
-
-extern int rrdset_set_name(RRDSET *st, const char *name);
-
-extern RRDSET *rrdset_create_custom(RRDHOST *host
- , const char *type
- , const char *id
- , const char *name
- , const char *family
- , const char *context
- , const char *title
- , const char *units
- , const char *plugin
- , const char *module
- , long priority
- , int update_every
- , RRDSET_TYPE chart_type
- , RRD_MEMORY_MODE memory_mode
- , long history_entries);
-
-#define rrdset_create(host, type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type) \
- rrdset_create_custom(host, type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type, (host)->rrd_memory_mode, (host)->rrd_history_entries)
-
-#define rrdset_create_localhost(type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type) \
- rrdset_create(localhost, type, id, name, family, context, title, units, plugin, module, priority, update_every, chart_type)
-
-extern void rrdhost_free_all(void);
-extern void rrdhost_save_all(void);
-extern void rrdhost_cleanup_all(void);
-
-extern void rrdhost_cleanup_orphan_hosts_nolock(RRDHOST *protected);
-extern void rrdhost_free(RRDHOST *host);
-extern void rrdhost_save_charts(RRDHOST *host);
-extern void rrdhost_delete_charts(RRDHOST *host);
-
-extern int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected, time_t now);
-
-extern void rrdset_update_heterogeneous_flag(RRDSET *st);
-
-extern RRDSET *rrdset_find(RRDHOST *host, const char *id);
-#define rrdset_find_localhost(id) rrdset_find(localhost, id)
-
-extern RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id);
-#define rrdset_find_bytype_localhost(type, id) rrdset_find_bytype(localhost, type, id)
-
-extern RRDSET *rrdset_find_byname(RRDHOST *host, const char *name);
-#define rrdset_find_byname_localhost(name) rrdset_find_byname(localhost, name)
-
-extern void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds);
-extern void rrdset_next_usec(RRDSET *st, usec_t microseconds);
-#define rrdset_next(st) rrdset_next_usec(st, 0ULL)
-
-extern void rrdset_done(RRDSET *st);
-
-extern void rrdset_is_obsolete(RRDSET *st);
-extern void rrdset_isnot_obsolete(RRDSET *st);
-
-// checks if the RRDSET should be offered to viewers
-#define rrdset_is_available_for_viewers(st) (rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && !rrdset_flag_check(st, RRDSET_FLAG_HIDDEN) && !rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE) && (st)->dimensions && (st)->rrd_memory_mode != RRD_MEMORY_MODE_NONE)
-#define rrdset_is_available_for_backends(st) (rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && !rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE) && (st)->dimensions)
-
-// get the total duration in seconds of the round robin database
-#define rrdset_duration(st) ((time_t)( (((st)->counter >= ((unsigned long)(st)->entries))?(unsigned long)(st)->entries:(st)->counter) * (st)->update_every ))
-
-// get the timestamp of the last entry in the round robin database
-#define rrdset_last_entry_t(st) ((time_t)(((st)->last_updated.tv_sec)))
-
-// get the timestamp of first entry in the round robin database
-#define rrdset_first_entry_t(st) ((time_t)(rrdset_last_entry_t(st) - rrdset_duration(st)))
-
-// get the last slot updated in the round robin database
-#define rrdset_last_slot(st) ((unsigned long)(((st)->current_entry == 0) ? (st)->entries - 1 : (st)->current_entry - 1))
-
-// get the first / oldest slot updated in the round robin database
-#define rrdset_first_slot(st) ((unsigned long)( (((st)->counter >= ((unsigned long)(st)->entries)) ? (unsigned long)( ((unsigned long)(st)->current_entry > 0) ? ((unsigned long)(st)->current_entry) : ((unsigned long)(st)->entries) ) - 1 : 0) ))
-
-// get the slot of the round robin database, for the given timestamp (t)
-// it always returns a valid slot, although may not be for the time requested if the time is outside the round robin database
-#define rrdset_time2slot(st, t) ( \
- ( (time_t)(t) >= rrdset_last_entry_t(st)) ? ( rrdset_last_slot(st) ) : \
- ( ((time_t)(t) <= rrdset_first_entry_t(st)) ? rrdset_first_slot(st) : \
- ( (rrdset_last_slot(st) >= (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) ? \
- (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) : \
- (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) + (unsigned long)(st)->entries ) \
- )))
-
-// get the timestamp of a specific slot in the round robin database
-#define rrdset_slot2time(st, slot) ( rrdset_last_entry_t(st) - \
- ((unsigned long)(st)->update_every * ( \
- ( (unsigned long)(slot) > rrdset_last_slot(st)) ? \
- ( (rrdset_last_slot(st) - (unsigned long)(slot) + (unsigned long)(st)->entries) ) : \
- ( (rrdset_last_slot(st) - (unsigned long)(slot)) )) \
- ))
-
-// ----------------------------------------------------------------------------
-// RRD DIMENSION functions
-
-extern RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm, RRD_MEMORY_MODE memory_mode);
-#define rrddim_add(st, id, name, multiplier, divisor, algorithm) rrddim_add_custom(st, id, name, multiplier, divisor, algorithm, (st)->rrd_memory_mode)
-
-extern int rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name);
-extern int rrddim_set_algorithm(RRDSET *st, RRDDIM *rd, RRD_ALGORITHM algorithm);
-extern int rrddim_set_multiplier(RRDSET *st, RRDDIM *rd, collected_number multiplier);
-extern int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, collected_number divisor);
-
-extern RRDDIM *rrddim_find(RRDSET *st, const char *id);
-
-extern int rrddim_hide(RRDSET *st, const char *id);
-extern int rrddim_unhide(RRDSET *st, const char *id);
-
-extern collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value);
-extern collected_number rrddim_set(RRDSET *st, const char *id, collected_number value);
-
-extern long align_entries_to_pagesize(RRD_MEMORY_MODE mode, long entries);
-
-// ----------------------------------------------------------------------------
-// RRD internal functions
-
-#ifdef NETDATA_RRD_INTERNALS
-
-extern avl_tree_lock rrdhost_root_index;
-
-extern char *rrdset_strncpyz_name(char *to, const char *from, size_t length);
-extern char *rrdset_cache_dir(RRDHOST *host, const char *id, const char *config_section);
-
-extern void rrddim_free(RRDSET *st, RRDDIM *rd);
-
-extern int rrddim_compare(void* a, void* b);
-extern int rrdset_compare(void* a, void* b);
-extern int rrdset_compare_name(void* a, void* b);
-extern int rrdfamily_compare(void *a, void *b);
-
-extern RRDFAMILY *rrdfamily_create(RRDHOST *host, const char *id);
-extern void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc);
-
-#define rrdset_index_add(host, st) (RRDSET *)avl_insert_lock(&((host)->rrdset_root_index), (avl *)(st))
-#define rrdset_index_del(host, st) (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index), (avl *)(st))
-extern RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st);
-
-extern void rrdset_free(RRDSET *st);
-extern void rrdset_reset(RRDSET *st);
-extern void rrdset_save(RRDSET *st);
-extern void rrdset_delete(RRDSET *st);
-
-extern void rrdhost_cleanup_obsolete_charts(RRDHOST *host);
-
-#endif /* NETDATA_RRD_INTERNALS */
-
-
-#endif /* NETDATA_RRD_H */
diff --git a/src/rrd2json.c b/src/rrd2json.c
deleted file mode 100644
index 24b3da340..000000000
--- a/src/rrd2json.c
+++ /dev/null
@@ -1,2059 +0,0 @@
-#include "common.h"
-
-void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used)
-{
- rrdset_rdlock(st);
-
- buffer_sprintf(wb,
- "\t\t{\n"
- "\t\t\t\"id\": \"%s\",\n"
- "\t\t\t\"name\": \"%s\",\n"
- "\t\t\t\"type\": \"%s\",\n"
- "\t\t\t\"family\": \"%s\",\n"
- "\t\t\t\"context\": \"%s\",\n"
- "\t\t\t\"title\": \"%s (%s)\",\n"
- "\t\t\t\"priority\": %ld,\n"
- "\t\t\t\"plugin\": \"%s\",\n"
- "\t\t\t\"module\": \"%s\",\n"
- "\t\t\t\"enabled\": %s,\n"
- "\t\t\t\"units\": \"%s\",\n"
- "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n"
- "\t\t\t\"chart_type\": \"%s\",\n"
- "\t\t\t\"duration\": %ld,\n"
- "\t\t\t\"first_entry\": %ld,\n"
- "\t\t\t\"last_entry\": %ld,\n"
- "\t\t\t\"update_every\": %d,\n"
- "\t\t\t\"dimensions\": {\n"
- , st->id
- , st->name
- , st->type
- , st->family
- , st->context
- , st->title, st->name
- , st->priority
- , st->plugin_name?st->plugin_name:""
- , st->module_name?st->module_name:""
- , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?"true":"false"
- , st->units
- , st->name
- , rrdset_type_name(st->chart_type)
- , st->entries * st->update_every
- , rrdset_first_entry_t(st)
- , rrdset_last_entry_t(st)
- , st->update_every
- );
-
- unsigned long memory = st->memsize;
-
- size_t dimensions = 0;
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) continue;
-
- memory += rd->memsize;
-
- buffer_sprintf(
- wb
- , "%s"
- "\t\t\t\t\"%s\": { \"name\": \"%s\" }"
- , dimensions ? ",\n" : ""
- , rd->id
- , rd->name
- );
-
- dimensions++;
- }
-
- if(dimensions_count) *dimensions_count += dimensions;
- if(memory_used) *memory_used += memory;
-
- buffer_strcat(wb, "\n\t\t\t},\n\t\t\t\"green\": ");
- buffer_rrd_value(wb, st->green);
- buffer_strcat(wb, ",\n\t\t\t\"red\": ");
- buffer_rrd_value(wb, st->red);
-
- buffer_strcat(wb, ",\n\t\t\t\"alarms\": {\n");
- size_t alarms = 0;
- RRDCALC *rc;
- for(rc = st->alarms; rc ; rc = rc->rrdset_next) {
-
- buffer_sprintf(
- wb
- , "%s"
- "\t\t\t\t\"%s\": {\n"
- "\t\t\t\t\t\"id\": %u,\n"
- "\t\t\t\t\t\"status\": \"%s\",\n"
- "\t\t\t\t\t\"units\": \"%s\",\n"
- "\t\t\t\t\t\"update_every\": %d\n"
- "\t\t\t\t}"
- , (alarms) ? ",\n" : ""
- , rc->name
- , rc->id
- , rrdcalc_status2string(rc->status)
- , rc->units
- , rc->update_every
- );
-
- alarms++;
- }
-
- buffer_sprintf(wb,
- "\n\t\t\t}\n\t\t}"
- );
-
- rrdset_unlock(st);
-}
-
-void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) {
- rrd_stats_api_v1_chart_with_data(st, wb, NULL, NULL);
-}
-
-void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) {
- static char *custom_dashboard_info_js_filename = NULL;
- size_t c, dimensions = 0, memory = 0, alarms = 0;
- RRDSET *st;
-
- time_t now = now_realtime_sec();
-
- if(unlikely(!custom_dashboard_info_js_filename))
- custom_dashboard_info_js_filename = config_get(CONFIG_SECTION_WEB, "custom dashboard_info.js", "");
-
- buffer_sprintf(wb, "{\n"
- "\t\"hostname\": \"%s\""
- ",\n\t\"version\": \"%s\""
- ",\n\t\"os\": \"%s\""
- ",\n\t\"timezone\": \"%s\""
- ",\n\t\"update_every\": %d"
- ",\n\t\"history\": %ld"
- ",\n\t\"custom_info\": \"%s\""
- ",\n\t\"charts\": {"
- , host->hostname
- , host->program_version
- , host->os
- , host->timezone
- , host->rrd_update_every
- , host->rrd_history_entries
- , custom_dashboard_info_js_filename
- );
-
- c = 0;
- rrdhost_rdlock(host);
- rrdset_foreach_read(st, host) {
- if(rrdset_is_available_for_viewers(st)) {
- if(c) buffer_strcat(wb, ",");
- buffer_strcat(wb, "\n\t\t\"");
- buffer_strcat(wb, st->id);
- buffer_strcat(wb, "\": ");
- rrd_stats_api_v1_chart_with_data(st, wb, &dimensions, &memory);
-
- c++;
- st->last_accessed_time = now;
- }
- }
-
- RRDCALC *rc;
- for(rc = host->alarms; rc ; rc = rc->next) {
- if(rc->rrdset)
- alarms++;
- }
- rrdhost_unlock(host);
-
- buffer_sprintf(wb
- , "\n\t}"
- ",\n\t\"charts_count\": %zu"
- ",\n\t\"dimensions_count\": %zu"
- ",\n\t\"alarms_count\": %zu"
- ",\n\t\"rrd_memory_bytes\": %zu"
- ",\n\t\"hosts_count\": %zu"
- ",\n\t\"hosts\": ["
- , c
- , dimensions
- , alarms
- , memory
- , rrd_hosts_available
- );
-
- if(unlikely(rrd_hosts_available > 1)) {
- rrd_rdlock();
-
- size_t found = 0;
- RRDHOST *h;
- rrdhost_foreach_read(h) {
- if(!rrdhost_should_be_removed(h, host, now)) {
- buffer_sprintf(wb
- , "%s\n\t\t{"
- "\n\t\t\t\"hostname\": \"%s\""
- "\n\t\t}"
- , (found > 0) ? "," : ""
- , h->hostname
- );
-
- found++;
- }
- }
-
- rrd_unlock();
- }
- else {
- buffer_sprintf(wb
- , "\n\t\t{"
- "\n\t\t\t\"hostname\": \"%s\""
- "\n\t\t}"
- , host->hostname
- );
- }
-
- buffer_sprintf(wb, "\n\t]\n}\n");
-}
-
-// ----------------------------------------------------------------------------
-// BASH
-// /api/v1/allmetrics?format=bash
-
-static inline size_t shell_name_copy(char *d, const char *s, size_t usable) {
- size_t n;
-
- for(n = 0; *s && n < usable ; d++, s++, n++) {
- register char c = *s;
-
- if(unlikely(!isalnum(c))) *d = '_';
- else *d = (char)toupper(c);
- }
- *d = '\0';
-
- return n;
-}
-
-#define SHELL_ELEMENT_MAX 100
-
-void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) {
- rrdhost_rdlock(host);
-
- // for each chart
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- calculated_number total = 0.0;
- char chart[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(chart, st->name?st->name:st->id, SHELL_ELEMENT_MAX);
-
- buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name);
- if(rrdset_is_available_for_viewers(st)) {
- rrdset_rdlock(st);
-
- // for each dimension
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rd->collections_counter) {
- char dimension[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(dimension, rd->name?rd->name:rd->id, SHELL_ELEMENT_MAX);
-
- calculated_number n = rd->last_stored_value;
-
- if(isnan(n) || isinf(n))
- buffer_sprintf(wb, "NETDATA_%s_%s=\"\" # %s\n", chart, dimension, st->units);
- else {
- if(rd->multiplier < 0 || rd->divisor < 0) n = -n;
- n = calculated_number_round(n);
- if(!rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) total += n;
- buffer_sprintf(wb, "NETDATA_%s_%s=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, dimension, n, st->units);
- }
- }
- }
-
- total = calculated_number_round(total);
- buffer_sprintf(wb, "NETDATA_%s_VISIBLETOTAL=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, total, st->units);
- rrdset_unlock(st);
- }
- }
-
- buffer_strcat(wb, "\n# NETDATA ALARMS RUNNING\n");
-
- RRDCALC *rc;
- for(rc = host->alarms; rc ;rc = rc->next) {
- if(!rc->rrdset) continue;
-
- char chart[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(chart, rc->rrdset->name?rc->rrdset->name:rc->rrdset->id, SHELL_ELEMENT_MAX);
-
- char alarm[SHELL_ELEMENT_MAX + 1];
- shell_name_copy(alarm, rc->name, SHELL_ELEMENT_MAX);
-
- calculated_number n = rc->value;
-
- if(isnan(n) || isinf(n))
- buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"\" # %s\n", chart, alarm, rc->units);
- else {
- n = calculated_number_round(n);
- buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, alarm, n, rc->units);
- }
-
- buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status));
- }
-
- rrdhost_unlock(host);
-}
-
-// ----------------------------------------------------------------------------
-
-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
-#define RRDR_HIDDEN 0x04 // the dimension contains / the value is hidden
-#define RRDR_NONZERO 0x08 // the dimension contains / the value is non-zero
-#define RRDR_SELECTED 0x10 // the dimension is selected
-
-// RRDR result options
-#define RRDR_RESULT_OPTION_ABSOLUTE 0x00000001
-#define RRDR_RESULT_OPTION_RELATIVE 0x00000002
-
-typedef struct rrdresult {
- RRDSET *st; // the chart this result refers to
-
- uint32_t result_options; // RRDR_RESULT_OPTION_*
-
- int d; // the number of dimensions
- long n; // the number of values in the arrays
- long rows; // the number of rows used
-
- uint8_t *od; // the options for the dimensions
-
- time_t *t; // array of n timestamps
- calculated_number *v; // array n x d values
- uint8_t *o; // array n x d options
-
- long c; // current line ( -1 ~ n ), ( -1 = none, use rrdr_rows() to get number of rows )
-
- long group; // how many collected values were grouped for each row
- int update_every; // what is the suggested update frequency in seconds
-
- calculated_number min;
- calculated_number max;
-
- time_t before;
- time_t after;
-
- int has_st_lock; // if st is read locked by us
-} RRDR;
-
-#define rrdr_rows(r) ((r)->rows)
-
-/*
-static void rrdr_dump(RRDR *r)
-{
- long c, i;
- RRDDIM *d;
-
- fprintf(stderr, "\nCHART %s (%s)\n", r->st->id, r->st->name);
-
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
- fprintf(stderr, "DIMENSION %s (%s), %s%s%s%s\n"
- , d->id
- , d->name
- , (r->od[c] & RRDR_EMPTY)?"EMPTY ":""
- , (r->od[c] & RRDR_RESET)?"RESET ":""
- , (r->od[c] & RRDR_HIDDEN)?"HIDDEN ":""
- , (r->od[c] & RRDR_NONZERO)?"NONZERO ":""
- );
- }
-
- if(r->rows <= 0) {
- fprintf(stderr, "RRDR does not have any values in it.\n");
- return;
- }
-
- fprintf(stderr, "RRDR includes %d values in it:\n", r->rows);
-
- // for each line in the array
- for(i = 0; i < r->rows ;i++) {
- calculated_number *cn = &r->v[ i * r->d ];
- uint8_t *co = &r->o[ i * r->d ];
-
- // print the id and the timestamp of the line
- fprintf(stderr, "%ld %ld ", i + 1, r->t[i]);
-
- // for each dimension
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
-
- if(co[c] & RRDR_EMPTY)
- fprintf(stderr, "null ");
- else
- fprintf(stderr, CALCULATED_NUMBER_FORMAT " %s%s%s%s "
- , cn[c]
- , (co[c] & RRDR_EMPTY)?"E":" "
- , (co[c] & RRDR_RESET)?"R":" "
- , (co[c] & RRDR_HIDDEN)?"H":" "
- , (co[c] & RRDR_NONZERO)?"N":" "
- );
- }
-
- fprintf(stderr, "\n");
- }
-}
-*/
-
-void rrdr_disable_not_selected_dimensions(RRDR *r, uint32_t options, const char *dims) {
- rrdset_check_rdlock(r->st);
-
- if(unlikely(!dims || !*dims || (dims[0] == '*' && dims[1] == '\0'))) return;
-
- int match_ids = 0, match_names = 0;
-
- if(unlikely(options & RRDR_OPTION_MATCH_IDS))
- match_ids = 1;
- if(unlikely(options & RRDR_OPTION_MATCH_NAMES))
- match_names = 1;
-
- if(likely(!match_ids && !match_names))
- match_ids = match_names = 1;
-
- SIMPLE_PATTERN *pattern = simple_pattern_create(dims, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT);
-
- RRDDIM *d;
- long c, dims_selected = 0, dims_not_hidden_not_zero = 0;
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
- if( (match_ids && simple_pattern_matches(pattern, d->id))
- || (match_names && simple_pattern_matches(pattern, d->name))
- ) {
- r->od[c] |= RRDR_SELECTED;
- if(unlikely(r->od[c] & RRDR_HIDDEN)) r->od[c] &= ~RRDR_HIDDEN;
- dims_selected++;
-
- // since the user needs this dimension
- // make it appear as NONZERO, to return it
- // even if the dimension has only zeros
- // unless option non_zero is set
- if(unlikely(!(options & RRDR_OPTION_NONZERO)))
- r->od[c] |= RRDR_NONZERO;
-
- // count the visible dimensions
- if(likely(r->od[c] & RRDR_NONZERO))
- dims_not_hidden_not_zero++;
- }
- else {
- r->od[c] |= RRDR_HIDDEN;
- if(unlikely(r->od[c] & RRDR_SELECTED)) r->od[c] &= ~RRDR_SELECTED;
- }
- }
- simple_pattern_free(pattern);
-
- // check if all dimensions are hidden
- if(unlikely(!dims_not_hidden_not_zero && dims_selected)) {
- // there are a few selected dimensions
- // but they are all zero
- // enable the selected ones
- // to avoid returning an empty chart
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next)
- if(unlikely(r->od[c] & RRDR_SELECTED))
- r->od[c] |= RRDR_NONZERO;
- }
-}
-
-void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
-{
- switch(format) {
- case DATASOURCE_JSON:
- buffer_strcat(wb, DATASOURCE_FORMAT_JSON);
- break;
-
- case DATASOURCE_DATATABLE_JSON:
- buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON);
- break;
-
- case DATASOURCE_DATATABLE_JSONP:
- buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP);
- break;
-
- case DATASOURCE_JSONP:
- buffer_strcat(wb, DATASOURCE_FORMAT_JSONP);
- break;
-
- case DATASOURCE_SSV:
- buffer_strcat(wb, DATASOURCE_FORMAT_SSV);
- break;
-
- case DATASOURCE_CSV:
- buffer_strcat(wb, DATASOURCE_FORMAT_CSV);
- break;
-
- case DATASOURCE_TSV:
- buffer_strcat(wb, DATASOURCE_FORMAT_TSV);
- break;
-
- case DATASOURCE_HTML:
- buffer_strcat(wb, DATASOURCE_FORMAT_HTML);
- break;
-
- case DATASOURCE_JS_ARRAY:
- buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY);
- break;
-
- case DATASOURCE_SSV_COMMA:
- buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA);
- break;
-
- default:
- buffer_strcat(wb, "unknown");
- break;
- }
-}
-
-uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims)
-{
- rrdset_check_rdlock(r->st);
-
- (void)dims;
-
- if(options & RRDR_OPTION_NONZERO) {
- long i;
-
- // commented due to #1514
-
- //if(dims && *dims) {
- // the caller wants specific dimensions
- // disable NONZERO option
- // to make sure we don't accidentally prevent
- // the specific dimensions from being returned
- // i = 0;
- //}
- //else {
- // find how many dimensions are not zero
- long c;
- RRDDIM *rd;
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
- i++;
- }
- //}
-
- // if with nonzero we get i = 0 (no dimensions will be returned)
- // disable nonzero to show all dimensions
- if(!i) options &= ~RRDR_OPTION_NONZERO;
- }
-
- return options;
-}
-
-void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
-{
- rrdset_check_rdlock(r->st);
-
- long rows = rrdr_rows(r);
- long c, i;
- RRDDIM *rd;
-
- //info("JSONWRAPPER(): %s: BEGIN", r->st->id);
- char kq[2] = "", // key quote
- sq[2] = ""; // string quote
-
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
-
- buffer_sprintf(wb, "{\n"
- " %sapi%s: 1,\n"
- " %sid%s: %s%s%s,\n"
- " %sname%s: %s%s%s,\n"
- " %sview_update_every%s: %d,\n"
- " %supdate_every%s: %d,\n"
- " %sfirst_entry%s: %u,\n"
- " %slast_entry%s: %u,\n"
- " %sbefore%s: %u,\n"
- " %safter%s: %u,\n"
- " %sdimension_names%s: ["
- , kq, kq
- , kq, kq, sq, r->st->id, sq
- , kq, kq, sq, r->st->name, sq
- , kq, kq, r->update_every
- , kq, kq, r->st->update_every
- , kq, kq, (uint32_t)rrdset_first_entry_t(r->st)
- , kq, kq, (uint32_t)rrdset_last_entry_t(r->st)
- , kq, kq, (uint32_t)r->before
- , kq, kq, (uint32_t)r->after
- , kq, kq);
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- buffer_strcat(wb, sq);
- buffer_strcat(wb, rd->name);
- buffer_strcat(wb, sq);
- i++;
- }
- if(!i) {
-#ifdef NETDATA_INTERNAL_CHECKS
- error("RRDR is empty for %s (RRDR has %d dimensions, options is 0x%08x)", r->st->id, r->d, options);
-#endif
- rows = 0;
- buffer_strcat(wb, sq);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, sq);
- }
-
- buffer_sprintf(wb, "],\n"
- " %sdimension_ids%s: ["
- , kq, kq);
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- buffer_strcat(wb, sq);
- buffer_strcat(wb, rd->id);
- buffer_strcat(wb, sq);
- i++;
- }
- if(!i) {
- rows = 0;
- buffer_strcat(wb, sq);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, sq);
- }
-
- buffer_sprintf(wb, "],\n"
- " %slatest_values%s: ["
- , kq, kq);
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- i++;
-
- storage_number n = rd->values[rrdset_last_slot(r->st)];
-
- if(!does_storage_number_exist(n))
- buffer_strcat(wb, "null");
- else
- buffer_rrd_value(wb, unpack_storage_number(n));
- }
- if(!i) {
- rows = 0;
- buffer_strcat(wb, "null");
- }
-
- buffer_sprintf(wb, "],\n"
- " %sview_latest_values%s: ["
- , kq, kq);
-
- i = 0;
- if(rows) {
- calculated_number total = 1;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- total = 0;
- for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- calculated_number *cn = &r->v[ (0) * r->d ];
- calculated_number n = cn[c];
-
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- total += n;
- }
- // prevent a division by zero
- if(total == 0) total = 1;
- }
-
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(i) buffer_strcat(wb, ", ");
- i++;
-
- calculated_number *cn = &r->v[ (0) * r->d ];
- uint8_t *co = &r->o[ (0) * r->d ];
- calculated_number n = cn[c];
-
- if(co[c] & RRDR_EMPTY) {
- if(options & RRDR_OPTION_NULL2ZERO)
- buffer_strcat(wb, "0");
- else
- buffer_strcat(wb, "null");
- }
- else {
- if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE))
- n = n * 100 / total;
-
- buffer_rrd_value(wb, n);
- }
- }
- }
- if(!i) {
- rows = 0;
- buffer_strcat(wb, "null");
- }
-
- buffer_sprintf(wb, "],\n"
- " %sdimensions%s: %ld,\n"
- " %spoints%s: %ld,\n"
- " %sformat%s: %s"
- , kq, kq, i
- , kq, kq, rows
- , kq, kq, sq
- );
-
- rrdr_buffer_print_format(wb, format);
-
- buffer_sprintf(wb, "%s,\n"
- " %sresult%s: "
- , sq
- , kq, kq
- );
-
- if(string_value) buffer_strcat(wb, sq);
- //info("JSONWRAPPER(): %s: END", r->st->id);
-}
-
-void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
-{
- (void)format;
-
- char kq[2] = "", // key quote
- sq[2] = ""; // string quote
-
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
-
- if(string_value) buffer_strcat(wb, sq);
-
- buffer_sprintf(wb, ",\n %smin%s: ", kq, kq);
- buffer_rrd_value(wb, r->min);
- buffer_sprintf(wb, ",\n %smax%s: ", kq, kq);
- buffer_rrd_value(wb, r->max);
- buffer_strcat(wb, "\n}\n");
-}
-
-#define JSON_DATES_JS 1
-#define JSON_DATES_TIMESTAMP 2
-
-static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
-{
- rrdset_check_rdlock(r->st);
-
- //info("RRD2JSON(): %s: BEGIN", r->st->id);
- int row_annotations = 0, dates, dates_with_new = 0;
- char kq[2] = "", // key quote
- sq[2] = "", // string quote
- pre_label[101] = "", // before each label
- post_label[101] = "", // after each label
- pre_date[101] = "", // the beginning of line, to the date
- post_date[101] = "", // closing the date
- pre_value[101] = "", // before each value
- post_value[101] = "", // after each value
- post_line[101] = "", // at the end of each row
- normal_annotation[201] = "", // default row annotation
- overflow_annotation[201] = "", // overflow row annotation
- data_begin[101] = "", // between labels and values
- finish[101] = ""; // at the end of everything
-
- if(datatable) {
- dates = JSON_DATES_JS;
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
- row_annotations = 1;
- snprintfz(pre_date, 100, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
- snprintfz(post_date, 100, "%s}", sq);
- snprintfz(pre_label, 100, ",\n {%sid%s:%s%s,%slabel%s:%s", kq, kq, sq, sq, kq, kq, sq);
- snprintfz(post_label, 100, "%s,%spattern%s:%s%s,%stype%s:%snumber%s}", sq, kq, kq, sq, sq, kq, kq, sq, sq);
- snprintfz(pre_value, 100, ",{%sv%s:", kq, kq);
- strcpy(post_value, "}");
- strcpy(post_line, "]}");
- snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq);
- strcpy(finish, "\n ]\n}");
-
- snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
- snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
-
- buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
-
- // remove the valueobjects flag
- // google wants its own keys
- if(options & RRDR_OPTION_OBJECTSROWS)
- options &= ~RRDR_OPTION_OBJECTSROWS;
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- if(options & RRDR_OPTION_GOOGLE_JSON) {
- dates = JSON_DATES_JS;
- dates_with_new = 1;
- }
- else {
- dates = JSON_DATES_TIMESTAMP;
- dates_with_new = 0;
- }
- if( options & RRDR_OPTION_OBJECTSROWS )
- strcpy(pre_date, " { ");
- else
- strcpy(pre_date, " [ ");
- strcpy(pre_label, ", \"");
- strcpy(post_label, "\"");
- strcpy(pre_value, ", ");
- if( options & RRDR_OPTION_OBJECTSROWS )
- strcpy(post_line, "}");
- else
- strcpy(post_line, "]");
- snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq);
- strcpy(finish, "\n ]\n}");
-
- buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq);
- buffer_sprintf(wb, "%stime%s", sq, sq);
- }
-
- // -------------------------------------------------------------------------
- // print the JSON header
-
- long c, i;
- RRDDIM *rd;
-
- // print the header lines
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- buffer_strcat(wb, pre_label);
- buffer_strcat(wb, rd->name);
- buffer_strcat(wb, post_label);
- i++;
- }
- if(!i) {
- buffer_strcat(wb, pre_label);
- buffer_strcat(wb, "no data");
- buffer_strcat(wb, post_label);
- }
-
- // print the begin of row data
- buffer_strcat(wb, data_begin);
-
- // if all dimensions are hidden, print a null
- if(!i) {
- buffer_strcat(wb, finish);
- return;
- }
-
- long start = 0, end = rrdr_rows(r), step = 1;
- if((options & RRDR_OPTION_REVERSED)) {
- start = rrdr_rows(r) - 1;
- end = -1;
- step = -1;
- }
-
- // for each line in the array
- calculated_number total = 1;
- for(i = start; i != end ;i += step) {
- calculated_number *cn = &r->v[ i * r->d ];
- uint8_t *co = &r->o[ i * r->d ];
-
- time_t now = r->t[i];
-
- if(dates == JSON_DATES_JS) {
- // generate the local date time
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
- if(!tm) { error("localtime_r() failed."); continue; }
-
- if(likely(i != start)) buffer_strcat(wb, ",\n");
- buffer_strcat(wb, pre_date);
-
- if( options & RRDR_OPTION_OBJECTSROWS )
- buffer_sprintf(wb, "%stime%s: ", kq, kq);
-
- if(dates_with_new)
- buffer_strcat(wb, "new ");
-
- buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
-
- buffer_strcat(wb, post_date);
-
- if(row_annotations) {
- // google supports one annotation per row
- int annotation_found = 0;
- for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
- if(co[c] & RRDR_RESET) {
- buffer_strcat(wb, overflow_annotation);
- annotation_found = 1;
- break;
- }
- }
- if(!annotation_found)
- buffer_strcat(wb, normal_annotation);
- }
- }
- else {
- // print the timestamp of the line
- if(likely(i != start)) buffer_strcat(wb, ",\n");
- buffer_strcat(wb, pre_date);
-
- if( options & RRDR_OPTION_OBJECTSROWS )
- buffer_sprintf(wb, "%stime%s: ", kq, kq);
-
- buffer_rrd_value(wb, (calculated_number)r->t[i]);
- // in ms
- if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
-
- buffer_strcat(wb, post_date);
- }
-
- int set_min_max = 0;
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- total = 0;
- for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- calculated_number n = cn[c];
-
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- total += n;
- }
- // prevent a division by zero
- if(total == 0) total = 1;
- set_min_max = 1;
- }
-
- // for each dimension
- for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- calculated_number n = cn[c];
-
- buffer_strcat(wb, pre_value);
-
- if( options & RRDR_OPTION_OBJECTSROWS )
- buffer_sprintf(wb, "%s%s%s: ", kq, rd->name, kq);
-
- if(co[c] & RRDR_EMPTY) {
- if(options & RRDR_OPTION_NULL2ZERO)
- buffer_strcat(wb, "0");
- else
- buffer_strcat(wb, "null");
- }
- else {
- if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- n = n * 100 / total;
-
- if(unlikely(set_min_max)) {
- r->min = r->max = n;
- set_min_max = 0;
- }
-
- if(n < r->min) r->min = n;
- if(n > r->max) r->max = n;
- }
-
- buffer_rrd_value(wb, n);
- }
-
- buffer_strcat(wb, post_value);
- }
-
- buffer_strcat(wb, post_line);
- }
-
- buffer_strcat(wb, finish);
- //info("RRD2JSON(): %s: END", r->st->id);
-}
-
-static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline, const char *betweenlines)
-{
- rrdset_check_rdlock(r->st);
-
- //info("RRD2CSV(): %s: BEGIN", r->st->id);
- long c, i;
- RRDDIM *d;
-
- // print the csv header
- for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- if(!i) {
- buffer_strcat(wb, startline);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- buffer_strcat(wb, "time");
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- }
- buffer_strcat(wb, separator);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- buffer_strcat(wb, d->name);
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
- i++;
- }
- buffer_strcat(wb, endline);
-
- if(!i) {
- // no dimensions present
- return;
- }
-
- long start = 0, end = rrdr_rows(r), step = 1;
- if((options & RRDR_OPTION_REVERSED)) {
- start = rrdr_rows(r) - 1;
- end = -1;
- step = -1;
- }
-
- // for each line in the array
- calculated_number total = 1;
- for(i = start; i != end ;i += step) {
- calculated_number *cn = &r->v[ i * r->d ];
- uint8_t *co = &r->o[ i * r->d ];
-
- buffer_strcat(wb, betweenlines);
- buffer_strcat(wb, startline);
-
- time_t now = r->t[i];
-
- if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
- // print the timestamp of the line
- buffer_rrd_value(wb, (calculated_number)now);
- // in ms
- if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
- }
- else {
- // generate the local date time
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
- if(!tm) { error("localtime() failed."); continue; }
- buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
- }
-
- int set_min_max = 0;
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- total = 0;
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
- calculated_number n = cn[c];
-
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- total += n;
- }
- // prevent a division by zero
- if(total == 0) total = 1;
- set_min_max = 1;
- }
-
- // for each dimension
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- buffer_strcat(wb, separator);
-
- calculated_number n = cn[c];
-
- if(co[c] & RRDR_EMPTY) {
- if(options & RRDR_OPTION_NULL2ZERO)
- buffer_strcat(wb, "0");
- else
- buffer_strcat(wb, "null");
- }
- else {
- if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- n = n * 100 / total;
-
- if(unlikely(set_min_max)) {
- r->min = r->max = n;
- set_min_max = 0;
- }
-
- if(n < r->min) r->min = n;
- if(n > r->max) r->max = n;
- }
-
- buffer_rrd_value(wb, n);
- }
- }
-
- buffer_strcat(wb, endline);
- }
- //info("RRD2CSV(): %s: END", r->st->id);
-}
-
-inline static calculated_number rrdr2value(RRDR *r, long i, uint32_t options, int *all_values_are_null) {
- rrdset_check_rdlock(r->st);
-
- long c;
- RRDDIM *d;
-
- calculated_number *cn = &r->v[ i * r->d ];
- uint8_t *co = &r->o[ i * r->d ];
-
- calculated_number sum = 0, min = 0, max = 0, v;
- int all_null = 1, init = 1;
-
- calculated_number total = 1;
- int set_min_max = 0;
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- total = 0;
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
- calculated_number n = cn[c];
-
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- total += n;
- }
- // prevent a division by zero
- if(total == 0) total = 1;
- set_min_max = 1;
- }
-
- // for each dimension
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
-
- calculated_number n = cn[c];
-
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
- n = -n;
-
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
- n = n * 100 / total;
-
- if(unlikely(set_min_max)) {
- r->min = r->max = n;
- set_min_max = 0;
- }
-
- if(n < r->min) r->min = n;
- if(n > r->max) r->max = n;
- }
-
- if(unlikely(init)) {
- if(n > 0) {
- min = 0;
- max = n;
- }
- else {
- min = n;
- max = 0;
- }
- init = 0;
- }
-
- if(likely(!(co[c] & RRDR_EMPTY))) {
- all_null = 0;
- sum += n;
- }
-
- if(n < min) min = n;
- if(n > max) max = n;
- }
-
- if(unlikely(all_null)) {
- if(likely(all_values_are_null))
- *all_values_are_null = 1;
- return 0;
- }
- else {
- if(likely(all_values_are_null))
- *all_values_are_null = 0;
- }
-
- if(options & RRDR_OPTION_MIN2MAX)
- v = max - min;
- else
- v = sum;
-
- return v;
-}
-
-static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix, const char *separator, const char *suffix)
-{
- //info("RRD2SSV(): %s: BEGIN", r->st->id);
- long i;
-
- buffer_strcat(wb, prefix);
- long start = 0, end = rrdr_rows(r), step = 1;
- if((options & RRDR_OPTION_REVERSED)) {
- start = rrdr_rows(r) - 1;
- end = -1;
- step = -1;
- }
-
- // for each line in the array
- for(i = start; i != end ;i += step) {
- int all_values_are_null = 0;
- calculated_number v = rrdr2value(r, i, options, &all_values_are_null);
-
- if(likely(i != start)) {
- if(r->min > v) r->min = v;
- if(r->max < v) r->max = v;
- }
- else {
- r->min = v;
- r->max = v;
- }
-
- if(likely(i != start))
- buffer_strcat(wb, separator);
-
- if(all_values_are_null) {
- if(options & RRDR_OPTION_NULL2ZERO)
- buffer_strcat(wb, "0");
- else
- buffer_strcat(wb, "null");
- }
- else
- buffer_rrd_value(wb, v);
- }
- buffer_strcat(wb, suffix);
- //info("RRD2SSV(): %s: END", r->st->id);
-}
-
-inline static calculated_number *rrdr_line_values(RRDR *r)
-{
- return &r->v[ r->c * r->d ];
-}
-
-inline static uint8_t *rrdr_line_options(RRDR *r)
-{
- return &r->o[ r->c * r->d ];
-}
-
-inline static int rrdr_line_init(RRDR *r, time_t t)
-{
- r->c++;
-
- if(unlikely(r->c >= r->n)) {
- error("requested to step above RRDR size for chart %s", r->st->name);
- r->c = r->n - 1;
- }
-
- // save the time
- r->t[r->c] = t;
-
- return 1;
-}
-
-inline static void rrdr_lock_rrdset(RRDR *r) {
- if(unlikely(!r)) {
- error("NULL value given!");
- return;
- }
-
- rrdset_rdlock(r->st);
- r->has_st_lock = 1;
-}
-
-inline static void rrdr_unlock_rrdset(RRDR *r) {
- if(unlikely(!r)) {
- error("NULL value given!");
- return;
- }
-
- if(likely(r->has_st_lock)) {
- rrdset_unlock(r->st);
- r->has_st_lock = 0;
- }
-}
-
-inline static void rrdr_free(RRDR *r)
-{
- if(unlikely(!r)) {
- error("NULL value given!");
- return;
- }
-
- rrdr_unlock_rrdset(r);
- freez(r->t);
- freez(r->v);
- freez(r->o);
- freez(r->od);
- freez(r);
-}
-
-static inline void rrdr_done(RRDR *r)
-{
- r->rows = r->c + 1;
- r->c = 0;
-}
-
-static RRDR *rrdr_create(RRDSET *st, long n)
-{
- if(unlikely(!st)) {
- error("NULL value given!");
- return NULL;
- }
-
- RRDR *r = callocz(1, sizeof(RRDR));
- r->st = st;
-
- rrdr_lock_rrdset(r);
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) r->d++;
-
- r->n = n;
-
- r->t = mallocz(n * sizeof(time_t));
- r->v = mallocz(n * r->d * sizeof(calculated_number));
- r->o = mallocz(n * r->d * sizeof(uint8_t));
- r->od = mallocz(r->d * sizeof(uint8_t));
-
- // set the hidden flag on hidden dimensions
- int c;
- for(c = 0, rd = st->dimensions ; rd ; c++, rd = rd->next) {
- if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)))
- r->od[c] = RRDR_HIDDEN;
- else
- r->od[c] = 0;
- }
-
- r->c = -1;
- r->group = 1;
- r->update_every = 1;
-
- return r;
-}
-
-RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int group_method, long group_time, int aligned)
-{
-#ifdef NETDATA_INTERNAL_CHECKS
- int debug = rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?1:0;
-#endif
- int absolute_period_requested = -1;
-
- time_t first_entry_t = rrdset_first_entry_t(st);
- time_t last_entry_t = rrdset_last_entry_t(st);
-
- if(before == 0 && after == 0) {
- // dump the all the data
- before = last_entry_t;
- after = first_entry_t;
- absolute_period_requested = 0;
- }
-
- // allow relative for before (smaller than API_RELATIVE_TIME_MAX)
- if(((before < 0)?-before:before) <= API_RELATIVE_TIME_MAX) {
- if(abs(before) % st->update_every) {
- // make sure it is multiple of st->update_every
- if(before < 0) before = before - st->update_every - before % st->update_every;
- else before = before + st->update_every - before % st->update_every;
- }
- if(before > 0) before = first_entry_t + before;
- else before = last_entry_t + before;
- absolute_period_requested = 0;
- }
-
- // allow relative for after (smaller than API_RELATIVE_TIME_MAX)
- if(((after < 0)?-after:after) <= API_RELATIVE_TIME_MAX) {
- if(after == 0) after = -st->update_every;
- if(abs(after) % st->update_every) {
- // make sure it is multiple of st->update_every
- if(after < 0) after = after - st->update_every - after % st->update_every;
- else after = after + st->update_every - after % st->update_every;
- }
- after = before + after;
- absolute_period_requested = 0;
- }
-
- if(absolute_period_requested == -1)
- absolute_period_requested = 1;
-
- // make sure they are within our timeframe
- if(before > last_entry_t) before = last_entry_t;
- if(before < first_entry_t) before = first_entry_t;
-
- if(after > last_entry_t) after = last_entry_t;
- if(after < first_entry_t) after = first_entry_t;
-
- // check if they are upside down
- if(after > before) {
- time_t tmp = before;
- before = after;
- after = tmp;
- }
-
- // the duration of the chart
- time_t duration = before - after;
- long available_points = duration / st->update_every;
-
- if(duration <= 0 || available_points <= 0)
- return rrdr_create(st, 1);
-
- // check the number of wanted points in the result
- if(unlikely(points < 0)) points = -points;
- if(unlikely(points > available_points)) points = available_points;
- if(unlikely(points == 0)) points = available_points;
-
- // calculate the desired grouping of source data points
- long group = available_points / points;
- if(unlikely(group <= 0)) group = 1;
- if(unlikely(available_points % points > points / 2)) group++; // rounding to the closest integer
-
- // group_time enforces a certain grouping multiple
- calculated_number group_sum_divisor = 1.0;
- long group_points = 1;
- if(unlikely(group_time > st->update_every)) {
- if (unlikely(group_time > duration)) {
- // group_time is above the available duration
-
- #ifdef NETDATA_INTERNAL_CHECKS
- info("INTERNAL CHECK: %s: requested gtime %ld secs, is greater than the desired duration %ld secs", st->id, group_time, duration);
- #endif
-
- group = points; // use all the points
- }
- else {
- // the points we should group to satisfy gtime
- group_points = group_time / st->update_every;
- if(unlikely(group_time % group_points)) {
- #ifdef NETDATA_INTERNAL_CHECKS
- info("INTERNAL CHECK: %s: requested gtime %ld secs, is not a multiple of the chart's data collection frequency %d secs", st->id, group_time, st->update_every);
- #endif
-
- group_points++;
- }
-
- // adapt group according to group_points
- if(unlikely(group < group_points)) group = group_points; // do not allow grouping below the desired one
- if(unlikely(group % group_points)) group += group_points - (group % group_points); // make sure group is multiple of group_points
-
- //group_sum_divisor = group / group_points;
- group_sum_divisor = (calculated_number)(group * st->update_every) / (calculated_number)group_time;
- }
- }
-
- time_t after_new = after - (after % ( ((aligned)?group:1) * st->update_every ));
- time_t before_new = before - (before % ( ((aligned)?group:1) * st->update_every ));
- long points_new = (before_new - after_new) / st->update_every / group;
-
- // find the starting and ending slots in our round robin db
- long start_at_slot = rrdset_time2slot(st, before_new),
- stop_at_slot = rrdset_time2slot(st, after_new);
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(after_new < first_entry_t)
- error("INTERNAL CHECK: after_new %u is too small, minimum %u", (uint32_t)after_new, (uint32_t)first_entry_t);
-
- if(after_new > last_entry_t)
- error("INTERNAL CHECK: after_new %u is too big, maximum %u", (uint32_t)after_new, (uint32_t)last_entry_t);
-
- if(before_new < first_entry_t)
- error("INTERNAL CHECK: before_new %u is too small, minimum %u", (uint32_t)before_new, (uint32_t)first_entry_t);
-
- if(before_new > last_entry_t)
- error("INTERNAL CHECK: before_new %u is too big, maximum %u", (uint32_t)before_new, (uint32_t)last_entry_t);
-
- if(start_at_slot < 0 || start_at_slot >= st->entries)
- error("INTERNAL CHECK: start_at_slot is invalid %ld, expected 0 to %ld", start_at_slot, st->entries - 1);
-
- if(stop_at_slot < 0 || stop_at_slot >= st->entries)
- error("INTERNAL CHECK: stop_at_slot is invalid %ld, expected 0 to %ld", stop_at_slot, st->entries - 1);
-
- if(points_new > (before_new - after_new) / group / st->update_every + 1)
- error("INTERNAL CHECK: points_new %ld is more than points %ld", points_new, (before_new - after_new) / group / st->update_every + 1);
-
- if(group < group_points)
- error("INTERNAL CHECK: group %ld is less than the desired group points %ld", group, group_points);
-
- if(group > group_points && group % group_points)
- error("INTERNAL CHECK: group %ld is not a multiple of the desired group points %ld", group, group_points);
-#endif
-
- //info("RRD2RRDR(): %s: wanted %ld points, got %ld - group=%ld, wanted duration=%u, got %u - wanted %ld - %ld, got %ld - %ld", st->id, points, points_new, group, before - after, before_new - after_new, after, before, after_new, before_new);
-
- after = after_new;
- before = before_new;
- duration = before - after;
- points = points_new;
-
- // Now we have:
- // before = the end time of the calculation
- // after = the start time of the calculation
- // duration = the duration of the calculation
- // group = the number of source points to aggregate / group together
- // method = the method of grouping source points
- // points = the number of points to generate
-
-
- // -------------------------------------------------------------------------
- // initialize our result set
-
- RRDR *r = rrdr_create(st, points);
- if(unlikely(!r)) {
-#ifdef NETDATA_INTERNAL_CHECKS
- error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points);
-#endif
- return NULL;
- }
-
- if(unlikely(!r->d)) {
-#ifdef NETDATA_INTERNAL_CHECKS
- error("INTERNAL CHECK: Returning empty RRDR (no dimensions in RRDSET) for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points);
-#endif
- return r;
- }
-
- if(unlikely(absolute_period_requested == 1))
- r->result_options |= RRDR_RESULT_OPTION_ABSOLUTE;
- else
- r->result_options |= RRDR_RESULT_OPTION_RELATIVE;
-
- // find how many dimensions we have
- long dimensions = r->d;
-
-
- // -------------------------------------------------------------------------
- // checks for debugging
-#ifdef NETDATA_INTERNAL_CHECKS
- if(debug) debug(D_RRD_STATS, "INFO %s first_t: %u, last_t: %u, all_duration: %u, after: %u, before: %u, duration: %u, points: %ld, group: %ld, group_points: %ld"
- , st->id
- , (uint32_t)first_entry_t
- , (uint32_t)last_entry_t
- , (uint32_t)(last_entry_t - first_entry_t)
- , (uint32_t)after
- , (uint32_t)before
- , (uint32_t)duration
- , points
- , group
- , group_points
- );
-#endif
-
- // -------------------------------------------------------------------------
- // temp arrays for keeping values per dimension
-
- calculated_number last_values[dimensions]; // keep the last value of each dimension
- calculated_number group_values[dimensions]; // keep sums when grouping
- long group_counts[dimensions]; // keep the number of values added to group_values
- uint8_t group_options[dimensions];
- uint8_t found_non_zero[dimensions];
-
-
- // initialize them
- RRDDIM *rd;
- long c;
- rrdset_check_rdlock(st);
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
- last_values[c] = 0;
- group_values[c] = (group_method == GROUP_MAX || group_method == GROUP_MIN)?NAN:0;
- group_counts[c] = 0;
- group_options[c] = 0;
- found_non_zero[c] = 0;
- }
-
-
- // -------------------------------------------------------------------------
- // the main loop
-
- time_t now = rrdset_slot2time(st, start_at_slot),
- dt = st->update_every,
- group_start_t = 0;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(debug)) debug(D_RRD_STATS, "BEGIN %s after_t: %u (stop_at_t: %ld), before_t: %u (start_at_t: %ld), start_t(now): %u, current_entry: %ld, entries: %ld"
- , st->id
- , (uint32_t)after
- , stop_at_slot
- , (uint32_t)before
- , start_at_slot
- , (uint32_t)now
- , st->current_entry
- , st->entries
- );
-#endif
-
- r->group = group;
- r->update_every = (int)group * st->update_every;
- r->before = now;
- r->after = now;
-
- //info("RRD2RRDR(): %s: STARTING", st->id);
-
- long slot = start_at_slot, counter = 0, stop_now = 0, added = 0, group_count = 0, add_this = 0;
- for(; !stop_now ; now -= dt, slot--, counter++) {
- if(unlikely(slot < 0)) slot = st->entries - 1;
- if(unlikely(slot == stop_at_slot)) stop_now = counter;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(debug)) debug(D_RRD_STATS, "ROW %s slot: %ld, entries_counter: %ld, group_count: %ld, added: %ld, now: %ld, %s %s"
- , st->id
- , slot
- , counter
- , group_count + 1
- , added
- , now
- , (group_count + 1 == group)?"PRINT":" - "
- , (now >= after && now <= before)?"RANGE":" - "
- );
-#endif
-
- // make sure we return data in the proper time range
- if(unlikely(now > before)) continue;
- if(unlikely(now < after)) break;
-
- if(unlikely(group_count == 0)) group_start_t = now;
- group_count++;
-
- if(unlikely(group_count == group)) {
- if(unlikely(added >= points)) break;
- add_this = 1;
- }
-
- // do the calculations
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
- storage_number n = rd->values[slot];
- if(unlikely(!does_storage_number_exist(n))) continue;
-
- group_counts[c]++;
-
- calculated_number value = unpack_storage_number(n);
- if(likely(value != 0.0)) {
- group_options[c] |= RRDR_NONZERO;
- found_non_zero[c] = 1;
- }
-
- if(unlikely(did_storage_number_reset(n)))
- group_options[c] |= RRDR_RESET;
-
- switch(group_method) {
- case GROUP_MIN:
- if(unlikely(isnan(group_values[c])) ||
- calculated_number_fabs(value) < calculated_number_fabs(group_values[c]))
- group_values[c] = value;
- break;
-
- case GROUP_MAX:
- if(unlikely(isnan(group_values[c])) ||
- calculated_number_fabs(value) > calculated_number_fabs(group_values[c]))
- group_values[c] = value;
- break;
-
- default:
- case GROUP_SUM:
- case GROUP_AVERAGE:
- case GROUP_UNDEFINED:
- group_values[c] += value;
- break;
-
- case GROUP_INCREMENTAL_SUM:
- if(unlikely(slot == start_at_slot))
- last_values[c] = value;
-
- group_values[c] += last_values[c] - value;
- last_values[c] = value;
- break;
- }
- }
-
- // added it
- if(unlikely(add_this)) {
- if(unlikely(!rrdr_line_init(r, group_start_t))) break;
-
- r->after = now;
-
- calculated_number *cn = rrdr_line_values(r);
- uint8_t *co = rrdr_line_options(r);
-
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
-
- // update the dimension options
- if(likely(found_non_zero[c])) r->od[c] |= RRDR_NONZERO;
-
- // store the specific point options
- co[c] = group_options[c];
-
- // store the value
- if(unlikely(group_counts[c] == 0)) {
- cn[c] = 0.0;
- co[c] |= RRDR_EMPTY;
- group_values[c] = (group_method == GROUP_MAX || group_method == GROUP_MIN)?NAN:0;
- }
- else {
- switch(group_method) {
- case GROUP_MIN:
- case GROUP_MAX:
- if(unlikely(isnan(group_values[c])))
- cn[c] = 0;
- else {
- cn[c] = group_values[c];
- group_values[c] = NAN;
- }
- break;
-
- case GROUP_SUM:
- case GROUP_INCREMENTAL_SUM:
- cn[c] = group_values[c];
- group_values[c] = 0;
- break;
-
- default:
- case GROUP_AVERAGE:
- case GROUP_UNDEFINED:
- if(unlikely(group_points != 1))
- cn[c] = group_values[c] / group_sum_divisor;
- else
- cn[c] = group_values[c] / group_counts[c];
-
- group_values[c] = 0;
- break;
- }
-
- if(cn[c] < r->min) r->min = cn[c];
- if(cn[c] > r->max) r->max = cn[c];
- }
-
- // reset for the next loop
- group_counts[c] = 0;
- group_options[c] = 0;
- }
-
- added++;
- group_count = 0;
- add_this = 0;
- }
- }
-
- rrdr_done(r);
- //info("RRD2RRDR(): %s: END %ld loops made, %ld points generated", st->id, counter, rrdr_rows(r));
- //error("SHIFT: %s: wanted %ld points, got %ld", st->id, points, rrdr_rows(r));
- return r;
-}
-
-int rrdset2value_api_v1(
- RRDSET *st
- , BUFFER *wb
- , calculated_number *n
- , const char *dimensions
- , long points
- , long long after
- , long long before
- , int group_method
- , long group_time
- , uint32_t options
- , time_t *db_after
- , time_t *db_before
- , int *value_is_null
-) {
- RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, !(options & RRDR_OPTION_NOT_ALIGNED));
- if(!r) {
- if(value_is_null) *value_is_null = 1;
- return 500;
- }
-
- if(rrdr_rows(r) == 0) {
- rrdr_free(r);
-
- if(db_after) *db_after = 0;
- if(db_before) *db_before = 0;
- if(value_is_null) *value_is_null = 1;
-
- return 400;
- }
-
- if(wb) {
- if (r->result_options & RRDR_RESULT_OPTION_RELATIVE)
- buffer_no_cacheable(wb);
- else if (r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
- buffer_cacheable(wb);
- }
-
- options = rrdr_check_options(r, options, dimensions);
-
- if(dimensions)
- rrdr_disable_not_selected_dimensions(r, options, dimensions);
-
- if(db_after) *db_after = r->after;
- if(db_before) *db_before = r->before;
-
- long i = (options & RRDR_OPTION_REVERSED)?rrdr_rows(r) - 1:0;
- *n = rrdr2value(r, i, options, value_is_null);
-
- rrdr_free(r);
- return 200;
-}
-
-int rrdset2anything_api_v1(
- RRDSET *st
- , BUFFER *wb
- , BUFFER *dimensions
- , uint32_t format
- , long points
- , long long after
- , long long before
- , int group_method
- , long group_time
- , uint32_t options
- , time_t *latest_timestamp
-) {
- st->last_accessed_time = now_realtime_sec();
-
- RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, !(options & RRDR_OPTION_NOT_ALIGNED));
- if(!r) {
- buffer_strcat(wb, "Cannot generate output with these parameters on this chart.");
- return 500;
- }
-
- if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
- buffer_no_cacheable(wb);
- else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
- buffer_cacheable(wb);
-
- options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
-
- if(dimensions)
- rrdr_disable_not_selected_dimensions(r, options, buffer_tostring(dimensions));
-
- if(latest_timestamp && rrdr_rows(r) > 0)
- *latest_timestamp = r->before;
-
- switch(format) {
- case DATASOURCE_SSV:
- if(options & RRDR_OPTION_JSON_WRAP) {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
- rrdr2ssv(r, wb, options, "", " ", "");
- rrdr_json_wrapper_end(r, wb, format, options, 1);
- }
- else {
- wb->contenttype = CT_TEXT_PLAIN;
- rrdr2ssv(r, wb, options, "", " ", "");
- }
- break;
-
- case DATASOURCE_SSV_COMMA:
- if(options & RRDR_OPTION_JSON_WRAP) {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
- rrdr2ssv(r, wb, options, "", ",", "");
- rrdr_json_wrapper_end(r, wb, format, options, 1);
- }
- else {
- wb->contenttype = CT_TEXT_PLAIN;
- rrdr2ssv(r, wb, options, "", ",", "");
- }
- break;
-
- case DATASOURCE_JS_ARRAY:
- if(options & RRDR_OPTION_JSON_WRAP) {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
- rrdr2ssv(r, wb, options, "[", ",", "]");
- rrdr_json_wrapper_end(r, wb, format, options, 0);
- }
- else {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr2ssv(r, wb, options, "[", ",", "]");
- }
- break;
-
- case DATASOURCE_CSV:
- if(options & RRDR_OPTION_JSON_WRAP) {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
- rrdr2csv(r, wb, options, "", ",", "\\n", "");
- rrdr_json_wrapper_end(r, wb, format, options, 1);
- }
- else {
- wb->contenttype = CT_TEXT_PLAIN;
- rrdr2csv(r, wb, options, "", ",", "\r\n", "");
- }
- break;
-
- case DATASOURCE_CSV_JSON_ARRAY:
- wb->contenttype = CT_APPLICATION_JSON;
- if(options & RRDR_OPTION_JSON_WRAP) {
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
- buffer_strcat(wb, "[\n");
- rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
- buffer_strcat(wb, "\n]");
- rrdr_json_wrapper_end(r, wb, format, options, 0);
- }
- else {
- wb->contenttype = CT_TEXT_PLAIN;
- buffer_strcat(wb, "[\n");
- rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
- buffer_strcat(wb, "\n]");
- }
- break;
-
- case DATASOURCE_TSV:
- if(options & RRDR_OPTION_JSON_WRAP) {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
- rrdr2csv(r, wb, options, "", "\t", "\\n", "");
- rrdr_json_wrapper_end(r, wb, format, options, 1);
- }
- else {
- wb->contenttype = CT_TEXT_PLAIN;
- rrdr2csv(r, wb, options, "", "\t", "\r\n", "");
- }
- break;
-
- case DATASOURCE_HTML:
- if(options & RRDR_OPTION_JSON_WRAP) {
- wb->contenttype = CT_APPLICATION_JSON;
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
- buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n");
- rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\\n", "");
- buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n");
- rrdr_json_wrapper_end(r, wb, format, options, 1);
- }
- else {
- wb->contenttype = CT_TEXT_HTML;
- buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n");
- rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\n", "");
- buffer_strcat(wb, "</table>\n</center>\n</html>\n");
- }
- break;
-
- case DATASOURCE_DATATABLE_JSONP:
- wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
-
- rrdr2json(r, wb, options, 1);
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_end(r, wb, format, options, 0);
- break;
-
- case DATASOURCE_DATATABLE_JSON:
- wb->contenttype = CT_APPLICATION_JSON;
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
-
- rrdr2json(r, wb, options, 1);
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_end(r, wb, format, options, 0);
- break;
-
- case DATASOURCE_JSONP:
- wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
-
- rrdr2json(r, wb, options, 0);
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_end(r, wb, format, options, 0);
- break;
-
- case DATASOURCE_JSON:
- default:
- wb->contenttype = CT_APPLICATION_JSON;
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
-
- rrdr2json(r, wb, options, 0);
-
- if(options & RRDR_OPTION_JSON_WRAP)
- rrdr_json_wrapper_end(r, wb, format, options, 0);
- break;
- }
-
- rrdr_free(r);
- return 200;
-}
diff --git a/src/rrd2json.h b/src/rrd2json.h
deleted file mode 100644
index b41c814ec..000000000
--- a/src/rrd2json.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef NETDATA_RRD2JSON_H
-#define NETDATA_RRD2JSON_H 1
-
-#define HOSTNAME_MAX 1024
-
-#define API_RELATIVE_TIME_MAX (3 * 365 * 86400)
-
-// type of JSON generations
-#define DATASOURCE_INVALID (-1)
-#define DATASOURCE_JSON 0
-#define DATASOURCE_DATATABLE_JSON 1
-#define DATASOURCE_DATATABLE_JSONP 2
-#define DATASOURCE_SSV 3
-#define DATASOURCE_CSV 4
-#define DATASOURCE_JSONP 5
-#define DATASOURCE_TSV 6
-#define DATASOURCE_HTML 7
-#define DATASOURCE_JS_ARRAY 8
-#define DATASOURCE_SSV_COMMA 9
-#define DATASOURCE_CSV_JSON_ARRAY 10
-
-#define DATASOURCE_FORMAT_JSON "json"
-#define DATASOURCE_FORMAT_DATATABLE_JSON "datatable"
-#define DATASOURCE_FORMAT_DATATABLE_JSONP "datasource"
-#define DATASOURCE_FORMAT_JSONP "jsonp"
-#define DATASOURCE_FORMAT_SSV "ssv"
-#define DATASOURCE_FORMAT_CSV "csv"
-#define DATASOURCE_FORMAT_TSV "tsv"
-#define DATASOURCE_FORMAT_HTML "html"
-#define DATASOURCE_FORMAT_JS_ARRAY "array"
-#define DATASOURCE_FORMAT_SSV_COMMA "ssvcomma"
-#define DATASOURCE_FORMAT_CSV_JSON_ARRAY "csvjsonarray"
-
-#define ALLMETRICS_FORMAT_SHELL "shell"
-#define ALLMETRICS_FORMAT_PROMETHEUS "prometheus"
-#define ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS "prometheus_all_hosts"
-#define ALLMETRICS_FORMAT_JSON "json"
-
-#define ALLMETRICS_SHELL 1
-#define ALLMETRICS_PROMETHEUS 2
-#define ALLMETRICS_JSON 3
-#define ALLMETRICS_PROMETHEUS_ALL_HOSTS 4
-
-#define GROUP_UNDEFINED 0
-#define GROUP_AVERAGE 1
-#define GROUP_MIN 2
-#define GROUP_MAX 3
-#define GROUP_SUM 4
-#define GROUP_INCREMENTAL_SUM 5
-
-#define RRDR_OPTION_NONZERO 0x00000001 // don't output dimensions will just zero values
-#define RRDR_OPTION_REVERSED 0x00000002 // output the rows in reverse order (oldest to newest)
-#define RRDR_OPTION_ABSOLUTE 0x00000004 // values positive, for DATASOURCE_SSV before summing
-#define RRDR_OPTION_MIN2MAX 0x00000008 // when adding dimensions, use max - min, instead of sum
-#define RRDR_OPTION_SECONDS 0x00000010 // output seconds, instead of dates
-#define RRDR_OPTION_MILLISECONDS 0x00000020 // output milliseconds, instead of dates
-#define RRDR_OPTION_NULL2ZERO 0x00000040 // do not show nulls, convert them to zeros
-#define RRDR_OPTION_OBJECTSROWS 0x00000080 // each row of values should be an object, not an array
-#define RRDR_OPTION_GOOGLE_JSON 0x00000100 // comply with google JSON/JSONP specs
-#define RRDR_OPTION_JSON_WRAP 0x00000200 // wrap the response in a JSON header with info about the result
-#define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes
-#define RRDR_OPTION_PERCENTAGE 0x00000800 // give values as percentage of total
-#define RRDR_OPTION_NOT_ALIGNED 0x00001000 // do not align charts for persistant timeframes
-#define RRDR_OPTION_DISPLAY_ABS 0x00002000 // for badges, display the absolute value, but calculate colors with sign
-#define RRDR_OPTION_MATCH_IDS 0x00004000 // when filtering dimensions, match only IDs
-#define RRDR_OPTION_MATCH_NAMES 0x00008000 // when filtering dimensions, match only names
-
-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 int rrdset2anything_api_v1(RRDSET *st, BUFFER *out, BUFFER *dimensions, uint32_t format, long points
- , long long after, long long before, int group_method, long group_time, uint32_t options
- , time_t *latest_timestamp);
-
-extern int rrdset2value_api_v1(RRDSET *st, BUFFER *wb, calculated_number *n, const char *dimensions, long points
- , long long after, long long before, int group_method, long group_time, uint32_t options
- , time_t *db_after, time_t *db_before, int *value_is_null);
-
-#endif /* NETDATA_RRD2JSON_H */
diff --git a/src/rrd2json_api_old.c b/src/rrd2json_api_old.c
deleted file mode 100644
index 003b8626d..000000000
--- a/src/rrd2json_api_old.c
+++ /dev/null
@@ -1,487 +0,0 @@
-#include "common.h"
-
-unsigned long rrdset_info2json_api_old(RRDSET *st, char *options, BUFFER *wb) {
- time_t now = now_realtime_sec();
-
- rrdset_rdlock(st);
-
- st->last_accessed_time = now;
-
- buffer_sprintf(wb,
- "\t\t{\n"
- "\t\t\t\"id\": \"%s\",\n"
- "\t\t\t\"name\": \"%s\",\n"
- "\t\t\t\"type\": \"%s\",\n"
- "\t\t\t\"family\": \"%s\",\n"
- "\t\t\t\"context\": \"%s\",\n"
- "\t\t\t\"title\": \"%s (%s)\",\n"
- "\t\t\t\"priority\": %ld,\n"
- "\t\t\t\"enabled\": %d,\n"
- "\t\t\t\"units\": \"%s\",\n"
- "\t\t\t\"url\": \"/data/%s/%s\",\n"
- "\t\t\t\"chart_type\": \"%s\",\n"
- "\t\t\t\"counter\": %lu,\n"
- "\t\t\t\"entries\": %ld,\n"
- "\t\t\t\"first_entry_t\": %ld,\n"
- "\t\t\t\"last_entry\": %lu,\n"
- "\t\t\t\"last_entry_t\": %ld,\n"
- "\t\t\t\"last_entry_secs_ago\": %ld,\n"
- "\t\t\t\"update_every\": %d,\n"
- "\t\t\t\"isdetail\": %d,\n"
- "\t\t\t\"usec_since_last_update\": %llu,\n"
- "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
- "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
- "\t\t\t\"dimensions\": [\n"
- , st->id
- , st->name
- , st->type
- , st->family
- , st->context
- , st->title, st->name
- , st->priority
- , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?1:0
- , st->units
- , st->name, options?options:""
- , rrdset_type_name(st->chart_type)
- , st->counter
- , st->entries
- , rrdset_first_entry_t(st)
- , rrdset_last_slot(st)
- , rrdset_last_entry_t(st)
- , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st)
- , st->update_every
- , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?1:0
- , st->usec_since_last_update
- , st->collected_total
- , st->last_collected_total
- );
-
- unsigned long memory = st->memsize;
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
-
- memory += rd->memsize;
-
- buffer_sprintf(wb,
- "\t\t\t\t{\n"
- "\t\t\t\t\t\"id\": \"%s\",\n"
- "\t\t\t\t\t\"name\": \"%s\",\n"
- "\t\t\t\t\t\"entries\": %ld,\n"
- "\t\t\t\t\t\"isHidden\": %d,\n"
- "\t\t\t\t\t\"algorithm\": \"%s\",\n"
- "\t\t\t\t\t\"multiplier\": " COLLECTED_NUMBER_FORMAT ",\n"
- "\t\t\t\t\t\"divisor\": " COLLECTED_NUMBER_FORMAT ",\n"
- "\t\t\t\t\t\"last_entry_t\": %ld,\n"
- "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
- "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
- "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
- "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
- "\t\t\t\t\t\"memory\": %lu\n"
- "\t\t\t\t}%s\n"
- , rd->id
- , rd->name
- , rd->entries
- , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0
- , rrd_algorithm_name(rd->algorithm)
- , rd->multiplier
- , rd->divisor
- , rd->last_collected_time.tv_sec
- , rd->collected_value
- , rd->calculated_value
- , rd->last_collected_value
- , rd->last_calculated_value
- , rd->memsize
- , rd->next?",":""
- );
- }
-
- buffer_sprintf(wb,
- "\t\t\t],\n"
- "\t\t\t\"memory\" : %lu\n"
- "\t\t}"
- , memory
- );
-
- rrdset_unlock(st);
- return memory;
-}
-
-#define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n"
-#define RRD_GRAPH_JSON_FOOTER "\n\t]\n}\n"
-
-void rrd_graph2json_api_old(RRDSET *st, char *options, BUFFER *wb)
-{
- buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
- rrdset_info2json_api_old(st, options, wb);
- buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER);
-}
-
-void rrd_all2json_api_old(RRDHOST *host, BUFFER *wb)
-{
- unsigned long memory = 0;
- long c = 0;
- RRDSET *st;
-
- time_t now = now_realtime_sec();
-
- buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
-
- rrdhost_rdlock(host);
- rrdset_foreach_read(st, host) {
- if(rrdset_is_available_for_viewers(st)) {
- if(c) buffer_strcat(wb, ",\n");
- memory += rrdset_info2json_api_old(st, NULL, wb);
-
- c++;
- st->last_accessed_time = now;
- }
- }
- rrdhost_unlock(host);
-
- buffer_sprintf(wb, "\n\t],\n"
- "\t\"hostname\": \"%s\",\n"
- "\t\"update_every\": %d,\n"
- "\t\"history\": %ld,\n"
- "\t\"memory\": %lu\n"
- "}\n"
- , host->hostname
- , host->rrd_update_every
- , host->rrd_history_entries
- , memory
- );
-}
-
-time_t rrdset2json_api_old(
- int type
- , RRDSET *st
- , BUFFER *wb
- , long points
- , long group
- , int group_method
- , time_t after
- , time_t before
- , int only_non_zero
-) {
- int c;
- rrdset_rdlock(st);
-
- st->last_accessed_time = now_realtime_sec();
-
- // -------------------------------------------------------------------------
- // switch from JSON to google JSON
-
- char kq[2] = "\"";
- char sq[2] = "\"";
- switch(type) {
- case DATASOURCE_DATATABLE_JSON:
- case DATASOURCE_DATATABLE_JSONP:
- kq[0] = '\0';
- sq[0] = '\'';
- break;
-
- case DATASOURCE_JSON:
- default:
- break;
- }
-
-
- // -------------------------------------------------------------------------
- // validate the parameters
-
- if(points < 1) points = 1;
- if(group < 1) group = 1;
-
- if(before == 0 || before > rrdset_last_entry_t(st)) before = rrdset_last_entry_t(st);
- if(after == 0 || after < rrdset_first_entry_t(st)) after = rrdset_first_entry_t(st);
-
- // ---
-
- // our return value (the last timestamp printed)
- // this is required to detect re-transmit in google JSONP
- time_t last_timestamp = 0;
-
-
- // -------------------------------------------------------------------------
- // find how many dimensions we have
-
- int dimensions = 0;
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) dimensions++;
- if(!dimensions) {
- rrdset_unlock(st);
- buffer_strcat(wb, "No dimensions yet.");
- return 0;
- }
-
-
- // -------------------------------------------------------------------------
- // prepare various strings, to speed up the loop
-
- char overflow_annotation[201]; snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
- char normal_annotation[201]; snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
- char pre_date[51]; snprintfz(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
- char post_date[21]; snprintfz(post_date, 20, "%s}", sq);
- char pre_value[21]; snprintfz(pre_value, 20, ",{%sv%s:", kq, kq);
- char post_value[21]; strcpy(post_value, "}");
-
-
- // -------------------------------------------------------------------------
- // checks for debugging
-
- if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)) {
- debug(D_RRD_STATS, "%s first_entry_t = %ld, last_entry_t = %ld, duration = %ld, after = %ld, before = %ld, duration = %ld, entries_to_show = %ld, group = %ld"
- , st->id
- , rrdset_first_entry_t(st)
- , rrdset_last_entry_t(st)
- , rrdset_last_entry_t(st) - rrdset_first_entry_t(st)
- , after
- , before
- , before - after
- , points
- , group
- );
-
- if(before < after)
- debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%ld) is earlier than the oldest (%ld)", st->name, before, after);
-
- if((before - after) > st->entries * st->update_every)
- debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%ld) is higher than the capacity of the database (%ld)", st->name, before - after, st->entries * st->update_every);
- }
-
-
- // -------------------------------------------------------------------------
- // temp arrays for keeping values per dimension
-
- calculated_number group_values[dimensions]; // keep sums when grouping
- int print_hidden[dimensions]; // keep hidden flags
- int found_non_zero[dimensions];
- int found_non_existing[dimensions];
-
- // initialize them
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
- group_values[c] = 0;
- print_hidden[c] = rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0;
- found_non_zero[c] = 0;
- found_non_existing[c] = 0;
- }
-
-
- // error("OLD: points=%d after=%d before=%d group=%d, duration=%d", entries_to_show, before - (st->update_every * group * entries_to_show), before, group, before - after + 1);
- // rrd2array(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method, only_non_zero);
- // rrd2rrdr(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method);
-
- // -------------------------------------------------------------------------
- // remove dimensions that contain only zeros
-
- int max_loop = 1;
- if(only_non_zero) max_loop = 2;
-
- for(; max_loop ; max_loop--) {
-
- // -------------------------------------------------------------------------
- // print the JSON header
-
- buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
-
- // print the header for each dimension
- // and update the print_hidden array for the dimensions that should be hidden
- int pc = 0;
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
- if(!print_hidden[c]) {
- pc++;
- buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
- }
- }
- if(!pc) {
- buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
- }
-
- // print the begin of row data
- buffer_sprintf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
-
-
- // -------------------------------------------------------------------------
- // the main loop
-
- int annotate_reset = 0;
- int annotation_count = 0;
-
- long t = rrdset_time2slot(st, before),
- stop_at_t = rrdset_time2slot(st, after),
- stop_now = 0;
-
- t -= t % group;
-
- time_t now = rrdset_slot2time(st, t),
- dt = st->update_every;
-
- long count = 0, printed = 0, group_count = 0;
- last_timestamp = 0;
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
- debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld"
- , st->id
- , (uint32_t)after
- , (uint32_t)before
- , points
- , group
- , st->current_entry
- , (uint32_t)rrdset_first_entry_t(st)
- , (uint32_t)rrdset_last_entry_t(st)
- , t
- , stop_at_t
- );
-
- long counter = 0;
- for(; !stop_now ; now -= dt, t--, counter++) {
- if(t < 0) t = st->entries - 1;
- if(t == stop_at_t) stop_now = counter;
-
- int print_this = 0;
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
- debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s"
- , st->id
- , t
- , count + 1
- , group_count + 1
- , printed
- , now
- , (group_count + 1 == group)?"PRINT":" - "
- , (now >= after && now <= before)?"RANGE":" - "
- );
-
-
- // make sure we return data in the proper time range
- if(now > before) continue;
- if(now < after) break;
-
- //if(rrdset_slot2time(st, t) != now)
- // error("%s: slot=%ld, now=%ld, slot2time=%ld, diff=%ld, last_entry_t=%ld, rrdset_last_slot=%ld", st->id, t, now, rrdset_slot2time(st,t), now - rrdset_slot2time(st,t), rrdset_last_entry_t(st), rrdset_last_slot(st));
-
- count++;
- group_count++;
-
- // check if we have to print this now
- if(group_count == group) {
- if(printed >= points) {
- // debug(D_RRD_STATS, "Already printed all rows. Stopping.");
- break;
- }
-
- // generate the local date time
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
- if(!tm) { error("localtime() failed."); continue; }
- if(now > last_timestamp) last_timestamp = now;
-
- if(printed) buffer_strcat(wb, "]},\n");
- buffer_strcat(wb, pre_date);
- buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
- buffer_strcat(wb, post_date);
-
- print_this = 1;
- }
-
- // do the calculations
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
- storage_number n = rd->values[t];
- calculated_number value = unpack_storage_number(n);
-
- if(!does_storage_number_exist(n)) {
- value = 0.0;
- found_non_existing[c]++;
- }
- if(did_storage_number_reset(n)) annotate_reset = 1;
-
- switch(group_method) {
- case GROUP_MAX:
- if(abs(value) > abs(group_values[c])) group_values[c] = value;
- break;
-
- case GROUP_SUM:
- group_values[c] += value;
- break;
-
- default:
- case GROUP_AVERAGE:
- group_values[c] += value;
- if(print_this) group_values[c] /= ( group_count - found_non_existing[c] );
- break;
- }
- }
-
- if(print_this) {
- if(annotate_reset) {
- annotation_count++;
- buffer_strcat(wb, overflow_annotation);
- annotate_reset = 0;
- }
- else
- buffer_strcat(wb, normal_annotation);
-
- pc = 0;
- for(c = 0 ; c < dimensions ; c++) {
- if(found_non_existing[c] == group_count) {
- // all entries are non-existing
- pc++;
- buffer_strcat(wb, pre_value);
- buffer_strcat(wb, "null");
- buffer_strcat(wb, post_value);
- }
- else if(!print_hidden[c]) {
- pc++;
- buffer_strcat(wb, pre_value);
- buffer_rrd_value(wb, group_values[c]);
- buffer_strcat(wb, post_value);
-
- if(group_values[c]) found_non_zero[c]++;
- }
-
- // reset them for the next loop
- group_values[c] = 0;
- found_non_existing[c] = 0;
- }
-
- // if all dimensions are hidden, print a null
- if(!pc) {
- buffer_strcat(wb, pre_value);
- buffer_strcat(wb, "null");
- buffer_strcat(wb, post_value);
- }
-
- printed++;
- group_count = 0;
- }
- }
-
- if(printed) buffer_strcat(wb, "]}");
- buffer_strcat(wb, "\n ]\n}\n");
-
- if(only_non_zero && max_loop > 1) {
- int changed = 0;
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
- group_values[c] = 0;
- found_non_existing[c] = 0;
-
- if(!print_hidden[c] && !found_non_zero[c]) {
- changed = 1;
- print_hidden[c] = 1;
- }
- }
-
- if(changed) buffer_flush(wb);
- else break;
- }
- else break;
-
- } // max_loop
-
- debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %zu bytes", st->name, wb->len);
-
- rrdset_unlock(st);
- return last_timestamp;
-}
diff --git a/src/rrd2json_api_old.h b/src/rrd2json_api_old.h
deleted file mode 100644
index f8c63814f..000000000
--- a/src/rrd2json_api_old.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef NETDATA_RRD2JSON_API_OLD_H
-#define NETDATA_RRD2JSON_API_OLD_H
-
-extern unsigned long rrdset_info2json_api_old(RRDSET *st, char *options, BUFFER *wb);
-
-extern void rrd_graph2json_api_old(RRDSET *st, char *options, BUFFER *wb);
-
-extern void rrd_all2json_api_old(RRDHOST *host, BUFFER *wb);
-
-extern time_t rrdset2json_api_old(int type, RRDSET *st, BUFFER *wb, long entries_to_show, long group, int group_method
- , time_t after, time_t before, int only_non_zero);
-
-
-#endif //NETDATA_RRD2JSON_API_OLD_H
diff --git a/src/rrdcalc.c b/src/rrdcalc.c
deleted file mode 100644
index 4e41539e2..000000000
--- a/src/rrdcalc.c
+++ /dev/null
@@ -1,424 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDCALC management
-
-inline const char *rrdcalc_status2string(RRDCALC_STATUS status) {
- switch(status) {
- case RRDCALC_STATUS_REMOVED:
- return "REMOVED";
-
- case RRDCALC_STATUS_UNDEFINED:
- return "UNDEFINED";
-
- case RRDCALC_STATUS_UNINITIALIZED:
- return "UNINITIALIZED";
-
- case RRDCALC_STATUS_CLEAR:
- return "CLEAR";
-
- case RRDCALC_STATUS_RAISED:
- return "RAISED";
-
- case RRDCALC_STATUS_WARNING:
- return "WARNING";
-
- case RRDCALC_STATUS_CRITICAL:
- return "CRITICAL";
-
- default:
- error("Unknown alarm status %d", status);
- return "UNKNOWN";
- }
-}
-
-static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
- RRDHOST *host = st->rrdhost;
-
- debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, host->hostname);
-
- rc->last_status_change = now_realtime_sec();
- rc->rrdset = st;
-
- rc->rrdset_next = st->alarms;
- rc->rrdset_prev = NULL;
-
- if(rc->rrdset_next)
- rc->rrdset_next->rrdset_prev = rc;
-
- st->alarms = rc;
-
- if(rc->update_every < rc->rrdset->update_every) {
- error("Health alarm '%s.%s' has update every %d, less than chart update every %d. Setting alarm update frequency to %d.", rc->rrdset->id, rc->name, rc->update_every, rc->rrdset->update_every, rc->rrdset->update_every);
- rc->update_every = rc->rrdset->update_every;
- }
-
- if(!isnan(rc->green) && isnan(st->green)) {
- debug(D_HEALTH, "Health alarm '%s.%s' green threshold set from " CALCULATED_NUMBER_FORMAT_AUTO " to " CALCULATED_NUMBER_FORMAT_AUTO ".", rc->rrdset->id, rc->name, rc->rrdset->green, rc->green);
- st->green = rc->green;
- }
-
- if(!isnan(rc->red) && isnan(st->red)) {
- debug(D_HEALTH, "Health alarm '%s.%s' red threshold set from " CALCULATED_NUMBER_FORMAT_AUTO " to " CALCULATED_NUMBER_FORMAT_AUTO ".", rc->rrdset->id, rc->name, rc->rrdset->red, rc->red);
- st->red = rc->red;
- }
-
- rc->local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
- rc->family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
-
- char fullname[RRDVAR_MAX_LENGTH + 1];
- snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name);
- rc->hostid = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value);
-
- snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name);
- rc->hostname = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value);
-
- if(!rc->units) rc->units = strdupz(st->units);
-
- {
- time_t now = now_realtime_sec();
- health_alarm_log(
- host,
- rc->id,
- rc->next_event_id++,
- now,
- rc->name,
- rc->rrdset->id,
- rc->rrdset->family,
- rc->exec,
- rc->recipient,
- now - rc->last_status_change,
- rc->old_value,
- rc->value,
- rc->status,
- RRDCALC_STATUS_UNINITIALIZED,
- rc->source,
- rc->units,
- rc->info,
- 0,
- 0
- );
- }
-}
-
-static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) {
- if( (rc->hash_chart == st->hash && !strcmp(rc->chart, st->id)) ||
- (rc->hash_chart == st->hash_name && !strcmp(rc->chart, st->name)))
- return 1;
-
- return 0;
-}
-
-// this has to be called while the RRDHOST is locked
-inline void rrdsetcalc_link_matching(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
- // debug(D_HEALTH, "find matching alarms for chart '%s'", st->id);
-
- RRDCALC *rc;
- for(rc = host->alarms; rc ; rc = rc->next) {
- if(unlikely(rc->rrdset))
- continue;
-
- if(unlikely(rrdcalc_is_matching_this_rrdset(rc, st)))
- rrdsetcalc_link(st, rc);
- }
-}
-
-// this has to be called while the RRDHOST is locked
-inline void rrdsetcalc_unlink(RRDCALC *rc) {
- RRDSET *st = rc->rrdset;
-
- if(!st) {
- debug(D_HEALTH, "Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rc->chart?rc->chart:"NOCHART", rc->name);
- error("Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rc->chart?rc->chart:"NOCHART", rc->name);
- return;
- }
-
- RRDHOST *host = st->rrdhost;
-
- {
- time_t now = now_realtime_sec();
- health_alarm_log(
- host,
- rc->id,
- rc->next_event_id++,
- now,
- rc->name,
- rc->rrdset->id,
- rc->rrdset->family,
- rc->exec,
- rc->recipient,
- now - rc->last_status_change,
- rc->old_value,
- rc->value,
- rc->status,
- RRDCALC_STATUS_REMOVED,
- rc->source,
- rc->units,
- rc->info,
- 0,
- 0
- );
- }
-
- debug(D_HEALTH, "Health unlinking alarm '%s.%s' from chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, host->hostname);
-
- // unlink it
- if(rc->rrdset_prev)
- rc->rrdset_prev->rrdset_next = rc->rrdset_next;
-
- if(rc->rrdset_next)
- rc->rrdset_next->rrdset_prev = rc->rrdset_prev;
-
- if(st->alarms == rc)
- st->alarms = rc->rrdset_next;
-
- rc->rrdset_prev = rc->rrdset_next = NULL;
-
- rrdvar_free(host, &st->rrdvar_root_index, rc->local);
- rc->local = NULL;
-
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rc->family);
- rc->family = NULL;
-
- rrdvar_free(host, &host->rrdvar_root_index, rc->hostid);
- rc->hostid = NULL;
-
- rrdvar_free(host, &host->rrdvar_root_index, rc->hostname);
- rc->hostname = NULL;
-
- rc->rrdset = NULL;
-
- // RRDCALC will remain in RRDHOST
- // so that if the matching chart is found in the future
- // it will be applied automatically
-}
-
-RRDCALC *rrdcalc_find(RRDSET *st, const char *name) {
- RRDCALC *rc;
- uint32_t hash = simple_hash(name);
-
- for( rc = st->alarms; rc ; rc = rc->rrdset_next ) {
- if(unlikely(rc->hash == hash && !strcmp(rc->name, name)))
- return rc;
- }
-
- return NULL;
-}
-
-inline int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name) {
- RRDCALC *rc;
-
- if(unlikely(!chart)) {
- error("attempt to find RRDCALC '%s' without giving a chart name", name);
- return 1;
- }
-
- if(unlikely(!hash_chart)) hash_chart = simple_hash(chart);
- if(unlikely(!hash_name)) hash_name = simple_hash(name);
-
- // make sure it does not already exist
- for(rc = host->alarms; rc ; rc = rc->next) {
- if (unlikely(rc->chart && rc->hash == hash_name && rc->hash_chart == hash_chart && !strcmp(name, rc->name) && !strcmp(chart, rc->chart))) {
- debug(D_HEALTH, "Health alarm '%s.%s' already exists in host '%s'.", chart, name, host->hostname);
- info("Health alarm '%s.%s' already exists in host '%s'.", chart, name, host->hostname);
- return 1;
- }
- }
-
- return 0;
-}
-
-inline uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id) {
- if(chart && name) {
- uint32_t hash_chart = simple_hash(chart);
- uint32_t hash_name = simple_hash(name);
-
- // re-use old IDs, by looking them up in the alarm log
- ALARM_ENTRY *ae;
- for(ae = host->health_log.alarms; ae ;ae = ae->next) {
- if(unlikely(ae->hash_name == hash_name && ae->hash_chart == hash_chart && !strcmp(name, ae->name) && !strcmp(chart, ae->chart))) {
- if(next_event_id) *next_event_id = ae->alarm_event_id + 1;
- return ae->alarm_id;
- }
- }
- }
-
- return host->health_log.next_alarm_id++;
-}
-
-inline void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc) {
- rrdhost_check_rdlock(host);
-
- if(rc->calculation) {
- rc->calculation->status = &rc->status;
- rc->calculation->this = &rc->value;
- rc->calculation->after = &rc->db_after;
- rc->calculation->before = &rc->db_before;
- rc->calculation->rrdcalc = rc;
- }
-
- if(rc->warning) {
- rc->warning->status = &rc->status;
- rc->warning->this = &rc->value;
- rc->warning->after = &rc->db_after;
- rc->warning->before = &rc->db_before;
- rc->warning->rrdcalc = rc;
- }
-
- if(rc->critical) {
- rc->critical->status = &rc->status;
- rc->critical->this = &rc->value;
- rc->critical->after = &rc->db_after;
- rc->critical->before = &rc->db_before;
- rc->critical->rrdcalc = rc;
- }
-
- // link it to the host
- if(likely(host->alarms)) {
- // append it
- RRDCALC *t;
- for(t = host->alarms; t && t->next ; t = t->next) ;
- t->next = rc;
- }
- else {
- host->alarms = rc;
- }
-
- // link it to its chart
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- if(rrdcalc_is_matching_this_rrdset(rc, st)) {
- rrdsetcalc_link(st, rc);
- break;
- }
- }
-}
-
-inline RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart) {
-
- debug(D_HEALTH, "Health creating dynamic alarm (from template) '%s.%s'", chart, rt->name);
-
- if(rrdcalc_exists(host, chart, rt->name, 0, 0))
- return NULL;
-
- RRDCALC *rc = callocz(1, sizeof(RRDCALC));
- rc->next_event_id = 1;
- rc->id = rrdcalc_get_unique_id(host, chart, rt->name, &rc->next_event_id);
- rc->name = strdupz(rt->name);
- rc->hash = simple_hash(rc->name);
- rc->chart = strdupz(chart);
- rc->hash_chart = simple_hash(rc->chart);
-
- if(rt->dimensions) rc->dimensions = strdupz(rt->dimensions);
-
- rc->green = rt->green;
- rc->red = rt->red;
- rc->value = NAN;
- rc->old_value = NAN;
-
- rc->delay_up_duration = rt->delay_up_duration;
- rc->delay_down_duration = rt->delay_down_duration;
- rc->delay_max_duration = rt->delay_max_duration;
- rc->delay_multiplier = rt->delay_multiplier;
-
- rc->group = rt->group;
- rc->after = rt->after;
- rc->before = rt->before;
- rc->update_every = rt->update_every;
- rc->options = rt->options;
-
- if(rt->exec) rc->exec = strdupz(rt->exec);
- if(rt->recipient) rc->recipient = strdupz(rt->recipient);
- if(rt->source) rc->source = strdupz(rt->source);
- if(rt->units) rc->units = strdupz(rt->units);
- if(rt->info) rc->info = strdupz(rt->info);
-
- if(rt->calculation) {
- rc->calculation = expression_parse(rt->calculation->source, NULL, NULL);
- if(!rc->calculation)
- error("Health alarm '%s.%s': failed to parse calculation expression '%s'", chart, rt->name, rt->calculation->source);
- }
- if(rt->warning) {
- rc->warning = expression_parse(rt->warning->source, NULL, NULL);
- if(!rc->warning)
- error("Health alarm '%s.%s': failed to re-parse warning expression '%s'", chart, rt->name, rt->warning->source);
- }
- if(rt->critical) {
- rc->critical = expression_parse(rt->critical->source, NULL, NULL);
- if(!rc->critical)
- error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", chart, rt->name, rt->critical->source);
- }
-
- debug(D_HEALTH, "Health runtime added alarm '%s.%s': exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f",
- (rc->chart)?rc->chart:"NOCHART",
- rc->name,
- (rc->exec)?rc->exec:"DEFAULT",
- (rc->recipient)?rc->recipient:"DEFAULT",
- rc->green,
- rc->red,
- rc->group,
- rc->after,
- rc->before,
- rc->options,
- (rc->dimensions)?rc->dimensions:"NONE",
- rc->update_every,
- (rc->calculation)?rc->calculation->parsed_as:"NONE",
- (rc->warning)?rc->warning->parsed_as:"NONE",
- (rc->critical)?rc->critical->parsed_as:"NONE",
- rc->source,
- rc->delay_up_duration,
- rc->delay_down_duration,
- rc->delay_max_duration,
- rc->delay_multiplier
- );
-
- rrdcalc_create_part2(host, rc);
- return rc;
-}
-
-void rrdcalc_free(RRDCALC *rc) {
- if(unlikely(!rc)) return;
-
- expression_free(rc->calculation);
- expression_free(rc->warning);
- expression_free(rc->critical);
-
- freez(rc->name);
- freez(rc->chart);
- freez(rc->family);
- freez(rc->dimensions);
- freez(rc->exec);
- freez(rc->recipient);
- freez(rc->source);
- freez(rc->units);
- freez(rc->info);
- freez(rc);
-}
-
-void rrdcalc_unlink_and_free(RRDHOST *host, RRDCALC *rc) {
- if(unlikely(!rc)) return;
-
- debug(D_HEALTH, "Health removing alarm '%s.%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname);
-
- // unlink it from RRDSET
- if(rc->rrdset) rrdsetcalc_unlink(rc);
-
- // unlink it from RRDHOST
- if(unlikely(rc == host->alarms))
- host->alarms = rc->next;
-
- else {
- RRDCALC *t;
- for(t = host->alarms; t && t->next != rc; t = t->next) ;
- if(t) {
- t->next = rc->next;
- rc->next = NULL;
- }
- else
- error("Cannot unlink alarm '%s.%s' from host '%s': not found", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname);
- }
-
- rrdcalc_free(rc);
-}
diff --git a/src/rrdcalctemplate.c b/src/rrdcalctemplate.c
deleted file mode 100644
index 75a7002b3..000000000
--- a/src/rrdcalctemplate.c
+++ /dev/null
@@ -1,69 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDCALCTEMPLATE management
-
-void rrdcalctemplate_link_matching(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
- RRDCALCTEMPLATE *rt;
-
- for(rt = host->templates; rt ; rt = rt->next) {
- if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context)
- && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) {
- RRDCALC *rc = rrdcalc_create(host, rt, st->id);
- if(unlikely(!rc))
- info("Health tried to create alarm from template '%s' on chart '%s' of host '%s', but it failed", rt->name, st->id, host->hostname);
-
-#ifdef NETDATA_INTERNAL_CHECKS
- else if(rc->rrdset != st)
- error("Health alarm '%s.%s' should be linked to chart '%s', but it is not", rc->chart?rc->chart:"NOCHART", rc->name, st->id);
-#endif
- }
- }
-}
-
-inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) {
- if(unlikely(!rt)) return;
-
- expression_free(rt->calculation);
- expression_free(rt->warning);
- expression_free(rt->critical);
-
- freez(rt->family_match);
- simple_pattern_free(rt->family_pattern);
-
- freez(rt->name);
- freez(rt->exec);
- freez(rt->recipient);
- freez(rt->context);
- freez(rt->source);
- freez(rt->units);
- freez(rt->info);
- freez(rt->dimensions);
- freez(rt);
-}
-
-inline void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
- if(unlikely(!rt)) return;
-
- debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname);
-
- if(host->templates == rt) {
- host->templates = rt->next;
- }
- else {
- RRDCALCTEMPLATE *t;
- for (t = host->templates; t && t->next != rt; t = t->next ) ;
- if(t) {
- t->next = rt->next;
- rt->next = NULL;
- }
- else
- error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname);
- }
-
- rrdcalctemplate_free(rt);
-}
-
-
diff --git a/src/rrddim.c b/src/rrddim.c
deleted file mode 100644
index a54c6452f..000000000
--- a/src/rrddim.c
+++ /dev/null
@@ -1,387 +0,0 @@
-#define NETDATA_RRD_INTERNALS 1
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDDIM index
-
-int rrddim_compare(void* a, void* b) {
- if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1;
- else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1;
- else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id);
-}
-
-#define rrddim_index_add(st, rd) (RRDDIM *)avl_insert_lock(&((st)->dimensions_index), (avl *)(rd))
-#define rrddim_index_del(st,rd ) (RRDDIM *)avl_remove_lock(&((st)->dimensions_index), (avl *)(rd))
-
-static inline RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) {
- RRDDIM tmp = {
- .id = id,
- .hash = (hash)?hash:simple_hash(id)
- };
- return (RRDDIM *)avl_search_lock(&(st->dimensions_index), (avl *) &tmp);
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDDIM - find a dimension
-
-inline RRDDIM *rrddim_find(RRDSET *st, const char *id) {
- debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", st->name, id);
-
- return rrddim_index_find(st, id, 0);
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDDIM rename a dimension
-
-inline int rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) {
- if(unlikely(!name || !*name || !strcmp(rd->name, name)))
- return 0;
-
- debug(D_RRD_CALLS, "rrddim_set_name() from %s.%s to %s.%s", st->name, rd->name, st->name, name);
-
- char varname[CONFIG_MAX_NAME + 1];
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
- rd->name = config_set_default(st->config_section, varname, name);
- rd->hash_name = simple_hash(rd->name);
- rrddimvar_rename_all(rd);
- rd->exposed = 0;
- return 1;
-}
-
-inline int rrddim_set_algorithm(RRDSET *st, RRDDIM *rd, RRD_ALGORITHM algorithm) {
- if(unlikely(rd->algorithm == algorithm))
- return 0;
-
- debug(D_RRD_CALLS, "Updating algorithm of dimension '%s/%s' from %s to %s", st->id, rd->name, rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm));
- rd->algorithm = algorithm;
- rd->exposed = 0;
- rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
- return 1;
-}
-
-inline int rrddim_set_multiplier(RRDSET *st, RRDDIM *rd, collected_number multiplier) {
- if(unlikely(rd->multiplier == multiplier))
- return 0;
-
- debug(D_RRD_CALLS, "Updating multiplier of dimension '%s/%s' from " COLLECTED_NUMBER_FORMAT " to " COLLECTED_NUMBER_FORMAT, st->id, rd->name, rd->multiplier, multiplier);
- rd->multiplier = multiplier;
- rd->exposed = 0;
- rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
- return 1;
-}
-
-inline int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, collected_number divisor) {
- if(unlikely(rd->divisor == divisor))
- return 0;
-
- debug(D_RRD_CALLS, "Updating divisor of dimension '%s/%s' from " COLLECTED_NUMBER_FORMAT " to " COLLECTED_NUMBER_FORMAT, st->id, rd->name, rd->divisor, divisor);
- rd->divisor = divisor;
- rd->exposed = 0;
- rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
- return 1;
-}
-
-// ----------------------------------------------------------------------------
-// RRDDIM create a dimension
-
-RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm, RRD_MEMORY_MODE memory_mode) {
- RRDDIM *rd = rrddim_find(st, id);
- if(unlikely(rd)) {
- debug(D_RRD_CALLS, "Cannot create rrd dimension '%s/%s', it already exists.", st->id, name?name:"<NONAME>");
-
- rrddim_set_name(st, rd, name);
- rrddim_set_algorithm(st, rd, algorithm);
- rrddim_set_multiplier(st, rd, multiplier);
- rrddim_set_divisor(st, rd, divisor);
-
- return rd;
- }
-
- RRDHOST *host = st->rrdhost;
- char filename[FILENAME_MAX + 1];
- char fullfilename[FILENAME_MAX + 1];
-
- char varname[CONFIG_MAX_NAME + 1];
- unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number));
-
- debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id);
-
- rrdset_strncpyz_name(filename, id, FILENAME_MAX);
- snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
-
- if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP || memory_mode == RRD_MEMORY_MODE_RAM) {
- rd = (RRDDIM *)mymmap(
- (memory_mode == RRD_MEMORY_MODE_RAM)?NULL:fullfilename
- , size
- , ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE)
- , 1
- );
-
- if(likely(rd)) {
- // we have a file mapped for rd
-
- memset(&rd->avl, 0, sizeof(avl));
- rd->id = NULL;
- rd->name = NULL;
- rd->cache_filename = NULL;
- rd->variables = NULL;
- rd->next = NULL;
- rd->rrdset = NULL;
- rd->exposed = 0;
-
- struct timeval now;
- now_realtime_timeval(&now);
-
- if(memory_mode == RRD_MEMORY_MODE_RAM) {
- memset(rd, 0, size);
- }
- else {
- int reset = 0;
-
- if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) {
- info("Initializing file %s.", fullfilename);
- memset(rd, 0, size);
- reset = 1;
- }
- else if(rd->memsize != size) {
- error("File %s does not have the desired size, expected %lu but found %lu. Clearing it.", fullfilename, size, rd->memsize);
- memset(rd, 0, size);
- reset = 1;
- }
- else if(rd->update_every != st->update_every) {
- error("File %s does not have the same update frequency, expected %d but found %d. Clearing it.", fullfilename, st->update_every, rd->update_every);
- memset(rd, 0, size);
- reset = 1;
- }
- else if(dt_usec(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * USEC_PER_SEC)) {
- info("File %s is too old (last collected %llu seconds ago, but the database is %ld seconds). Clearing it.", fullfilename, dt_usec(&now, &rd->last_collected_time) / USEC_PER_SEC, rd->entries * rd->update_every);
- memset(rd, 0, size);
- reset = 1;
- }
-
- if(!reset) {
- if(rd->algorithm != algorithm) {
- info("File %s does not have the expected algorithm (expected %u '%s', found %u '%s'). Previous values may be wrong.",
- fullfilename, algorithm, rrd_algorithm_name(algorithm), rd->algorithm, rrd_algorithm_name(rd->algorithm));
- }
-
- if(rd->multiplier != multiplier) {
- info("File %s does not have the expected multiplier (expected " COLLECTED_NUMBER_FORMAT ", found " COLLECTED_NUMBER_FORMAT "). Previous values may be wrong.", fullfilename, multiplier, rd->multiplier);
- }
-
- if(rd->divisor != divisor) {
- info("File %s does not have the expected divisor (expected " COLLECTED_NUMBER_FORMAT ", found " COLLECTED_NUMBER_FORMAT "). Previous values may be wrong.", fullfilename, divisor, rd->divisor);
- }
- }
- }
-
- // make sure we have the right memory mode
- // even if we cleared the memory
- rd->rrd_memory_mode = memory_mode;
- }
- }
-
- if(unlikely(!rd)) {
- // if we didn't manage to get a mmap'd dimension, just create one
- rd = callocz(1, size);
- rd->rrd_memory_mode = (memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_ALLOC;
- }
-
- rd->memsize = size;
-
- strcpy(rd->magic, RRDDIMENSION_MAGIC);
-
- rd->id = strdupz(id);
- rd->hash = simple_hash(rd->id);
-
- rd->cache_filename = strdupz(fullfilename);
-
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
- rd->name = config_get(st->config_section, varname, (name && *name)?name:rd->id);
- rd->hash_name = simple_hash(rd->name);
-
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id);
- rd->algorithm = rrd_algorithm_id(config_get(st->config_section, varname, rrd_algorithm_name(algorithm)));
-
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id);
- rd->multiplier = config_get_number(st->config_section, varname, multiplier);
-
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id);
- rd->divisor = config_get_number(st->config_section, varname, divisor);
- if(!rd->divisor) rd->divisor = 1;
-
- rd->entries = st->entries;
- rd->update_every = st->update_every;
-
- if(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST))
- rd->collections_counter = 1;
- else
- rd->collections_counter = 0;
-
- rd->updated = 0;
- rd->flags = 0x00000000;
-
- rd->calculated_value = 0;
- rd->last_calculated_value = 0;
- rd->collected_value = 0;
- rd->last_collected_value = 0;
- rd->collected_volume = 0;
- rd->stored_volume = 0;
- rd->last_stored_value = 0;
- rd->values[st->current_entry] = SN_EMPTY_SLOT; // pack_storage_number(0, SN_NOT_EXISTS);
- rd->last_collected_time.tv_sec = 0;
- rd->last_collected_time.tv_usec = 0;
- rd->rrdset = st;
-
- // append this dimension
- rrdset_wrlock(st);
- if(!st->dimensions)
- st->dimensions = rd;
- else {
- RRDDIM *td = st->dimensions;
-
- if(td->algorithm != rd->algorithm || abs(td->multiplier) != abs(rd->multiplier) || abs(td->divisor) != abs(rd->divisor)) {
- if(!rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS)) {
- #ifdef NETDATA_INTERNAL_CHECKS
- info("Dimension '%s' added on chart '%s' of host '%s' is not homogeneous to other dimensions already present (algorithm is '%s' vs '%s', multiplier is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ", divisor is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ").",
- rd->name,
- st->name,
- host->hostname,
- rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(td->algorithm),
- rd->multiplier, td->multiplier,
- rd->divisor, td->divisor
- );
- #endif
- rrdset_flag_set(st, RRDSET_FLAG_HETEROGENEOUS);
- }
- }
-
- for(; td->next; td = td->next) ;
- td->next = rd;
- }
-
- if(host->health_enabled) {
- rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, RRDVAR_OPTION_DEFAULT);
- rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, RRDVAR_OPTION_DEFAULT);
- rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT);
- }
-
- rrdset_unlock(st);
-
- if(unlikely(rrddim_index_add(st, rd) != rd))
- error("RRDDIM: INTERNAL ERROR: attempt to index duplicate dimension '%s' on chart '%s'", rd->id, st->id);
-
- return(rd);
-}
-
-// ----------------------------------------------------------------------------
-// RRDDIM remove / free a dimension
-
-void rrddim_free(RRDSET *st, RRDDIM *rd)
-{
- debug(D_RRD_CALLS, "rrddim_free() %s.%s", st->name, rd->name);
-
- if(rd == st->dimensions)
- st->dimensions = rd->next;
- else {
- RRDDIM *i;
- for (i = st->dimensions; i && i->next != rd; i = i->next) ;
-
- if (i && i->next == rd)
- i->next = rd->next;
- else
- error("Request to free dimension '%s.%s' but it is not linked.", st->id, rd->name);
- }
- rd->next = NULL;
-
- while(rd->variables)
- rrddimvar_free(rd->variables);
-
- if(unlikely(rrddim_index_del(st, rd) != rd))
- error("RRDDIM: INTERNAL ERROR: attempt to remove from index dimension '%s' on chart '%s', removed a different dimension.", rd->id, st->id);
-
- // free(rd->annotations);
-
- switch(rd->rrd_memory_mode) {
- case RRD_MEMORY_MODE_SAVE:
- case RRD_MEMORY_MODE_MAP:
- case RRD_MEMORY_MODE_RAM:
- debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name);
- freez((void *)rd->id);
- freez(rd->cache_filename);
- munmap(rd, rd->memsize);
- break;
-
- case RRD_MEMORY_MODE_ALLOC:
- case RRD_MEMORY_MODE_NONE:
- debug(D_RRD_CALLS, "Removing dimension '%s'.", rd->name);
- freez((void *)rd->id);
- freez(rd->cache_filename);
- freez(rd);
- break;
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDDIM - set dimension options
-
-int rrddim_hide(RRDSET *st, const char *id) {
- debug(D_RRD_CALLS, "rrddim_hide() for chart %s, dimension %s", st->name, id);
-
- RRDHOST *host = st->rrdhost;
-
- RRDDIM *rd = rrddim_find(st, id);
- if(unlikely(!rd)) {
- error("Cannot find dimension with id '%s' on stats '%s' (%s) on host '%s'.", id, st->name, st->id, host->hostname);
- return 1;
- }
-
- rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN);
- return 0;
-}
-
-int rrddim_unhide(RRDSET *st, const char *id) {
- debug(D_RRD_CALLS, "rrddim_unhide() for chart %s, dimension %s", st->name, id);
-
- RRDHOST *host = st->rrdhost;
- RRDDIM *rd = rrddim_find(st, id);
- if(unlikely(!rd)) {
- error("Cannot find dimension with id '%s' on stats '%s' (%s) on host '%s'.", id, st->name, st->id, host->hostname);
- return 1;
- }
-
- rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN);
- return 0;
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDDIM - collect values for a dimension
-
-inline collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value) {
- debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value);
-
- now_realtime_timeval(&rd->last_collected_time);
- rd->collected_value = value;
- rd->updated = 1;
-
- rd->collections_counter++;
-
- // fprintf(stderr, "%s.%s %llu " COLLECTED_NUMBER_FORMAT " dt %0.6f" " rate " CALCULATED_NUMBER_FORMAT "\n", st->name, rd->name, st->usec_since_last_update, value, (float)((double)st->usec_since_last_update / (double)1000000), (calculated_number)((value - rd->last_collected_value) * (calculated_number)rd->multiplier / (calculated_number)rd->divisor * 1000000.0 / (calculated_number)st->usec_since_last_update));
-
- return rd->last_collected_value;
-}
-
-collected_number rrddim_set(RRDSET *st, const char *id, collected_number value) {
- RRDHOST *host = st->rrdhost;
- RRDDIM *rd = rrddim_find(st, id);
- if(unlikely(!rd)) {
- error("Cannot find dimension with id '%s' on stats '%s' (%s) on host '%s'.", id, st->name, st->id, host->hostname);
- return 0;
- }
-
- return rrddim_set_by_pointer(st, rd, value);
-}
diff --git a/src/rrddimvar.c b/src/rrddimvar.c
deleted file mode 100644
index 28a3e7fa6..000000000
--- a/src/rrddimvar.c
+++ /dev/null
@@ -1,212 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDDIMVAR management
-// DIMENSION VARIABLES
-
-#define RRDDIMVAR_ID_MAX 1024
-
-static inline void rrddimvar_free_variables(RRDDIMVAR *rs) {
- RRDDIM *rd = rs->rrddim;
- RRDSET *st = rd->rrdset;
- RRDHOST *host = st->rrdhost;
-
- // CHART VARIABLES FOR THIS DIMENSION
-
- rrdvar_free(host, &st->rrdvar_root_index, rs->var_local_id);
- rs->var_local_id = NULL;
-
- rrdvar_free(host, &st->rrdvar_root_index, rs->var_local_name);
- rs->var_local_name = NULL;
-
- // FAMILY VARIABLES FOR THIS DIMENSION
-
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rs->var_family_id);
- rs->var_family_id = NULL;
-
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rs->var_family_name);
- rs->var_family_name = NULL;
-
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rs->var_family_contextid);
- rs->var_family_contextid = NULL;
-
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rs->var_family_contextname);
- rs->var_family_contextname = NULL;
-
- // HOST VARIABLES FOR THIS DIMENSION
-
- rrdvar_free(host, &host->rrdvar_root_index, rs->var_host_chartidid);
- rs->var_host_chartidid = NULL;
-
- rrdvar_free(host, &host->rrdvar_root_index, rs->var_host_chartidname);
- rs->var_host_chartidname = NULL;
-
- rrdvar_free(host, &host->rrdvar_root_index, rs->var_host_chartnameid);
- rs->var_host_chartnameid = NULL;
-
- rrdvar_free(host, &host->rrdvar_root_index, rs->var_host_chartnamename);
- rs->var_host_chartnamename = NULL;
-
- // KEYS
-
- freez(rs->key_id);
- rs->key_id = NULL;
-
- freez(rs->key_name);
- rs->key_name = NULL;
-
- freez(rs->key_fullidid);
- rs->key_fullidid = NULL;
-
- freez(rs->key_fullidname);
- rs->key_fullidname = NULL;
-
- freez(rs->key_contextid);
- rs->key_contextid = NULL;
-
- freez(rs->key_contextname);
- rs->key_contextname = NULL;
-
- freez(rs->key_fullnameid);
- rs->key_fullnameid = NULL;
-
- freez(rs->key_fullnamename);
- rs->key_fullnamename = NULL;
-}
-
-static inline void rrddimvar_create_variables(RRDDIMVAR *rs) {
- rrddimvar_free_variables(rs);
-
- RRDDIM *rd = rs->rrddim;
- RRDSET *st = rd->rrdset;
- RRDHOST *host = st->rrdhost;
-
- char buffer[RRDDIMVAR_ID_MAX + 1];
-
- // KEYS
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->id, rs->suffix);
- rs->key_id = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix);
- rs->key_name = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_id);
- rs->key_fullidid = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_name);
- rs->key_fullidname = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_id);
- rs->key_contextid = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_name);
- rs->key_contextname = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_id);
- rs->key_fullnameid = strdupz(buffer);
-
- snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_name);
- rs->key_fullnamename = strdupz(buffer);
-
- // CHART VARIABLES FOR THIS DIMENSION
- // -----------------------------------
- //
- // dimensions are available as:
- // - $id
- // - $name
-
- rs->var_local_id = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_id, rs->type, rs->value);
- rs->var_local_name = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_name, rs->type, rs->value);
-
- // FAMILY VARIABLES FOR THIS DIMENSION
- // -----------------------------------
- //
- // dimensions are available as:
- // - $id (only the first, when multiple overlap)
- // - $name (only the first, when multiple overlap)
- // - $chart-context.id
- // - $chart-context.name
-
- rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_id, rs->type, rs->value);
- rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_name, rs->type, rs->value);
- rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextid, rs->type, rs->value);
- rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextname, rs->type, rs->value);
-
- // HOST VARIABLES FOR THIS DIMENSION
- // -----------------------------------
- //
- // dimensions are available as:
- // - $chart-id.id
- // - $chart-id.name
- // - $chart-name.id
- // - $chart-name.name
-
- rs->var_host_chartidid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidid, rs->type, rs->value);
- rs->var_host_chartidname = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidname, rs->type, rs->value);
- rs->var_host_chartnameid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnameid, rs->type, rs->value);
- rs->var_host_chartnamename = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnamename, rs->type, rs->value);
-}
-
-RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options) {
- RRDSET *st = rd->rrdset;
-
- debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:"");
-
- if(!prefix) prefix = "";
- if(!suffix) suffix = "";
-
- RRDDIMVAR *rs = (RRDDIMVAR *)callocz(1, sizeof(RRDDIMVAR));
-
- rs->prefix = strdupz(prefix);
- rs->suffix = strdupz(suffix);
-
- rs->type = type;
- rs->value = value;
- rs->options = options;
- rs->rrddim = rd;
-
- rs->next = rd->variables;
- rd->variables = rs;
-
- rrddimvar_create_variables(rs);
-
- return rs;
-}
-
-void rrddimvar_rename_all(RRDDIM *rd) {
- RRDSET *st = rd->rrdset;
- debug(D_VARIABLES, "RRDDIMSET rename for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name);
-
- RRDDIMVAR *rs, *next = rd->variables;
- while((rs = next)) {
- next = rs->next;
- rrddimvar_create_variables(rs);
- }
-}
-
-void rrddimvar_free(RRDDIMVAR *rs) {
- RRDDIM *rd = rs->rrddim;
- RRDSET *st = rd->rrdset;
- debug(D_VARIABLES, "RRDDIMSET free for chart id '%s' name '%s', dimension id '%s', name '%s', prefix='%s', suffix='%s'", st->id, st->name, rd->id, rd->name, rs->prefix, rs->suffix);
-
- rrddimvar_free_variables(rs);
-
- if(rd->variables == rs) {
- debug(D_VARIABLES, "RRDDIMSET removing first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name);
- rd->variables = rs->next;
- }
- else {
- debug(D_VARIABLES, "RRDDIMSET removing non-first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name);
- RRDDIMVAR *t;
- for (t = rd->variables; t && t->next != rs; t = t->next) ;
- if(!t) error("RRDDIMVAR '%s' not found in dimension '%s/%s' variables linked list", rs->key_name, st->id, rd->id);
- else t->next = rs->next;
- }
-
- freez(rs->prefix);
- freez(rs->suffix);
- freez(rs);
-}
-
diff --git a/src/rrdfamily.c b/src/rrdfamily.c
deleted file mode 100644
index 905ae480b..000000000
--- a/src/rrdfamily.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#define NETDATA_RRD_INTERNALS 1
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDFAMILY index
-
-int rrdfamily_compare(void *a, void *b) {
- if(((RRDFAMILY *)a)->hash_family < ((RRDFAMILY *)b)->hash_family) return -1;
- else if(((RRDFAMILY *)a)->hash_family > ((RRDFAMILY *)b)->hash_family) return 1;
- else return strcmp(((RRDFAMILY *)a)->family, ((RRDFAMILY *)b)->family);
-}
-
-#define rrdfamily_index_add(host, rc) (RRDFAMILY *)avl_insert_lock(&((host)->rrdfamily_root_index), (avl *)(rc))
-#define rrdfamily_index_del(host, rc) (RRDFAMILY *)avl_remove_lock(&((host)->rrdfamily_root_index), (avl *)(rc))
-
-static RRDFAMILY *rrdfamily_index_find(RRDHOST *host, const char *id, uint32_t hash) {
- RRDFAMILY tmp;
- tmp.family = id;
- tmp.hash_family = (hash)?hash:simple_hash(tmp.family);
-
- return (RRDFAMILY *)avl_search_lock(&(host->rrdfamily_root_index), (avl *) &tmp);
-}
-
-RRDFAMILY *rrdfamily_create(RRDHOST *host, const char *id) {
- RRDFAMILY *rc = rrdfamily_index_find(host, id, 0);
- if(!rc) {
- rc = callocz(1, sizeof(RRDFAMILY));
-
- rc->family = strdupz(id);
- rc->hash_family = simple_hash(rc->family);
-
- // initialize the variables index
- avl_init_lock(&rc->rrdvar_root_index, rrdvar_compare);
-
- RRDFAMILY *ret = rrdfamily_index_add(host, rc);
- if(ret != rc)
- error("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE");
- }
-
- rc->use_count++;
- return rc;
-}
-
-void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc) {
- rc->use_count--;
- if(!rc->use_count) {
- RRDFAMILY *ret = rrdfamily_index_del(host, rc);
- if(ret != rc)
- error("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE");
- else {
- debug(D_RRD_CALLS, "RRDFAMILY: Cleaning up remaining family variables for host '%s', family '%s'", host->hostname, rc->family);
- rrdvar_free_remaining_variables(host, &rc->rrdvar_root_index);
-
- freez((void *) rc->family);
- freez(rc);
- }
- }
-}
-
diff --git a/src/rrdhost.c b/src/rrdhost.c
deleted file mode 100644
index e62e61ae8..000000000
--- a/src/rrdhost.c
+++ /dev/null
@@ -1,735 +0,0 @@
-#define NETDATA_RRD_INTERNALS 1
-#include "common.h"
-
-RRDHOST *localhost = NULL;
-size_t rrd_hosts_available = 0;
-netdata_rwlock_t rrd_rwlock = NETDATA_RWLOCK_INITIALIZER;
-
-time_t rrdset_free_obsolete_time = 3600;
-time_t rrdhost_free_orphan_time = 3600;
-
-// ----------------------------------------------------------------------------
-// RRDHOST index
-
-int rrdhost_compare(void* a, void* b) {
- if(((RRDHOST *)a)->hash_machine_guid < ((RRDHOST *)b)->hash_machine_guid) return -1;
- else if(((RRDHOST *)a)->hash_machine_guid > ((RRDHOST *)b)->hash_machine_guid) return 1;
- else return strcmp(((RRDHOST *)a)->machine_guid, ((RRDHOST *)b)->machine_guid);
-}
-
-avl_tree_lock rrdhost_root_index = {
- .avl_tree = { NULL, rrdhost_compare },
- .rwlock = AVL_LOCK_INITIALIZER
-};
-
-RRDHOST *rrdhost_find_by_guid(const char *guid, uint32_t hash) {
- debug(D_RRDHOST, "Searching in index for host with guid '%s'", guid);
-
- RRDHOST tmp;
- strncpyz(tmp.machine_guid, guid, GUID_LEN);
- tmp.hash_machine_guid = (hash)?hash:simple_hash(tmp.machine_guid);
-
- return (RRDHOST *)avl_search_lock(&(rrdhost_root_index), (avl *) &tmp);
-}
-
-RRDHOST *rrdhost_find_by_hostname(const char *hostname, uint32_t hash) {
- if(unlikely(!strcmp(hostname, "localhost")))
- return localhost;
-
- if(unlikely(!hash)) hash = simple_hash(hostname);
-
- rrd_rdlock();
- RRDHOST *host;
- rrdhost_foreach_read(host) {
- if(unlikely((hash == host->hash_hostname && !strcmp(hostname, host->hostname)))) {
- rrd_unlock();
- return host;
- }
- }
- rrd_unlock();
-
- return NULL;
-}
-
-#define rrdhost_index_add(rrdhost) (RRDHOST *)avl_insert_lock(&(rrdhost_root_index), (avl *)(rrdhost))
-#define rrdhost_index_del(rrdhost) (RRDHOST *)avl_remove_lock(&(rrdhost_root_index), (avl *)(rrdhost))
-
-
-// ----------------------------------------------------------------------------
-// RRDHOST - internal helpers
-
-static inline void rrdhost_init_tags(RRDHOST *host, const char *tags) {
- if(host->tags && tags && !strcmp(host->tags, tags))
- return;
-
- void *old = (void *)host->tags;
- host->tags = (tags && *tags)?strdupz(tags):NULL;
- freez(old);
-}
-
-static inline void rrdhost_init_hostname(RRDHOST *host, const char *hostname) {
- if(host->hostname && hostname && !strcmp(host->hostname, hostname))
- return;
-
- void *old = host->hostname;
- host->hostname = strdupz(hostname?hostname:"localhost");
- host->hash_hostname = simple_hash(host->hostname);
- freez(old);
-}
-
-static inline void rrdhost_init_os(RRDHOST *host, const char *os) {
- if(host->os && os && !strcmp(host->os, os))
- return;
-
- void *old = (void *)host->os;
- host->os = strdupz(os?os:"unknown");
- freez(old);
-}
-
-static inline void rrdhost_init_timezone(RRDHOST *host, const char *timezone) {
- if(host->timezone && timezone && !strcmp(host->timezone, timezone))
- return;
-
- void *old = (void *)host->timezone;
- host->timezone = strdupz((timezone && *timezone)?timezone:"unknown");
- freez(old);
-}
-
-static inline void rrdhost_init_machine_guid(RRDHOST *host, const char *machine_guid) {
- strncpy(host->machine_guid, machine_guid, GUID_LEN);
- host->machine_guid[GUID_LEN] = '\0';
- host->hash_machine_guid = simple_hash(host->machine_guid);
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDHOST - add a host
-
-RRDHOST *rrdhost_create(const char *hostname,
- const char *registry_hostname,
- const char *guid,
- const char *os,
- const char *timezone,
- const char *tags,
- const char *program_name,
- const char *program_version,
- int update_every,
- long entries,
- RRD_MEMORY_MODE memory_mode,
- int health_enabled,
- int rrdpush_enabled,
- char *rrdpush_destination,
- 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 > 0)?update_every:1;
- host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries);
- host->rrd_memory_mode = memory_mode;
- host->health_enabled = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled;
- host->rrdpush_send_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key);
- host->rrdpush_send_destination = (host->rrdpush_send_enabled)?strdupz(rrdpush_destination):NULL;
- host->rrdpush_send_api_key = (host->rrdpush_send_enabled)?strdupz(rrdpush_api_key):NULL;
-
- host->rrdpush_sender_pipe[0] = -1;
- host->rrdpush_sender_pipe[1] = -1;
- host->rrdpush_sender_socket = -1;
-
- netdata_mutex_init(&host->rrdpush_sender_buffer_mutex);
- netdata_rwlock_init(&host->rrdhost_rwlock);
-
- rrdhost_init_hostname(host, hostname);
- rrdhost_init_machine_guid(host, guid);
- rrdhost_init_os(host, os);
- rrdhost_init_timezone(host, timezone);
- rrdhost_init_tags(host, tags);
-
- host->program_name = strdupz((program_name && *program_name)?program_name:"unknown");
- host->program_version = strdupz((program_version && *program_version)?program_version:"unknown");
- host->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
-
- avl_init_lock(&(host->rrdset_root_index), rrdset_compare);
- avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name);
- avl_init_lock(&(host->rrdfamily_root_index), rrdfamily_compare);
- avl_init_lock(&(host->rrdvar_root_index), rrdvar_compare);
-
- if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete obsolete charts files", 1))
- rrdhost_flag_set(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS);
-
- if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete orphan hosts files", 1) && !is_localhost)
- rrdhost_flag_set(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST);
-
-
- // ------------------------------------------------------------------------
- // initialize health variables
-
- host->health_log.next_log_id = 1;
- host->health_log.next_alarm_id = 1;
- host->health_log.max = 1000;
- host->health_log.next_log_id =
- host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
-
- long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max);
- if(n < 10) {
- error("Host '%s': health configuration has invalid max log entries %ld. Using default %u", host->hostname, n, host->health_log.max);
- config_set_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", (long)host->health_log.max);
- }
- else
- host->health_log.max = (unsigned int)n;
-
- netdata_rwlock_init(&host->health_log.alarm_log_rwlock);
-
- char filename[FILENAME_MAX + 1];
-
- if(is_localhost) {
-
- host->cache_dir = strdupz(netdata_configured_cache_dir);
- host->varlib_dir = strdupz(netdata_configured_varlib_dir);
-
- }
- else {
- // this is not localhost - append our GUID to localhost path
-
- snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid);
- host->cache_dir = strdupz(filename);
-
- if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
- int r = mkdir(host->cache_dir, 0775);
- if(r != 0 && errno != EEXIST)
- error("Host '%s': cannot create directory '%s'", host->hostname, host->cache_dir);
- }
-
- snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid);
- host->varlib_dir = strdupz(filename);
-
- if(host->health_enabled) {
- int r = mkdir(host->varlib_dir, 0775);
- if(r != 0 && errno != EEXIST)
- error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir);
- }
-
- }
-
- if(host->health_enabled) {
- snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir);
- int r = mkdir(filename, 0775);
- if(r != 0 && errno != EEXIST)
- error("Host '%s': cannot create directory '%s'", host->hostname, filename);
- }
-
- snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
- host->health_log_filename = strdupz(filename);
-
- snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir);
- host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
- host->health_default_recipient = strdup("root");
-
-
- // ------------------------------------------------------------------------
- // load health configuration
-
- if(host->health_enabled) {
- health_alarm_log_load(host);
- health_alarm_log_open(host);
-
- rrdhost_wrlock(host);
- health_readdir(host, health_config_dir());
- rrdhost_unlock(host);
- }
-
-
- // ------------------------------------------------------------------------
- // link it and add it to the index
-
- if(is_localhost) {
- host->next = localhost;
- localhost = host;
- }
- else {
- if(localhost) {
- host->next = localhost->next;
- localhost->next = host;
- }
- else localhost = host;
- }
-
- RRDHOST *t = rrdhost_index_add(host);
-
- if(t != host) {
- error("Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.", host->hostname, host->machine_guid, t->hostname, t->machine_guid);
- rrdhost_free(host);
- host = NULL;
- }
- else {
- info("Host '%s' (at registry as '%s') with guid '%s' initialized"
- ", os '%s'"
- ", timezone '%s'"
- ", tags '%s'"
- ", program_name '%s'"
- ", program_version '%s'"
- ", update every %d"
- ", memory mode %s"
- ", history entries %ld"
- ", streaming %s"
- " (to '%s' with api key '%s')"
- ", health %s"
- ", cache_dir '%s'"
- ", varlib_dir '%s'"
- ", health_log '%s'"
- ", alarms default handler '%s'"
- ", alarms default recipient '%s'"
- , host->hostname
- , host->registry_hostname
- , host->machine_guid
- , host->os
- , host->timezone
- , (host->tags)?host->tags:""
- , host->program_name
- , host->program_version
- , host->rrd_update_every
- , rrd_memory_mode_name(host->rrd_memory_mode)
- , host->rrd_history_entries
- , host->rrdpush_send_enabled?"enabled":"disabled"
- , host->rrdpush_send_destination?host->rrdpush_send_destination:""
- , host->rrdpush_send_api_key?host->rrdpush_send_api_key:""
- , host->health_enabled?"enabled":"disabled"
- , host->cache_dir
- , host->varlib_dir
- , host->health_log_filename
- , host->health_default_exec
- , host->health_default_recipient
- );
- }
-
- rrd_hosts_available++;
-
- return host;
-}
-
-RRDHOST *rrdhost_find_or_create(
- const char *hostname
- , const char *registry_hostname
- , const char *guid
- , const char *os
- , const char *timezone
- , const char *tags
- , const char *program_name
- , const char *program_version
- , int update_every
- , long history
- , RRD_MEMORY_MODE mode
- , int health_enabled
- , int rrdpush_enabled
- , char *rrdpush_destination
- , char *rrdpush_api_key
-) {
- 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(
- hostname
- , registry_hostname
- , guid
- , os
- , timezone
- , tags
- , program_name
- , program_version
- , update_every
- , history
- , mode
- , health_enabled
- , rrdpush_enabled
- , rrdpush_destination
- , rrdpush_api_key
- , 0
- );
- }
- else {
- host->health_enabled = health_enabled;
-
- if(strcmp(host->hostname, hostname) != 0) {
- info("Host '%s' has been renamed to '%s'. If this is not intentional it may mean multiple hosts are using the same machine_guid.", host->hostname, hostname);
- char *t = host->hostname;
- host->hostname = strdupz(hostname);
- host->hash_hostname = simple_hash(host->hostname);
- freez(t);
- }
-
- if(strcmp(host->program_name, program_name) != 0) {
- info("Host '%s' switched program name from '%s' to '%s'", host->hostname, host->program_name, program_name);
- char *t = host->program_name;
- host->program_name = strdupz(program_name);
- freez(t);
- }
-
- if(strcmp(host->program_version, program_version) != 0) {
- info("Host '%s' switched program version from '%s' to '%s'", host->hostname, host->program_version, program_version);
- char *t = host->program_version;
- host->program_version = strdupz(program_version);
- freez(t);
- }
-
- if(host->rrd_update_every != update_every)
- error("Host '%s' has an update frequency of %d seconds, but the wanted one is %d seconds. Restart netdata here to apply the new settings.", host->hostname, host->rrd_update_every, update_every);
-
- if(host->rrd_history_entries < history)
- error("Host '%s' has history of %ld entries, but the wanted one is %ld entries. Restart netdata here to apply the new settings.", host->hostname, host->rrd_history_entries, history);
-
- if(host->rrd_memory_mode != mode)
- error("Host '%s' has memory mode '%s', but the wanted one is '%s'. Restart netdata here to apply the new settings.", host->hostname, rrd_memory_mode_name(host->rrd_memory_mode), rrd_memory_mode_name(mode));
-
- // update host tags
- rrdhost_init_tags(host, tags);
- }
-
- rrdhost_cleanup_orphan_hosts_nolock(host);
-
- rrd_unlock();
-
- return host;
-}
-
-inline int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected, time_t now) {
- if(host != protected
- && host != localhost
- && rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)
- && !host->connected_senders
- && host->senders_disconnected_time
- && host->senders_disconnected_time + rrdhost_free_orphan_time < now)
- return 1;
-
- return 0;
-}
-
-void rrdhost_cleanup_orphan_hosts_nolock(RRDHOST *protected) {
- time_t now = now_realtime_sec();
-
- RRDHOST *host;
-
-restart_after_removal:
- rrdhost_foreach_write(host) {
- if(rrdhost_should_be_removed(host, protected, now)) {
- info("Host '%s' with machine guid '%s' is obsolete - cleaning up.", host->hostname, host->machine_guid);
-
- if(rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST))
- rrdhost_delete_charts(host);
- else
- rrdhost_save_charts(host);
-
- rrdhost_free(host);
- goto restart_after_removal;
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST global / startup initialization
-
-void rrd_init(char *hostname) {
- rrdset_free_obsolete_time = config_get_number(CONFIG_SECTION_GLOBAL, "cleanup obsolete charts after seconds", rrdset_free_obsolete_time);
- gap_when_lost_iterations_above = (int)config_get_number(CONFIG_SECTION_GLOBAL, "gap when lost iterations above", gap_when_lost_iterations_above);
- if(gap_when_lost_iterations_above < 1)
- gap_when_lost_iterations_above = 1;
-
- health_init();
- registry_init();
- rrdpush_init();
-
- debug(D_RRDHOST, "Initializing localhost with hostname '%s'", hostname);
- rrd_wrlock();
- localhost = rrdhost_create(
- hostname
- , registry_get_this_machine_hostname()
- , registry_get_this_machine_guid()
- , os_type
- , netdata_configured_timezone
- , config_get(CONFIG_SECTION_BACKEND, "host tags", "")
- , program_name
- , program_version
- , default_rrd_update_every
- , default_rrd_history_entries
- , default_rrd_memory_mode
- , default_health_enabled
- , default_rrdpush_enabled
- , default_rrdpush_destination
- , default_rrdpush_api_key
- , 1
- );
- rrd_unlock();
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST - lock validations
-// there are only used when NETDATA_INTERNAL_CHECKS is set
-
-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 = 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(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 = 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(const char *file, const char *function, const unsigned long line) {
- debug(D_RRDHOST, "Checking read lock on all RRDs");
-
- 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(const char *file, const char *function, const unsigned long line) {
- debug(D_RRDHOST, "Checking write lock on all RRDs");
-
- 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);
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST - free
-
-void rrdhost_free(RRDHOST *host) {
- if(!host) return;
-
- info("Freeing all memory for host '%s'...", host->hostname);
-
- rrd_check_wrlock(); // make sure the RRDs are write locked
-
- // stop a possibly running thread
- rrdpush_sender_thread_stop(host);
-
- rrdhost_wrlock(host); // lock this RRDHOST
-
- // ------------------------------------------------------------------------
- // release its children resources
-
- while(host->rrdset_root)
- rrdset_free(host->rrdset_root);
-
- while(host->alarms)
- rrdcalc_unlink_and_free(host, host->alarms);
-
- while(host->templates)
- rrdcalctemplate_unlink_and_free(host, host->templates);
-
- debug(D_RRD_CALLS, "RRDHOST: Cleaning up remaining host variables for host '%s'", host->hostname);
- rrdvar_free_remaining_variables(host, &host->rrdvar_root_index);
-
- health_alarm_log_free(host);
-
- // ------------------------------------------------------------------------
- // remove it from the indexes
-
- if(rrdhost_index_del(host) != host)
- error("RRDHOST '%s' removed from index, deleted the wrong entry.", host->hostname);
-
-
- // ------------------------------------------------------------------------
- // unlink it from the host
-
- if(host == localhost) {
- localhost = host->next;
- }
- else {
- // find the previous one
- RRDHOST *h;
- for(h = localhost; h && h->next != host ; h = h->next) ;
-
- // bypass it
- if(h) h->next = host->next;
- else error("Request to free RRDHOST '%s': cannot find it", host->hostname);
- }
-
- // ------------------------------------------------------------------------
- // free it
-
- freez((void *)host->tags);
- freez((void *)host->os);
- freez((void *)host->timezone);
- freez(host->program_version);
- freez(host->program_name);
- freez(host->cache_dir);
- freez(host->varlib_dir);
- freez(host->rrdpush_send_api_key);
- freez(host->rrdpush_send_destination);
- freez(host->health_default_exec);
- freez(host->health_default_recipient);
- freez(host->health_log_filename);
- freez(host->hostname);
- freez(host->registry_hostname);
- rrdhost_unlock(host);
- netdata_rwlock_destroy(&host->health_log.alarm_log_rwlock);
- netdata_rwlock_destroy(&host->rrdhost_rwlock);
- freez(host);
-
- rrd_hosts_available--;
-}
-
-void rrdhost_free_all(void) {
- rrd_wrlock();
- while(localhost) rrdhost_free(localhost);
- rrd_unlock();
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST - save host files
-
-void rrdhost_save_charts(RRDHOST *host) {
- if(!host) return;
-
- info("Saving/Closing database of host '%s'...", host->hostname);
-
- RRDSET *st;
-
- // we get a write lock
- // to ensure only one thread is saving the database
- rrdhost_wrlock(host);
-
- rrdset_foreach_write(st, host) {
- rrdset_rdlock(st);
- rrdset_save(st);
- rrdset_unlock(st);
- }
-
- rrdhost_unlock(host);
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST - delete host files
-
-void rrdhost_delete_charts(RRDHOST *host) {
- if(!host) return;
-
- info("Deleting database of host '%s'...", host->hostname);
-
- RRDSET *st;
-
- // we get a write lock
- // to ensure only one thread is saving the database
- rrdhost_wrlock(host);
-
- rrdset_foreach_write(st, host) {
- rrdset_rdlock(st);
- rrdset_delete(st);
- rrdset_unlock(st);
- }
-
- recursively_delete_dir(host->cache_dir, "left over host");
-
- rrdhost_unlock(host);
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST - cleanup host files
-
-void rrdhost_cleanup_charts(RRDHOST *host) {
- if(!host) return;
-
- info("Cleaning up database of host '%s'...", host->hostname);
-
- RRDSET *st;
- uint32_t rrdhost_delete_obsolete_charts = rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS);
-
- // we get a write lock
- // to ensure only one thread is saving the database
- rrdhost_wrlock(host);
-
- rrdset_foreach_write(st, host) {
- rrdset_rdlock(st);
-
- if(rrdhost_delete_obsolete_charts && rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE))
- rrdset_delete(st);
- else
- rrdset_save(st);
-
- rrdset_unlock(st);
- }
-
- rrdhost_unlock(host);
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDHOST - save all hosts to disk
-
-void rrdhost_save_all(void) {
- info("Saving database [%zu hosts(s)]...", rrd_hosts_available);
-
- rrd_rdlock();
-
- RRDHOST *host;
- rrdhost_foreach_read(host)
- rrdhost_save_charts(host);
-
- rrd_unlock();
-}
-
-// ----------------------------------------------------------------------------
-// RRDHOST - save or delete all hosts from disk
-
-void rrdhost_cleanup_all(void) {
- info("Cleaning up database [%zu hosts(s)]...", rrd_hosts_available);
-
- rrd_rdlock();
-
- RRDHOST *host;
- rrdhost_foreach_read(host) {
- if(host != localhost && rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS) && !host->connected_senders)
- rrdhost_delete_charts(host);
- else
- rrdhost_cleanup_charts(host);
- }
-
- rrd_unlock();
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDHOST - save or delete all the host charts from disk
-
-void rrdhost_cleanup_obsolete_charts(RRDHOST *host) {
- time_t now = now_realtime_sec();
-
- RRDSET *st;
-
- uint32_t rrdhost_delete_obsolete_charts = rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS);
-
-restart_after_removal:
- rrdset_foreach_write(st, host) {
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)
- && st->last_accessed_time + rrdset_free_obsolete_time < now
- && st->last_updated.tv_sec + rrdset_free_obsolete_time < now
- && st->last_collected_time.tv_sec + rrdset_free_obsolete_time < now
- )) {
-
- rrdset_rdlock(st);
-
- if(rrdhost_delete_obsolete_charts)
- rrdset_delete(st);
- else
- rrdset_save(st);
-
- rrdset_unlock(st);
-
- rrdset_free(st);
- goto restart_after_removal;
- }
- }
-}
diff --git a/src/rrdpush.c b/src/rrdpush.c
deleted file mode 100644
index 8f71c6d4c..000000000
--- a/src/rrdpush.c
+++ /dev/null
@@ -1,1160 +0,0 @@
-#include "common.h"
-
-/*
- * rrdpush
- *
- * 3 threads are involved for all stream operations
- *
- * 1. a random data collection thread, calling rrdset_done_push()
- * this is called for each chart.
- *
- * the output of this work is kept in a BUFFER in RRDHOST
- * the sender thread is signalled via a pipe (also in RRDHOST)
- *
- * 2. a sender thread running at the sending netdata
- * this is spawned automatically on the first chart to be pushed
- *
- * It tries to push the metrics to the remote netdata, as fast
- * as possible (i.e. immediately after they are collected).
- *
- * 3. a receiver thread, running at the receiving netdata
- * this is spawned automatically when the sender connects to
- * the receiver.
- *
- */
-
-#define START_STREAMING_PROMPT "Hit me baby, push them over..."
-
-typedef enum {
- RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW,
- RRDPUSH_MULTIPLE_CONNECTIONS_DENY_NEW
-} RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY;
-
-int default_rrdpush_enabled = 0;
-char *default_rrdpush_destination = NULL;
-char *default_rrdpush_api_key = NULL;
-
-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 = 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.");
- default_rrdpush_enabled = 0;
- }
-
- return default_rrdpush_enabled;
-}
-
-#define CONNECTED_TO_SIZE 100
-
-// data collection happens from multiple threads
-// each of these threads calls rrdset_done()
-// which in turn calls rrdset_done_push()
-// which uses this pipe to notify the streaming thread
-// that there are more data ready to be sent
-#define PIPE_READ 0
-#define PIPE_WRITE 1
-
-// to have the remote netdata re-sync the charts
-// to its current clock, we send for this many
-// iterations a BEGIN line without microseconds
-// this is for the first iterations of each chart
-unsigned int remote_clock_resync_iterations = 60;
-
-#define rrdpush_buffer_lock(host) netdata_mutex_lock(&((host)->rrdpush_sender_buffer_mutex))
-#define rrdpush_buffer_unlock(host) netdata_mutex_unlock(&((host)->rrdpush_sender_buffer_mutex))
-
-// checks if the current chart definition has been sent
-static inline int need_to_send_chart_definition(RRDSET *st) {
- rrdset_check_rdlock(st);
-
- if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_EXPOSED_UPSTREAM))))
- return 1;
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st)
- if(unlikely(!rd->exposed))
- return 1;
-
- return 0;
-}
-
-// sends the current chart definition
-static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
-
- rrdset_flag_set(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
-
- // send the chart
- buffer_sprintf(
- host->rrdpush_sender_buffer
- , "CHART \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %ld %d \"%s %s %s %s\" \"%s\" \"%s\"\n"
- , st->id
- , st->name
- , st->title
- , st->units
- , st->family
- , st->context
- , rrdset_type_name(st->chart_type)
- , st->priority
- , st->update_every
- , rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)?"obsolete":""
- , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?"detail":""
- , rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST)?"store_first":""
- , rrdset_flag_check(st, RRDSET_FLAG_HIDDEN)?"hidden":""
- , (st->plugin_name)?st->plugin_name:""
- , (st->module_name)?st->module_name:""
- );
-
- // send the dimensions
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- buffer_sprintf(
- host->rrdpush_sender_buffer
- , "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s\"\n"
- , rd->id
- , rd->name
- , rrd_algorithm_name(rd->algorithm)
- , rd->multiplier
- , rd->divisor
- , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?"hidden":""
- , rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)?"noreset":""
- );
- rd->exposed = 1;
- }
-
- // send the chart local custom variables
- RRDSETVAR *rs;
- for(rs = st->variables; rs ;rs = rs->next) {
- if(unlikely(rs->options && RRDVAR_OPTION_ALLOCATED)) {
- calculated_number *value = (calculated_number *) rs->value;
-
- buffer_sprintf(
- host->rrdpush_sender_buffer
- , "VARIABLE CHART %s = " CALCULATED_NUMBER_FORMAT "\n"
- , rs->variable
- , *value
- );
- }
- }
-
- st->upstream_resync_time = st->last_collected_time.tv_sec + (remote_clock_resync_iterations * st->update_every);
-}
-
-// sends the current chart dimensions
-static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
- buffer_sprintf(host->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->upstream_resync_time > st->last_collected_time.tv_sec)?st->usec_since_last_update:0);
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rd->updated && rd->exposed)
- buffer_sprintf(host->rrdpush_sender_buffer
- , "SET \"%s\" = " COLLECTED_NUMBER_FORMAT "\n"
- , rd->id
- , rd->collected_value
- );
- }
-
- buffer_strcat(host->rrdpush_sender_buffer, "END\n");
-}
-
-static void rrdpush_sender_thread_spawn(RRDHOST *host);
-
-void rrdset_push_chart_definition(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
-
- rrdset_rdlock(st);
- rrdpush_buffer_lock(host);
- rrdpush_send_chart_definition_nolock(st);
- rrdpush_buffer_unlock(host);
- rrdset_unlock(st);
-}
-
-void rrdset_done_push(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
-
- if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_ENABLED)))
- return;
-
- rrdpush_buffer_lock(host);
-
- if(unlikely(host->rrdpush_send_enabled && !host->rrdpush_sender_spawn))
- rrdpush_sender_thread_spawn(host);
-
- if(unlikely(!host->rrdpush_sender_buffer || !host->rrdpush_sender_connected)) {
- if(unlikely(!host->rrdpush_sender_error_shown))
- error("STREAM %s [send]: not ready - discarding collected metrics.", host->hostname);
-
- host->rrdpush_sender_error_shown = 1;
-
- rrdpush_buffer_unlock(host);
- return;
- }
- else if(unlikely(host->rrdpush_sender_error_shown)) {
- info("STREAM %s [send]: sending metrics...", host->hostname);
- host->rrdpush_sender_error_shown = 0;
- }
-
- if(need_to_send_chart_definition(st))
- rrdpush_send_chart_definition_nolock(st);
-
- rrdpush_send_chart_metrics_nolock(st);
-
- // signal the sender there are more data
- if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1 && write(host->rrdpush_sender_pipe[PIPE_WRITE], " ", 1) == -1)
- error("STREAM %s [send]: cannot write to internal pipe", host->hostname);
-
- rrdpush_buffer_unlock(host);
-}
-
-// ----------------------------------------------------------------------------
-// rrdpush sender thread
-
-static inline void rrdpush_sender_add_host_variable_to_buffer_nolock(RRDHOST *host, RRDVAR *rv) {
- calculated_number *value = (calculated_number *)rv->value;
-
- buffer_sprintf(
- host->rrdpush_sender_buffer
- , "VARIABLE HOST %s = " CALCULATED_NUMBER_FORMAT "\n"
- , rv->name
- , *value
- );
-
- debug(D_STREAM, "RRDVAR pushed HOST VARIABLE %s = " CALCULATED_NUMBER_FORMAT, rv->name, *value);
-}
-
-void rrdpush_sender_send_this_host_variable_now(RRDHOST *host, RRDVAR *rv) {
- if(host->rrdpush_send_enabled && host->rrdpush_sender_spawn && host->rrdpush_sender_connected) {
- rrdpush_buffer_lock(host);
- rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv);
- rrdpush_buffer_unlock(host);
- }
-}
-
-static int rrdpush_sender_thread_custom_host_variables_callback(void *rrdvar_ptr, void *host_ptr) {
- RRDVAR *rv = (RRDVAR *)rrdvar_ptr;
- RRDHOST *host = (RRDHOST *)host_ptr;
-
- if(unlikely(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)) {
- rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv);
-
- // return 1, so that the traversal will return the number of variables sent
- return 1;
- }
-
- // returning a negative number will break the traversal
- return 0;
-}
-
-static void rrdpush_sender_thread_send_custom_host_variables(RRDHOST *host) {
- int ret = rrdvar_callback_for_all_host_variables(host, rrdpush_sender_thread_custom_host_variables_callback, host);
- debug(D_STREAM, "RRDVAR sent %d VARIABLES", ret);
-}
-
-// resets all the chart, so that their definitions
-// will be resent to the central netdata
-static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) {
- rrdhost_rdlock(host);
-
- RRDSET *st;
- rrdset_foreach_read(st, host) {
- rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
-
- st->upstream_resync_time = 0;
-
- rrdset_rdlock(st);
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st)
- rd->exposed = 0;
-
- rrdset_unlock(st);
- }
-
- rrdhost_unlock(host);
-}
-
-static inline void rrdpush_sender_thread_data_flush(RRDHOST *host) {
- rrdpush_buffer_lock(host);
-
- if(buffer_strlen(host->rrdpush_sender_buffer))
- error("STREAM %s [send]: discarding %zu bytes of metrics already in the buffer.", host->hostname, buffer_strlen(host->rrdpush_sender_buffer));
-
- buffer_flush(host->rrdpush_sender_buffer);
-
- rrdpush_sender_thread_reset_all_charts(host);
- rrdpush_sender_thread_send_custom_host_variables(host);
-
- rrdpush_buffer_unlock(host);
-}
-
-void rrdpush_sender_thread_stop(RRDHOST *host) {
- rrdpush_buffer_lock(host);
- rrdhost_wrlock(host);
-
- netdata_thread_t thr = 0;
-
- if(host->rrdpush_sender_spawn) {
- info("STREAM %s [send]: signaling sending thread to stop...", host->hostname);
-
- // signal the thread that we want to join it
- host->rrdpush_sender_join = 1;
-
- // copy the thread id, so that we will be waiting for the right one
- // even if a new one has been spawn
- thr = host->rrdpush_sender_thread;
-
- // signal it to cancel
- netdata_thread_cancel(host->rrdpush_sender_thread);
- }
-
- rrdhost_unlock(host);
- rrdpush_buffer_unlock(host);
-
- if(thr != 0) {
- info("STREAM %s [send]: waiting for the sending thread to stop...", host->hostname);
- void *result;
- netdata_thread_join(thr, &result);
- info("STREAM %s [send]: sending thread has exited.", host->hostname);
- }
-}
-
-static inline void rrdpush_sender_thread_close_socket(RRDHOST *host) {
- host->rrdpush_sender_connected = 0;
-
- if(host->rrdpush_sender_socket != -1) {
- close(host->rrdpush_sender_socket);
- host->rrdpush_sender_socket = -1;
- }
-}
-
-static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_port, int timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) {
- struct timeval tv = {
- .tv_sec = timeout,
- .tv_usec = 0
- };
-
- // make sure the socket is closed
- rrdpush_sender_thread_close_socket(host);
-
- debug(D_STREAM, "STREAM: Attempting to connect...");
- info("STREAM %s [send to %s]: connecting...", host->hostname, host->rrdpush_send_destination);
-
- host->rrdpush_sender_socket = connect_to_one_of(
- host->rrdpush_send_destination
- , default_port
- , &tv
- , reconnects_counter
- , connected_to
- , connected_to_size
- );
-
- if(unlikely(host->rrdpush_sender_socket == -1)) {
- error("STREAM %s [send to %s]: failed to connect", host->hostname, host->rrdpush_send_destination);
- return 0;
- }
-
- info("STREAM %s [send to %s]: initializing communication...", host->hostname, connected_to);
-
- #define HTTP_HEADER_SIZE 8192
- char http[HTTP_HEADER_SIZE + 1];
- snprintfz(http, HTTP_HEADER_SIZE,
- "STREAM key=%s&hostname=%s&registry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&timezone=%s&tags=%s HTTP/1.1\r\n"
- "User-Agent: %s/%s\r\n"
- "Accept: */*\r\n\r\n"
- , host->rrdpush_send_api_key
- , host->hostname
- , host->registry_hostname
- , host->machine_guid
- , default_rrd_update_every
- , host->os
- , host->timezone
- , (host->tags)?host->tags:""
- , host->program_name
- , host->program_version
- );
-
- if(send_timeout(host->rrdpush_sender_socket, http, strlen(http), 0, timeout) == -1) {
- error("STREAM %s [send to %s]: failed to send HTTP header to remote netdata.", host->hostname, connected_to);
- rrdpush_sender_thread_close_socket(host);
- return 0;
- }
-
- info("STREAM %s [send to %s]: waiting response from remote netdata...", host->hostname, connected_to);
-
- if(recv_timeout(host->rrdpush_sender_socket, http, HTTP_HEADER_SIZE, 0, timeout) == -1) {
- error("STREAM %s [send to %s]: remote netdata does not respond.", host->hostname, connected_to);
- rrdpush_sender_thread_close_socket(host);
- return 0;
- }
-
- if(strncmp(http, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT)) != 0) {
- error("STREAM %s [send to %s]: server is not replying properly (is it a netdata?).", host->hostname, connected_to);
- rrdpush_sender_thread_close_socket(host);
- return 0;
- }
-
- info("STREAM %s [send to %s]: established communication - ready to send metrics...", host->hostname, connected_to);
-
- if(sock_setnonblock(host->rrdpush_sender_socket) < 0)
- error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", host->hostname, connected_to);
-
- if(sock_enlarge_out(host->rrdpush_sender_socket) < 0)
- error("STREAM %s [send to %s]: cannot enlarge the socket buffer.", host->hostname, connected_to);
-
- debug(D_STREAM, "STREAM: Connected on fd %d...", host->rrdpush_sender_socket);
-
- return 1;
-}
-
-static void rrdpush_sender_thread_cleanup_callback(void *ptr) {
- RRDHOST *host = (RRDHOST *)ptr;
-
- rrdpush_buffer_lock(host);
- rrdhost_wrlock(host);
-
- info("STREAM %s [send]: sending thread cleans up...", host->hostname);
-
- rrdpush_sender_thread_close_socket(host);
-
- // close the pipe
- if(host->rrdpush_sender_pipe[PIPE_READ] != -1) {
- close(host->rrdpush_sender_pipe[PIPE_READ]);
- host->rrdpush_sender_pipe[PIPE_READ] = -1;
- }
-
- if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1) {
- close(host->rrdpush_sender_pipe[PIPE_WRITE]);
- host->rrdpush_sender_pipe[PIPE_WRITE] = -1;
- }
-
- buffer_free(host->rrdpush_sender_buffer);
- host->rrdpush_sender_buffer = NULL;
-
- if(!host->rrdpush_sender_join) {
- info("STREAM %s [send]: sending thread detaches itself.", host->hostname);
- netdata_thread_detach(netdata_thread_self());
- }
-
- host->rrdpush_sender_spawn = 0;
-
- info("STREAM %s [send]: sending thread now exits.", host->hostname);
-
- rrdhost_unlock(host);
- rrdpush_buffer_unlock(host);
-}
-
-void *rrdpush_sender_thread(void *ptr) {
- RRDHOST *host = (RRDHOST *)ptr;
-
- if(!host->rrdpush_send_enabled || !host->rrdpush_send_destination || !*host->rrdpush_send_destination || !host->rrdpush_send_api_key || !*host->rrdpush_send_api_key) {
- error("STREAM %s [send]: thread created (task id %d), but host has streaming disabled.", host->hostname, gettid());
- return NULL;
- }
-
- info("STREAM %s [send]: thread created (task id %d)", host->hostname, gettid());
-
- int timeout = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "timeout seconds", 60);
- int default_port = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "default port", 19999);
- size_t max_size = (size_t)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "buffer size bytes", 1024 * 1024);
- unsigned int reconnect_delay = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "reconnect delay seconds", 5);
- remote_clock_resync_iterations = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "initial clock resync iterations", remote_clock_resync_iterations);
- char connected_to[CONNECTED_TO_SIZE + 1] = "";
-
- // initialize rrdpush globals
- host->rrdpush_sender_buffer = buffer_create(1);
- host->rrdpush_sender_connected = 0;
- if(pipe(host->rrdpush_sender_pipe) == -1) fatal("STREAM %s [send]: cannot create required pipe.", host->hostname);
-
- // initialize local variables
- size_t begin = 0;
- size_t reconnects_counter = 0;
- size_t sent_bytes = 0;
- size_t sent_bytes_on_this_connection = 0;
-
-
- time_t last_sent_t = 0;
- struct pollfd fds[2], *ifd, *ofd;
- nfds_t fdmax;
-
- ifd = &fds[0];
- ofd = &fds[1];
-
- size_t not_connected_loops = 0;
-
- netdata_thread_cleanup_push(rrdpush_sender_thread_cleanup_callback, host);
-
- for(; host->rrdpush_send_enabled && !netdata_exit ;) {
- // check for outstanding cancellation requests
- netdata_thread_testcancel();
-
- // if we don't have socket open, lets wait a bit
- if(unlikely(host->rrdpush_sender_socket == -1)) {
- if(not_connected_loops == 0 && sent_bytes_on_this_connection > 0) {
- // fast re-connection on first disconnect
- sleep_usec(USEC_PER_MS * 500); // milliseconds
- }
- else {
- // slow re-connection on repeating errors
- sleep_usec(USEC_PER_SEC * reconnect_delay); // seconds
- }
-
- if(rrdpush_sender_thread_connect_to_master(host, default_port, timeout, &reconnects_counter, connected_to, CONNECTED_TO_SIZE)) {
- last_sent_t = now_monotonic_sec();
-
- // reset the buffer, to properly send charts and metrics
- rrdpush_sender_thread_data_flush(host);
-
- // make sure the next reconnection will be immediate
- not_connected_loops = 0;
-
- // reset the bytes we have sent for this session
- sent_bytes_on_this_connection = 0;
-
- // let the data collection threads know we are ready
- host->rrdpush_sender_connected = 1;
- }
- else {
- // increase the failed connections counter
- not_connected_loops++;
-
- // reset the number of bytes sent
- sent_bytes_on_this_connection = 0;
- }
-
- // loop through
- continue;
- }
- else if(unlikely(now_monotonic_sec() - last_sent_t > timeout)) {
- error("STREAM %s [send to %s]: could not send metrics for %d seconds - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, timeout, sent_bytes_on_this_connection);
- rrdpush_sender_thread_close_socket(host);
- }
-
- ifd->fd = host->rrdpush_sender_pipe[PIPE_READ];
- ifd->events = POLLIN;
- ifd->revents = 0;
-
- ofd->fd = host->rrdpush_sender_socket;
- ofd->revents = 0;
- if(ofd->fd != -1 && begin < buffer_strlen(host->rrdpush_sender_buffer)) {
- debug(D_STREAM, "STREAM: Requesting data output on streaming socket %d...", ofd->fd);
- ofd->events = POLLOUT;
- fdmax = 2;
- }
- else {
- debug(D_STREAM, "STREAM: Not requesting data output on streaming socket %d (nothing to send now)...", ofd->fd);
- ofd->events = 0;
- fdmax = 1;
- }
-
- debug(D_STREAM, "STREAM: Waiting for poll() events (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer));
- if(unlikely(netdata_exit)) break;
- int retval = poll(fds, fdmax, 1000);
- if(unlikely(netdata_exit)) break;
-
- if(unlikely(retval == -1)) {
- debug(D_STREAM, "STREAM: poll() failed (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer));
-
- if(errno == EAGAIN || errno == EINTR) {
- debug(D_STREAM, "STREAM: poll() failed with EAGAIN or EINTR...");
- }
- else {
- error("STREAM %s [send to %s]: failed to poll(). Closing socket.", host->hostname, connected_to);
- rrdpush_sender_thread_close_socket(host);
- }
-
- continue;
- }
- else if(likely(retval)) {
- if (ifd->revents & POLLIN || ifd->revents & POLLPRI) {
- debug(D_STREAM, "STREAM: Data added to send buffer (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer));
-
- char buffer[1000 + 1];
- if (read(host->rrdpush_sender_pipe[PIPE_READ], buffer, 1000) == -1)
- error("STREAM %s [send to %s]: cannot read from internal pipe.", host->hostname, connected_to);
- }
-
- if (ofd->revents & POLLOUT) {
- if (begin < buffer_strlen(host->rrdpush_sender_buffer)) {
- debug(D_STREAM, "STREAM: Sending data (current buffer length %zu bytes, begin = %zu)...", buffer_strlen(host->rrdpush_sender_buffer), begin);
-
- // BEGIN RRDPUSH LOCKED SESSION
-
- // during this session, data collectors
- // will not be able to append data to our buffer
- // but the socket is in non-blocking mode
- // so, we will not block at send()
-
- netdata_thread_disable_cancelability();
-
- debug(D_STREAM, "STREAM: Getting exclusive lock on host...");
- rrdpush_buffer_lock(host);
-
- debug(D_STREAM, "STREAM: Sending data, starting from %zu, size %zu...", begin, buffer_strlen(host->rrdpush_sender_buffer));
- ssize_t ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT);
- if (unlikely(ret == -1)) {
- if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
- debug(D_STREAM, "STREAM: Send failed - closing socket...");
- error("STREAM %s [send to %s]: failed to send metrics - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_bytes_on_this_connection);
- rrdpush_sender_thread_close_socket(host);
- }
- else {
- debug(D_STREAM, "STREAM: Send failed - will retry...");
- }
- }
- else if (likely(ret > 0)) {
- // DEBUG - dump the string to see it
- //char c = host->rrdpush_sender_buffer->buffer[begin + ret];
- //host->rrdpush_sender_buffer->buffer[begin + ret] = '\0';
- //debug(D_STREAM, "STREAM: sent from %zu to %zd:\n%s\n", begin, ret, &host->rrdpush_sender_buffer->buffer[begin]);
- //host->rrdpush_sender_buffer->buffer[begin + ret] = c;
-
- sent_bytes_on_this_connection += ret;
- sent_bytes += ret;
- begin += ret;
-
- if (begin == buffer_strlen(host->rrdpush_sender_buffer)) {
- // we send it all
-
- debug(D_STREAM, "STREAM: Sent %zd bytes (the whole buffer)...", ret);
- buffer_flush(host->rrdpush_sender_buffer);
- begin = 0;
- }
- else {
- debug(D_STREAM, "STREAM: Sent %zd bytes (part of the data buffer)...", ret);
- }
-
- last_sent_t = now_monotonic_sec();
- }
- else {
- debug(D_STREAM, "STREAM: send() returned %zd - closing the socket...", ret);
- error("STREAM %s [send to %s]: failed to send metrics (send() returned %zd) - closing connection - we have sent %zu bytes on this connection.",
- host->hostname, connected_to, ret, sent_bytes_on_this_connection);
- rrdpush_sender_thread_close_socket(host);
- }
-
- debug(D_STREAM, "STREAM: Releasing exclusive lock on host...");
- rrdpush_buffer_unlock(host);
-
- netdata_thread_enable_cancelability();
-
- // END RRDPUSH LOCKED SESSION
- }
- else {
- debug(D_STREAM, "STREAM: we have sent the entire buffer, but we received POLLOUT...");
- }
- }
-
- if(host->rrdpush_sender_socket != -1) {
- char *error = NULL;
-
- if (unlikely(ofd->revents & POLLERR))
- error = "socket reports errors (POLLERR)";
-
- else if (unlikely(ofd->revents & POLLHUP))
- error = "connection closed by remote end (POLLHUP)";
-
- else if (unlikely(ofd->revents & POLLNVAL))
- error = "connection is invalid (POLLNVAL)";
-
- if(unlikely(error)) {
- debug(D_STREAM, "STREAM: %s - closing socket...", error);
- error("STREAM %s [send to %s]: %s - reopening socket - we have sent %zu bytes on this connection.", host->hostname, connected_to, error, sent_bytes_on_this_connection);
- rrdpush_sender_thread_close_socket(host);
- }
- }
- }
- else {
- debug(D_STREAM, "STREAM: poll() timed out.");
- }
-
- // protection from overflow
- if(buffer_strlen(host->rrdpush_sender_buffer) > max_size) {
- debug(D_STREAM, "STREAM: Buffer is too big (%zu bytes), bigger than the max (%zu) - flushing it...", buffer_strlen(host->rrdpush_sender_buffer), max_size);
- errno = 0;
- error("STREAM %s [send to %s]: too many data pending - buffer is %zu bytes long, %zu unsent - we have sent %zu bytes in total, %zu on this connection. Closing connection to flush the data.", host->hostname, connected_to, host->rrdpush_sender_buffer->len, host->rrdpush_sender_buffer->len - begin, sent_bytes, sent_bytes_on_this_connection);
- rrdpush_sender_thread_close_socket(host);
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-
-// ----------------------------------------------------------------------------
-// rrdpush receiver thread
-
-static void log_stream_connection(const char *client_ip, const char *client_port, const char *api_key, const char *machine_guid, const char *host, const char *msg) {
- log_access("STREAM: %d '[%s]:%s' '%s' host '%s' api key '%s' machine guid '%s'", gettid(), client_ip, client_port, msg, host, api_key, machine_guid);
-}
-
-static RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY get_multiple_connections_strategy(struct config *c, const char *section, const char *name, RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY def) {
- char *value;
- switch(def) {
- default:
- case RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW:
- value = "allow";
- break;
-
- case RRDPUSH_MULTIPLE_CONNECTIONS_DENY_NEW:
- value = "deny";
- break;
- }
-
- value = appconfig_get(c, section, name, value);
-
- RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY ret = def;
-
- if(strcasecmp(value, "allow") == 0 || strcasecmp(value, "permit") == 0 || strcasecmp(value, "accept") == 0)
- ret = RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW;
-
- else if(strcasecmp(value, "deny") == 0 || strcasecmp(value, "reject") == 0 || strcasecmp(value, "block") == 0)
- ret = RRDPUSH_MULTIPLE_CONNECTIONS_DENY_NEW;
-
- else
- error("Invalid stream config value at section [%s], setting '%s', value '%s'", section, name, value);
-
- return ret;
-}
-
-static int rrdpush_receive(int fd
- , const char *key
- , const char *hostname
- , const char *registry_hostname
- , const char *machine_guid
- , const char *os
- , const char *timezone
- , const char *tags
- , const char *program_name
- , const char *program_version
- , int update_every
- , char *client_ip
- , char *client_port
-) {
- RRDHOST *host;
- int history = default_rrd_history_entries;
- RRD_MEMORY_MODE mode = default_rrd_memory_mode;
- int health_enabled = default_health_enabled;
- int rrdpush_enabled = default_rrdpush_enabled;
- char *rrdpush_destination = default_rrdpush_destination;
- char *rrdpush_api_key = default_rrdpush_api_key;
- time_t alarms_delay = 60;
- RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY rrdpush_multiple_connections_strategy = RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW;
-
- update_every = (int)appconfig_get_number(&stream_config, machine_guid, "update every", update_every);
- if(update_every < 0) update_every = 1;
-
- history = (int)appconfig_get_number(&stream_config, key, "default history", history);
- history = (int)appconfig_get_number(&stream_config, machine_guid, "history", history);
- if(history < 5) history = 5;
-
- mode = rrd_memory_mode_id(appconfig_get(&stream_config, key, "default memory mode", rrd_memory_mode_name(mode)));
- mode = rrd_memory_mode_id(appconfig_get(&stream_config, machine_guid, "memory mode", rrd_memory_mode_name(mode)));
-
- health_enabled = appconfig_get_boolean_ondemand(&stream_config, key, "health enabled by default", health_enabled);
- health_enabled = appconfig_get_boolean_ondemand(&stream_config, machine_guid, "health enabled", health_enabled);
-
- alarms_delay = appconfig_get_number(&stream_config, key, "default postpone alarms on connect seconds", alarms_delay);
- alarms_delay = appconfig_get_number(&stream_config, machine_guid, "postpone alarms on connect seconds", alarms_delay);
-
- rrdpush_enabled = appconfig_get_boolean(&stream_config, key, "default proxy enabled", rrdpush_enabled);
- rrdpush_enabled = appconfig_get_boolean(&stream_config, machine_guid, "proxy enabled", rrdpush_enabled);
-
- rrdpush_destination = appconfig_get(&stream_config, key, "default proxy destination", rrdpush_destination);
- rrdpush_destination = appconfig_get(&stream_config, machine_guid, "proxy destination", rrdpush_destination);
-
- rrdpush_api_key = appconfig_get(&stream_config, key, "default proxy api key", rrdpush_api_key);
- rrdpush_api_key = appconfig_get(&stream_config, machine_guid, "proxy api key", rrdpush_api_key);
-
- rrdpush_multiple_connections_strategy = get_multiple_connections_strategy(&stream_config, key, "multiple connections", rrdpush_multiple_connections_strategy);
- rrdpush_multiple_connections_strategy = get_multiple_connections_strategy(&stream_config, machine_guid, "multiple connections", rrdpush_multiple_connections_strategy);
-
- tags = appconfig_set_default(&stream_config, machine_guid, "host tags", (tags)?tags:"");
- if(tags && !*tags) tags = NULL;
-
- if(!strcmp(machine_guid, "localhost"))
- host = localhost;
- else
- host = rrdhost_find_or_create(
- hostname
- , registry_hostname
- , machine_guid
- , os
- , timezone
- , tags
- , program_name
- , program_version
- , update_every
- , history
- , mode
- , (health_enabled != CONFIG_BOOLEAN_NO)
- , (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key)
- , rrdpush_destination
- , rrdpush_api_key
- );
-
- if(!host) {
- close(fd);
- log_stream_connection(client_ip, client_port, key, machine_guid, hostname, "FAILED - CANNOT ACQUIRE HOST");
- error("STREAM %s [receive from [%s]:%s]: failed to find/create host structure.", hostname, client_ip, client_port);
- return 1;
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- info("STREAM %s [receive from [%s]:%s]: client willing to stream metrics for host '%s' with machine_guid '%s': update every = %d, history = %ld, memory mode = %s, health %s, tags '%s'"
- , hostname
- , client_ip
- , client_port
- , host->hostname
- , host->machine_guid
- , host->rrd_update_every
- , host->rrd_history_entries
- , rrd_memory_mode_name(host->rrd_memory_mode)
- , (health_enabled == CONFIG_BOOLEAN_NO)?"disabled":((health_enabled == CONFIG_BOOLEAN_YES)?"enabled":"auto")
- , host->tags?host->tags:""
- );
-#endif // NETDATA_INTERNAL_CHECKS
-
- struct plugind cd = {
- .enabled = 1,
- .update_every = default_rrd_update_every,
- .pid = 0,
- .serial_failures = 0,
- .successful_collections = 0,
- .obsolete = 0,
- .started_t = now_realtime_sec(),
- .next = NULL,
- };
-
- // put the client IP and port into the buffers used by plugins.d
- snprintfz(cd.id, CONFIG_MAX_NAME, "%s:%s", client_ip, client_port);
- snprintfz(cd.filename, FILENAME_MAX, "%s:%s", client_ip, client_port);
- snprintfz(cd.fullfilename, FILENAME_MAX, "%s:%s", client_ip, client_port);
- snprintfz(cd.cmd, PLUGINSD_CMD_MAX, "%s:%s", client_ip, client_port);
-
- info("STREAM %s [receive from [%s]:%s]: initializing communication...", host->hostname, client_ip, client_port);
- if(send_timeout(fd, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT), 0, 60) != strlen(START_STREAMING_PROMPT)) {
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "FAILED - CANNOT REPLY");
- error("STREAM %s [receive from [%s]:%s]: cannot send ready command.", host->hostname, client_ip, client_port);
- close(fd);
- return 0;
- }
-
- // remove the non-blocking flag from the socket
- if(sock_delnonblock(fd) < 0)
- error("STREAM %s [receive from [%s]:%s]: cannot remove the non-blocking flag from socket %d", host->hostname, client_ip, client_port, fd);
-
- // convert the socket to a FILE *
- FILE *fp = fdopen(fd, "r");
- if(!fp) {
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "FAILED - SOCKET ERROR");
- error("STREAM %s [receive from [%s]:%s]: failed to get a FILE for FD %d.", host->hostname, client_ip, client_port, fd);
- close(fd);
- return 0;
- }
-
- rrdhost_wrlock(host);
- if(host->connected_senders > 0) {
- switch(rrdpush_multiple_connections_strategy) {
- case RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW:
- info("STREAM %s [receive from [%s]:%s]: multiple streaming connections for the same host detected. If multiple netdata are pushing metrics for the same charts, at the same time, the result is unexpected.", host->hostname, client_ip, client_port);
- break;
-
- case RRDPUSH_MULTIPLE_CONNECTIONS_DENY_NEW:
- rrdhost_unlock(host);
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "REJECTED - ALREADY CONNECTED");
- info("STREAM %s [receive from [%s]:%s]: multiple streaming connections for the same host detected. Rejecting new connection.", host->hostname, client_ip, client_port);
- fclose(fp);
- return 0;
- }
- }
-
- rrdhost_flag_clear(host, RRDHOST_FLAG_ORPHAN);
- host->connected_senders++;
- host->senders_disconnected_time = 0;
- if(health_enabled != CONFIG_BOOLEAN_NO) {
- if(alarms_delay > 0) {
- host->health_delay_up_to = now_realtime_sec() + alarms_delay;
- info("Postponing health checks for %ld seconds, on host '%s', because it was just connected."
- , alarms_delay
- , host->hostname
- );
- }
- }
- rrdhost_unlock(host);
-
- // call the plugins.d processor to receive the metrics
- info("STREAM %s [receive from [%s]:%s]: receiving metrics...", host->hostname, client_ip, client_port);
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "CONNECTED");
-
- size_t count = pluginsd_process(host, &cd, fp, 1);
-
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "DISCONNECTED");
- error("STREAM %s [receive from [%s]:%s]: disconnected (completed %zu updates).", host->hostname, client_ip, client_port, count);
-
- rrdhost_wrlock(host);
- host->senders_disconnected_time = now_realtime_sec();
- host->connected_senders--;
- if(!host->connected_senders) {
- rrdhost_flag_set(host, RRDHOST_FLAG_ORPHAN);
- if(health_enabled == CONFIG_BOOLEAN_AUTO)
- host->health_enabled = 0;
- }
- rrdhost_unlock(host);
-
- if(host->connected_senders == 0)
- rrdpush_sender_thread_stop(host);
-
- // cleanup
- fclose(fp);
-
- return (int)count;
-}
-
-struct rrdpush_thread {
- int fd;
- char *key;
- char *hostname;
- char *registry_hostname;
- char *machine_guid;
- char *os;
- char *timezone;
- char *tags;
- char *client_ip;
- char *client_port;
- char *program_name;
- char *program_version;
- int update_every;
-};
-
-static void rrdpush_receiver_thread_cleanup(void *ptr) {
- static __thread int executed = 0;
- if(!executed) {
- executed = 1;
- struct rrdpush_thread *rpt = (struct rrdpush_thread *) ptr;
-
- info("STREAM %s [receive from [%s]:%s]: receive thread ended (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
-
- freez(rpt->key);
- freez(rpt->hostname);
- freez(rpt->registry_hostname);
- freez(rpt->machine_guid);
- freez(rpt->os);
- freez(rpt->timezone);
- freez(rpt->tags);
- freez(rpt->client_ip);
- freez(rpt->client_port);
- freez(rpt->program_name);
- freez(rpt->program_version);
- freez(rpt);
- }
-}
-
-static void *rrdpush_receiver_thread(void *ptr) {
- netdata_thread_cleanup_push(rrdpush_receiver_thread_cleanup, ptr);
-
- struct rrdpush_thread *rpt = (struct rrdpush_thread *)ptr;
- info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
-
- rrdpush_receive(
- rpt->fd
- , rpt->key
- , rpt->hostname
- , rpt->registry_hostname
- , rpt->machine_guid
- , rpt->os
- , rpt->timezone
- , rpt->tags
- , rpt->program_name
- , rpt->program_version
- , rpt->update_every
- , rpt->client_ip
- , rpt->client_port
- );
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-static void rrdpush_sender_thread_spawn(RRDHOST *host) {
- rrdhost_wrlock(host);
-
- if(!host->rrdpush_sender_spawn) {
- char tag[NETDATA_THREAD_TAG_MAX + 1];
- snprintfz(tag, NETDATA_THREAD_TAG_MAX, "STREAM_SENDER[%s]", host->hostname);
-
- if(netdata_thread_create(&host->rrdpush_sender_thread, tag, NETDATA_THREAD_OPTION_JOINABLE, rrdpush_sender_thread, (void *) host))
- error("STREAM %s [send]: failed to create new thread for client.", host->hostname);
- else
- host->rrdpush_sender_spawn = 1;
- }
-
- rrdhost_unlock(host);
-}
-
-int rrdpush_receiver_permission_denied(struct web_client *w) {
- // we always respond with the same message and error code
- // to prevent an attacker from gaining info about the error
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "You are not permitted to access this. Check the logs for more info.");
- return 401;
-}
-
-int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url) {
- (void)host;
-
- info("clients wants to STREAM metrics.");
-
- char *key = NULL, *hostname = NULL, *registry_hostname = NULL, *machine_guid = NULL, *os = "unknown", *timezone = "unknown", *tags = NULL;
- int update_every = default_rrd_update_every;
- char buf[GUID_LEN + 1];
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if(!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if(!name || !*name) continue;
- if(!value || !*value) continue;
-
- if(!strcmp(name, "key"))
- key = value;
- else if(!strcmp(name, "hostname"))
- hostname = value;
- else if(!strcmp(name, "registry_hostname"))
- registry_hostname = value;
- else if(!strcmp(name, "machine_guid"))
- machine_guid = value;
- else if(!strcmp(name, "update_every"))
- update_every = (int)strtoul(value, NULL, 0);
- else if(!strcmp(name, "os"))
- os = value;
- else if(!strcmp(name, "timezone"))
- timezone = value;
- else if(!strcmp(name, "tags"))
- tags = value;
- else
- info("STREAM [receive from [%s]:%s]: request has parameter '%s' = '%s', which is not used.", w->client_ip, w->client_port, key, value);
- }
-
- if(!key || !*key) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO KEY");
- error("STREAM [receive from [%s]:%s]: request without an API key. Forbidding access.", w->client_ip, w->client_port);
- return rrdpush_receiver_permission_denied(w);
- }
-
- if(!hostname || !*hostname) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO HOSTNAME");
- error("STREAM [receive from [%s]:%s]: request without a hostname. Forbidding access.", w->client_ip, w->client_port);
- return rrdpush_receiver_permission_denied(w);
- }
-
- if(!machine_guid || !*machine_guid) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - NO MACHINE GUID");
- error("STREAM [receive from [%s]:%s]: request without a machine GUID. Forbidding access.", w->client_ip, w->client_port);
- return rrdpush_receiver_permission_denied(w);
- }
-
- if(regenerate_guid(key, buf) == -1) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - INVALID KEY");
- error("STREAM [receive from [%s]:%s]: API key '%s' is not valid GUID (use the command uuidgen to generate one). Forbidding access.", w->client_ip, w->client_port, key);
- return rrdpush_receiver_permission_denied(w);
- }
-
- if(regenerate_guid(machine_guid, buf) == -1) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - INVALID MACHINE GUID");
- error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not GUID. Forbidding access.", w->client_ip, w->client_port, machine_guid);
- return rrdpush_receiver_permission_denied(w);
- }
-
- if(!appconfig_get_boolean(&stream_config, key, "enabled", 0)) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - KEY NOT ENABLED");
- error("STREAM [receive from [%s]:%s]: API key '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, key);
- return rrdpush_receiver_permission_denied(w);
- }
-
- {
- SIMPLE_PATTERN *key_allow_from = simple_pattern_create(appconfig_get(&stream_config, key, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT);
- if(key_allow_from) {
- if(!simple_pattern_matches(key_allow_from, w->client_ip)) {
- simple_pattern_free(key_allow_from);
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname) ? hostname : "-", "ACCESS DENIED - KEY NOT ALLOWED FROM THIS IP");
- error("STREAM [receive from [%s]:%s]: API key '%s' is not permitted from this IP. Forbidding access.", w->client_ip, w->client_port, key);
- return rrdpush_receiver_permission_denied(w);
- }
- simple_pattern_free(key_allow_from);
- }
- }
-
- if(!appconfig_get_boolean(&stream_config, machine_guid, "enabled", 1)) {
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname)?hostname:"-", "ACCESS DENIED - MACHINE GUID NOT ENABLED");
- error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, machine_guid);
- return rrdpush_receiver_permission_denied(w);
- }
-
- {
- SIMPLE_PATTERN *machine_allow_from = simple_pattern_create(appconfig_get(&stream_config, machine_guid, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT);
- if(machine_allow_from) {
- if(!simple_pattern_matches(machine_allow_from, w->client_ip)) {
- simple_pattern_free(machine_allow_from);
- log_stream_connection(w->client_ip, w->client_port, (key && *key)?key:"-", (machine_guid && *machine_guid)?machine_guid:"-", (hostname && *hostname) ? hostname : "-", "ACCESS DENIED - MACHINE GUID NOT ALLOWED FROM THIS IP");
- error("STREAM [receive from [%s]:%s]: Machine GUID '%s' is not permitted from this IP. Forbidding access.", w->client_ip, w->client_port, machine_guid);
- return rrdpush_receiver_permission_denied(w);
- }
- simple_pattern_free(machine_allow_from);
- }
- }
-
- struct rrdpush_thread *rpt = callocz(1, sizeof(struct rrdpush_thread));
- rpt->fd = w->ifd;
- rpt->key = strdupz(key);
- rpt->hostname = strdupz(hostname);
- rpt->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
- rpt->machine_guid = strdupz(machine_guid);
- rpt->os = strdupz(os);
- rpt->timezone = strdupz(timezone);
- rpt->tags = (tags)?strdupz(tags):NULL;
- rpt->client_ip = strdupz(w->client_ip);
- rpt->client_port = strdupz(w->client_port);
- rpt->update_every = update_every;
-
- if(w->user_agent && w->user_agent[0]) {
- char *t = strchr(w->user_agent, '/');
- if(t && *t) {
- *t = '\0';
- t++;
- }
-
- rpt->program_name = strdupz(w->user_agent);
- if(t && *t) rpt->program_version = strdupz(t);
- }
-
- netdata_thread_t thread;
-
- debug(D_SYSTEM, "starting STREAM receive thread.");
-
- char tag[FILENAME_MAX + 1];
- snprintfz(tag, FILENAME_MAX, "STREAM_RECEIVER[%s,[%s]:%s]", rpt->hostname, w->client_ip, w->client_port);
-
- if(netdata_thread_create(&thread, tag, NETDATA_THREAD_OPTION_DEFAULT, rrdpush_receiver_thread, (void *)rpt))
- error("Failed to create new STREAM receive thread for client.");
-
- // prevent the caller from closing the streaming socket
- if(web_server_mode == WEB_SERVER_MODE_STATIC_THREADED) {
- web_client_flag_set(w, WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET);
- }
- else {
- if(w->ifd == w->ofd)
- w->ifd = w->ofd = -1;
- else
- w->ifd = -1;
- }
-
- buffer_flush(w->response.data);
- return 200;
-}
diff --git a/src/rrdpush.h b/src/rrdpush.h
deleted file mode 100644
index bf3d9435c..000000000
--- a/src/rrdpush.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef NETDATA_RRDPUSH_H
-#define NETDATA_RRDPUSH_H
-
-extern int default_rrdpush_enabled;
-extern char *default_rrdpush_destination;
-extern char *default_rrdpush_api_key;
-extern unsigned int remote_clock_resync_iterations;
-
-extern int rrdpush_init();
-extern void rrdset_done_push(RRDSET *st);
-extern void rrdset_push_chart_definition(RRDSET *st);
-extern void *rrdpush_sender_thread(void *ptr);
-
-extern int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url);
-extern void rrdpush_sender_thread_stop(RRDHOST *host);
-
-extern void rrdpush_sender_send_this_host_variable_now(RRDHOST *host, RRDVAR *rv);
-
-#endif //NETDATA_RRDPUSH_H
diff --git a/src/rrdset.c b/src/rrdset.c
deleted file mode 100644
index bbd0ae728..000000000
--- a/src/rrdset.c
+++ /dev/null
@@ -1,1544 +0,0 @@
-#define NETDATA_RRD_INTERNALS 1
-#include "common.h"
-
-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 = 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(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 = 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);
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDSET index
-
-int rrdset_compare(void* a, void* b) {
- if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1;
- else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1;
- else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id);
-}
-
-static RRDSET *rrdset_index_find(RRDHOST *host, const char *id, uint32_t hash) {
- RRDSET tmp;
- strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX);
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
-
- return (RRDSET *)avl_search_lock(&(host->rrdset_root_index), (avl *) &tmp);
-}
-
-// ----------------------------------------------------------------------------
-// RRDSET name index
-
-#define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname)))
-
-int rrdset_compare_name(void* a, void* b) {
- RRDSET *A = rrdset_from_avlname(a);
- RRDSET *B = rrdset_from_avlname(b);
-
- // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name);
-
- if(A->hash_name < B->hash_name) return -1;
- else if(A->hash_name > B->hash_name) return 1;
- else return strcmp(A->name, B->name);
-}
-
-RRDSET *rrdset_index_add_name(RRDHOST *host, RRDSET *st) {
- void *result;
- // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name);
- result = avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname));
- if(result) return rrdset_from_avlname(result);
- return NULL;
-}
-
-RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st) {
- void *result;
- // fprintf(stderr, "DELETING: %s (name: %s)\n", st->id, st->name);
- result = (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index_name), (avl *)(&st->avlname));
- if(result) return rrdset_from_avlname(result);
- return NULL;
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDSET - find charts
-
-static inline RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t hash) {
- void *result = NULL;
- RRDSET tmp;
- tmp.name = name;
- tmp.hash_name = (hash)?hash:simple_hash(tmp.name);
-
- // fprintf(stderr, "SEARCHING: %s\n", name);
- result = avl_search_lock(&host->rrdset_root_index_name, (avl *) (&(tmp.avlname)));
- if(result) {
- RRDSET *st = rrdset_from_avlname(result);
- if(strcmp(st->magic, RRDSET_MAGIC) != 0)
- error("Search for RRDSET %s returned an invalid RRDSET %s (name %s)", name, st->id, st->name);
-
- // fprintf(stderr, "FOUND: %s\n", name);
- return rrdset_from_avlname(result);
- }
- // fprintf(stderr, "NOT FOUND: %s\n", name);
- return NULL;
-}
-
-inline RRDSET *rrdset_find(RRDHOST *host, const char *id) {
- debug(D_RRD_CALLS, "rrdset_find() for chart '%s' in host '%s'", id, host->hostname);
- RRDSET *st = rrdset_index_find(host, id, 0);
- return(st);
-}
-
-inline RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id) {
- debug(D_RRD_CALLS, "rrdset_find_bytype() for chart '%s.%s' in host '%s'", type, id, host->hostname);
-
- char buf[RRD_ID_LENGTH_MAX + 1];
- strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1);
- strcat(buf, ".");
- int len = (int) strlen(buf);
- strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len));
-
- return(rrdset_find(host, buf));
-}
-
-inline RRDSET *rrdset_find_byname(RRDHOST *host, const char *name) {
- debug(D_RRD_CALLS, "rrdset_find_byname() for chart '%s' in host '%s'", name, host->hostname);
- RRDSET *st = rrdset_index_find_name(host, name, 0);
- return(st);
-}
-
-// ----------------------------------------------------------------------------
-// RRDSET - rename charts
-
-char *rrdset_strncpyz_name(char *to, const char *from, size_t length) {
- char c, *p = to;
-
- while (length-- && (c = *from++)) {
- if(c != '.' && !isalnum(c))
- c = '_';
-
- *p++ = c;
- }
-
- *p = '\0';
-
- return to;
-}
-
-int rrdset_set_name(RRDSET *st, const char *name) {
- if(unlikely(st->name && !strcmp(st->name, name)))
- return 1;
-
- RRDHOST *host = st->rrdhost;
-
- debug(D_RRD_CALLS, "rrdset_set_name() old: '%s', new: '%s'", st->name?st->name:"", name);
-
- char b[CONFIG_MAX_VALUE + 1];
- char n[RRD_ID_LENGTH_MAX + 1];
-
- snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name);
- rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE);
-
- if(rrdset_index_find_name(host, b, 0)) {
- error("RRDSET: chart name '%s' on host '%s' already exists.", b, host->hostname);
- return 0;
- }
-
- if(st->name) {
- rrdset_index_del_name(host, st);
- st->name = config_set_default(st->config_section, "name", b);
- st->hash_name = simple_hash(st->name);
- rrdsetvar_rename_all(st);
- }
- else {
- st->name = config_get(st->config_section, "name", b);
- st->hash_name = simple_hash(st->name);
- }
-
- rrdset_wrlock(st);
- RRDDIM *rd;
- rrddim_foreach_write(rd, st)
- rrddimvar_rename_all(rd);
- rrdset_unlock(st);
-
- if(unlikely(rrdset_index_add_name(host, st) != st))
- error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name);
-
- return 1;
-}
-
-inline void rrdset_is_obsolete(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
-
- if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) {
- rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE);
- rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
-
- // the chart will not get more updates (data collection)
- // so, we have to push its definition now
- if(unlikely(host->rrdpush_send_enabled))
- rrdset_push_chart_definition(st);
- }
-}
-
-inline void rrdset_isnot_obsolete(RRDSET *st) {
- if(unlikely((rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) {
- rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE);
- rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
-
- // the chart will be pushed upstream automatically
- // due to data collection
- }
-}
-
-inline void rrdset_update_heterogeneous_flag(RRDSET *st) {
- RRDHOST *host = st->rrdhost;
- RRDDIM *rd;
-
- rrdset_flag_clear(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
-
- RRD_ALGORITHM algorithm = st->dimensions->algorithm;
- collected_number multiplier = abs(st->dimensions->multiplier);
- collected_number divisor = abs(st->dimensions->divisor);
-
- rrddim_foreach_read(rd, st) {
- if(algorithm != rd->algorithm || multiplier != abs(rd->multiplier) || divisor != abs(rd->divisor)) {
- if(!rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS)) {
- #ifdef NETDATA_INTERNAL_CHECKS
- info("Dimension '%s' added on chart '%s' of host '%s' is not homogeneous to other dimensions already present (algorithm is '%s' vs '%s', multiplier is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ", divisor is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ").",
- rd->name,
- st->name,
- host->hostname,
- rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm),
- rd->multiplier, multiplier,
- rd->divisor, divisor
- );
- #endif
- rrdset_flag_set(st, RRDSET_FLAG_HETEROGENEOUS);
- }
- return;
- }
- }
-
- rrdset_flag_clear(st, RRDSET_FLAG_HETEROGENEOUS);
-}
-
-// ----------------------------------------------------------------------------
-// RRDSET - reset a chart
-
-void rrdset_reset(RRDSET *st) {
- debug(D_RRD_CALLS, "rrdset_reset() %s", st->name);
-
- st->last_collected_time.tv_sec = 0;
- st->last_collected_time.tv_usec = 0;
- st->last_updated.tv_sec = 0;
- st->last_updated.tv_usec = 0;
- st->current_entry = 0;
- st->counter = 0;
- st->counter_done = 0;
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- rd->last_collected_time.tv_sec = 0;
- rd->last_collected_time.tv_usec = 0;
- rd->collections_counter = 0;
- // memset(rd->values, 0, rd->entries * sizeof(storage_number));
- }
-}
-
-// ----------------------------------------------------------------------------
-// RRDSET - helpers for rrdset_create()
-
-inline long align_entries_to_pagesize(RRD_MEMORY_MODE mode, long entries) {
- if(unlikely(entries < 5)) entries = 5;
- if(unlikely(entries > RRD_HISTORY_ENTRIES_MAX)) entries = RRD_HISTORY_ENTRIES_MAX;
-
- if(unlikely(mode == RRD_MEMORY_MODE_NONE || mode == RRD_MEMORY_MODE_ALLOC))
- return entries;
-
- long page = (size_t)sysconf(_SC_PAGESIZE);
- long size = sizeof(RRDDIM) + entries * sizeof(storage_number);
- if(unlikely(size % page)) {
- size -= (size % page);
- size += page;
-
- long n = (size - sizeof(RRDDIM)) / sizeof(storage_number);
- return n;
- }
-
- return entries;
-}
-
-static inline void last_collected_time_align(RRDSET *st) {
- st->last_collected_time.tv_sec -= st->last_collected_time.tv_sec % st->update_every;
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST)))
- st->last_collected_time.tv_usec = 0;
- else
- st->last_collected_time.tv_usec = 500000;
-}
-
-static inline void last_updated_time_align(RRDSET *st) {
- st->last_updated.tv_sec -= st->last_updated.tv_sec % st->update_every;
- st->last_updated.tv_usec = 0;
-}
-
-// ----------------------------------------------------------------------------
-// RRDSET - free a chart
-
-void rrdset_free(RRDSET *st) {
- if(unlikely(!st)) return;
-
- RRDHOST *host = st->rrdhost;
-
- rrdhost_check_wrlock(host); // make sure we have a write lock on the host
- rrdset_wrlock(st); // lock this RRDSET
-
- // info("Removing chart '%s' ('%s')", st->id, st->name);
-
- // ------------------------------------------------------------------------
- // remove it from the indexes
-
- if(unlikely(rrdset_index_del(host, st) != st))
- error("RRDSET: INTERNAL ERROR: attempt to remove from index chart '%s', removed a different chart.", st->id);
-
- rrdset_index_del_name(host, st);
-
- // ------------------------------------------------------------------------
- // free its children structures
-
- while(st->variables) rrdsetvar_free(st->variables);
- while(st->alarms) rrdsetcalc_unlink(st->alarms);
- while(st->dimensions) rrddim_free(st, st->dimensions);
-
- rrdfamily_free(host, st->rrdfamily);
-
- debug(D_RRD_CALLS, "RRDSET: Cleaning up remaining chart variables for host '%s', chart '%s'", host->hostname, st->id);
- rrdvar_free_remaining_variables(host, &st->rrdvar_root_index);
-
- // ------------------------------------------------------------------------
- // unlink it from the host
-
- if(st == host->rrdset_root) {
- host->rrdset_root = st->next;
- }
- else {
- // find the previous one
- RRDSET *s;
- for(s = host->rrdset_root; s && s->next != st ; s = s->next) ;
-
- // bypass it
- if(s) s->next = st->next;
- else error("Request to free RRDSET '%s': cannot find it under host '%s'", st->id, host->hostname);
- }
-
- rrdset_unlock(st);
-
- // ------------------------------------------------------------------------
- // free it
-
- netdata_rwlock_destroy(&st->rrdset_rwlock);
-
- // free directly allocated members
- freez(st->config_section);
- freez(st->plugin_name);
- freez(st->module_name);
-
- switch(st->rrd_memory_mode) {
- case RRD_MEMORY_MODE_SAVE:
- case RRD_MEMORY_MODE_MAP:
- case RRD_MEMORY_MODE_RAM:
- debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
- munmap(st, st->memsize);
- break;
-
- case RRD_MEMORY_MODE_ALLOC:
- case RRD_MEMORY_MODE_NONE:
- freez(st);
- break;
- }
-}
-
-void rrdset_save(RRDSET *st) {
- rrdset_check_rdlock(st);
-
- // info("Saving chart '%s' ('%s')", st->id, st->name);
-
- if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
- debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
- memory_file_save(st->cache_filename, st, st->memsize);
- }
-
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE)) {
- debug(D_RRD_STATS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
- memory_file_save(rd->cache_filename, rd, rd->memsize);
- }
- }
-}
-
-void rrdset_delete(RRDSET *st) {
- RRDDIM *rd;
-
- rrdset_check_rdlock(st);
-
- info("Deleting chart '%s' ('%s') from disk...", st->id, st->name);
-
- if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) {
- info("Deleting chart header file '%s'.", st->cache_filename);
- if(unlikely(unlink(st->cache_filename) == -1))
- error("Cannot delete chart header file '%s'", st->cache_filename);
- }
-
- rrddim_foreach_read(rd, st) {
- if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || rd->rrd_memory_mode == RRD_MEMORY_MODE_MAP)) {
- info("Deleting dimension file '%s'.", rd->cache_filename);
- if(unlikely(unlink(rd->cache_filename) == -1))
- error("Cannot delete dimension file '%s'", rd->cache_filename);
- }
- }
-
- recursively_delete_dir(st->cache_dir, "left-over chart");
-}
-
-// ----------------------------------------------------------------------------
-// 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_isnot_obsolete(st);
- debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid);
- return st;
- }
-
- return NULL;
-}
-
-RRDSET *rrdset_create_custom(
- RRDHOST *host
- , const char *type
- , const char *id
- , const char *name
- , const char *family
- , const char *context
- , const char *title
- , const char *units
- , const char *plugin
- , const char *module
- , long priority
- , int update_every
- , RRDSET_TYPE chart_type
- , RRD_MEMORY_MODE memory_mode
- , long history_entries
-) {
- if(!type || !type[0]) {
- fatal("Cannot create rrd stats without a type: id '%s', name '%s', family '%s', context '%s', title '%s', units '%s', plugin '%s', module '%s'."
- , (id && *id)?id:"<unset>"
- , (name && *name)?name:"<unset>"
- , (family && *family)?family:"<unset>"
- , (context && *context)?context:"<unset>"
- , (title && *title)?title:"<unset>"
- , (units && *units)?units:"<unset>"
- , (plugin && *plugin)?plugin:"<unset>"
- , (module && *module)?module:"<unset>"
- );
- return NULL;
- }
-
- if(!id || !id[0]) {
- fatal("Cannot create rrd stats without an id: type '%s', name '%s', family '%s', context '%s', title '%s', units '%s', plugin '%s', module '%s'."
- , type
- , (name && *name)?name:"<unset>"
- , (family && *family)?family:"<unset>"
- , (context && *context)?context:"<unset>"
- , (title && *title)?title:"<unset>"
- , (units && *units)?units:"<unset>"
- , (plugin && *plugin)?plugin:"<unset>"
- , (module && *module)?module:"<unset>"
- );
- return NULL;
- }
-
- // ------------------------------------------------------------------------
- // check if it already exists
-
- char fullid[RRD_ID_LENGTH_MAX + 1];
- snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);
-
- RRDSET *st = rrdset_find_on_create(host, fullid);
- if(st) return st;
-
- rrdhost_wrlock(host);
-
- st = rrdset_find_on_create(host, fullid);
- if(st) {
- rrdhost_unlock(host);
- return st;
- }
-
- char fullfilename[FILENAME_MAX + 1];
-
- // ------------------------------------------------------------------------
- // compose the config_section for this chart
-
- char config_section[RRD_ID_LENGTH_MAX + 1];
- if(host == localhost)
- strcpy(config_section, fullid);
- else
- snprintfz(config_section, RRD_ID_LENGTH_MAX, "%s/%s", host->machine_guid, fullid);
-
- // ------------------------------------------------------------------------
- // get the options from the config, we need to create it
-
- long rentries = config_get_number(config_section, "history", history_entries);
- long entries = align_entries_to_pagesize(memory_mode, rentries);
- if(entries != rentries) entries = config_set_number(config_section, "history", entries);
-
- if(memory_mode == RRD_MEMORY_MODE_NONE && entries != rentries)
- entries = config_set_number(config_section, "history", 10);
-
- int enabled = config_get_boolean(config_section, "enabled", 1);
- if(!enabled) entries = 5;
-
- unsigned long size = sizeof(RRDSET);
- char *cache_dir = rrdset_cache_dir(host, fullid, config_section);
-
- time_t now = now_realtime_sec();
-
- // ------------------------------------------------------------------------
- // load it or allocate it
-
- debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
-
- snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
- if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP || memory_mode == RRD_MEMORY_MODE_RAM) {
- st = (RRDSET *) mymmap(
- (memory_mode == RRD_MEMORY_MODE_RAM)?NULL:fullfilename
- , size
- , ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE)
- , 0
- );
-
- if(st) {
- memset(&st->avl, 0, sizeof(avl));
- memset(&st->avlname, 0, sizeof(avl));
- memset(&st->rrdvar_root_index, 0, sizeof(avl_tree_lock));
- memset(&st->dimensions_index, 0, sizeof(avl_tree_lock));
- memset(&st->rrdset_rwlock, 0, sizeof(netdata_rwlock_t));
-
- st->name = NULL;
- st->config_section = NULL;
- st->type = NULL;
- st->family = NULL;
- st->title = NULL;
- st->units = NULL;
- st->context = NULL;
- st->cache_dir = NULL;
- st->plugin_name = NULL;
- st->module_name = NULL;
- st->dimensions = NULL;
- st->rrdfamily = NULL;
- st->rrdhost = NULL;
- st->next = NULL;
- st->variables = NULL;
- st->alarms = NULL;
- st->flags = 0x00000000;
-
- if(memory_mode == RRD_MEMORY_MODE_RAM) {
- memset(st, 0, size);
- }
- else {
- if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
- info("Initializing file %s.", fullfilename);
- memset(st, 0, size);
- }
- else if(strcmp(st->id, fullid) != 0) {
- error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
- // munmap(st, size);
- // st = NULL;
- memset(st, 0, size);
- }
- else if(st->memsize != size || st->entries != entries) {
- error("File %s does not have the desired size. Clearing it.", fullfilename);
- memset(st, 0, size);
- }
- else if(st->update_every != update_every) {
- error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
- memset(st, 0, size);
- }
- else if((now - st->last_updated.tv_sec) > update_every * entries) {
- error("File %s is too old. Clearing it.", fullfilename);
- memset(st, 0, size);
- }
- else if(st->last_updated.tv_sec > now + update_every) {
- error("File %s refers to the future. Clearing it.", fullfilename);
- memset(st, 0, size);
- }
-
- // make sure the database is aligned
- if(st->last_updated.tv_sec) {
- st->update_every = update_every;
- last_updated_time_align(st);
- }
- }
-
- // make sure we have the right memory mode
- // even if we cleared the memory
- st->rrd_memory_mode = memory_mode;
- }
- }
-
- if(unlikely(!st)) {
- st = callocz(1, size);
- st->rrd_memory_mode = (memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_ALLOC;
- }
-
- st->plugin_name = plugin?strdup(plugin):NULL;
- st->module_name = module?strdup(module):NULL;
-
- st->config_section = strdup(config_section);
- st->rrdhost = host;
- st->memsize = size;
- st->entries = entries;
- st->update_every = update_every;
-
- if(st->current_entry >= st->entries) st->current_entry = 0;
-
- strcpy(st->cache_filename, fullfilename);
- strcpy(st->magic, RRDSET_MAGIC);
-
- strcpy(st->id, fullid);
- st->hash = simple_hash(st->id);
-
- st->cache_dir = cache_dir;
-
- st->chart_type = rrdset_type_id(config_get(st->config_section, "chart type", rrdset_type_name(chart_type)));
- st->type = config_get(st->config_section, "type", type);
-
- st->family = config_get(st->config_section, "family", family?family:st->type);
- json_fix_string(st->family);
-
- st->units = config_get(st->config_section, "units", units?units:"");
- json_fix_string(st->units);
-
- st->context = config_get(st->config_section, "context", context?context:st->id);
- json_fix_string(st->context);
- st->hash_context = simple_hash(st->context);
-
- st->priority = config_get_number(st->config_section, "priority", priority);
- if(enabled)
- rrdset_flag_set(st, RRDSET_FLAG_ENABLED);
- else
- rrdset_flag_clear(st, RRDSET_FLAG_ENABLED);
-
- rrdset_flag_clear(st, RRDSET_FLAG_DETAIL);
- rrdset_flag_clear(st, RRDSET_FLAG_DEBUG);
- rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE);
- rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
-
- // if(!strcmp(st->id, "disk_util.dm-0")) {
- // st->debug = 1;
- // error("enabled debugging for '%s'", st->id);
- // }
- // else error("not enabled debugging for '%s'", st->id);
-
- st->green = NAN;
- st->red = NAN;
-
- st->last_collected_time.tv_sec = 0;
- st->last_collected_time.tv_usec = 0;
- st->counter_done = 0;
-
- st->gap_when_lost_iterations_above = (int) (gap_when_lost_iterations_above + 2);
-
- st->last_accessed_time = 0;
- st->upstream_resync_time = 0;
-
- avl_init_lock(&st->dimensions_index, rrddim_compare);
- avl_init_lock(&st->rrdvar_root_index, rrdvar_compare);
-
- netdata_rwlock_init(&st->rrdset_rwlock);
-
- if(name && *name && rrdset_set_name(st, name))
- // we did set the name
- ;
- else
- // could not use the name, use the id
- rrdset_set_name(st, id);
-
- st->title = config_get(st->config_section, "title", title);
- json_fix_string(st->title);
-
- st->rrdfamily = rrdfamily_create(host, st->family);
-
- st->next = host->rrdset_root;
- host->rrdset_root = st;
-
- if(host->health_enabled) {
- rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT);
- rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, RRDVAR_OPTION_DEFAULT);
- rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, RRDVAR_OPTION_DEFAULT);
- rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, RRDVAR_OPTION_DEFAULT);
- rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_OPTION_DEFAULT);
- }
-
- if(unlikely(rrdset_index_add(host, st) != st))
- error("RRDSET: INTERNAL ERROR: attempt to index duplicate chart '%s'", st->id);
-
- rrdsetcalc_link_matching(st);
- rrdcalctemplate_link_matching(st);
-
- rrdhost_cleanup_obsolete_charts(host);
-
- rrdhost_unlock(host);
-
- return(st);
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDSET - data collection iteration control
-
-inline void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds) {
- if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) {
- // call the full next_usec() function
- rrdset_next_usec(st, microseconds);
- return;
- }
-
- st->usec_since_last_update = microseconds;
-}
-
-inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) {
- struct timeval now;
- now_realtime_timeval(&now);
-
- if(unlikely(!st->last_collected_time.tv_sec)) {
- // the first entry
- microseconds = st->update_every * USEC_PER_SEC;
- }
- else if(unlikely(!microseconds)) {
- // no dt given by the plugin
- microseconds = dt_usec(&now, &st->last_collected_time);
- }
- else {
- // microseconds has the time since the last collection
- susec_t since_last_usec = dt_usec_signed(&now, &st->last_collected_time);
-
- if(unlikely(since_last_usec < 0)) {
- // oops! the database is in the future
- info("RRD database for chart '%s' on host '%s' is %0.5" LONG_DOUBLE_MODIFIER " secs in the future (counter #%zu, update #%zu). Adjusting it to current time.", st->id, st->rrdhost->hostname, (LONG_DOUBLE)-since_last_usec / USEC_PER_SEC, st->counter, st->counter_done);
-
- st->last_collected_time.tv_sec = now.tv_sec - st->update_every;
- st->last_collected_time.tv_usec = now.tv_usec;
- last_collected_time_align(st);
-
- st->last_updated.tv_sec = now.tv_sec - st->update_every;
- st->last_updated.tv_usec = now.tv_usec;
- last_updated_time_align(st);
-
- microseconds = st->update_every * USEC_PER_SEC;
- }
- else if(unlikely((usec_t)since_last_usec > (usec_t)(st->update_every * 10 * USEC_PER_SEC))) {
- // oops! the database is too far behind
- info("RRD database for chart '%s' on host '%s' is %0.5" LONG_DOUBLE_MODIFIER " secs in the past (counter #%zu, update #%zu). Adjusting it to current time.", st->id, st->rrdhost->hostname, (LONG_DOUBLE)since_last_usec / USEC_PER_SEC, st->counter, st->counter_done);
-
- microseconds = (usec_t)since_last_usec;
- }
- }
-
- #ifdef NETDATA_INTERNAL_CHECKS
- debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds);
- rrdset_debug(st, "NEXT: %llu microseconds", microseconds);
- #endif
-
- st->usec_since_last_update = microseconds;
-}
-
-
-// ----------------------------------------------------------------------------
-// RRDSET - process the collected values for all dimensions of a chart
-
-static inline usec_t rrdset_init_last_collected_time(RRDSET *st) {
- now_realtime_timeval(&st->last_collected_time);
- last_collected_time_align(st);
-
- usec_t last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "initialized last collected time to %0.3" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE)last_collect_ut / USEC_PER_SEC);
- #endif
-
- return last_collect_ut;
-}
-
-static inline usec_t rrdset_update_last_collected_time(RRDSET *st) {
- usec_t last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
- usec_t ut = last_collect_ut + st->usec_since_last_update;
- st->last_collected_time.tv_sec = (time_t) (ut / USEC_PER_SEC);
- st->last_collected_time.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "updated last collected time to %0.3" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE)last_collect_ut / USEC_PER_SEC);
- #endif
-
- return last_collect_ut;
-}
-
-static inline usec_t rrdset_init_last_updated_time(RRDSET *st) {
- // copy the last collected time to last updated time
- st->last_updated.tv_sec = st->last_collected_time.tv_sec;
- st->last_updated.tv_usec = st->last_collected_time.tv_usec;
-
- if(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST))
- st->last_updated.tv_sec -= st->update_every;
-
- last_updated_time_align(st);
-
- usec_t last_updated_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "initialized last updated time to %0.3" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE)last_updated_ut / USEC_PER_SEC);
- #endif
-
- return last_updated_ut;
-}
-
-static inline void rrdset_done_push_exclusive(RRDSET *st) {
-// usec_t update_every_ut = st->update_every * USEC_PER_SEC; // st->update_every in microseconds
-//
-// if(unlikely(st->usec_since_last_update > update_every_ut * remote_clock_resync_iterations)) {
-// error("Chart '%s' was last collected %llu usec before. Resetting it.", st->id, st->usec_since_last_update);
-// rrdset_reset(st);
-// st->usec_since_last_update = update_every_ut;
-// }
-
- if(unlikely(!st->last_collected_time.tv_sec)) {
- // it is the first entry
- // set the last_collected_time to now
- rrdset_init_last_collected_time(st);
- }
- else {
- // it is not the first entry
- // calculate the proper last_collected_time, using usec_since_last_update
- rrdset_update_last_collected_time(st);
- }
-
- st->counter_done++;
-
- rrdset_rdlock(st);
- rrdset_done_push(st);
- rrdset_unlock(st);
-}
-
-
-static inline size_t rrdset_done_interpolate(
- RRDSET *st
- , usec_t update_every_ut
- , usec_t last_stored_ut
- , usec_t next_store_ut
- , usec_t last_collect_ut
- , usec_t now_collect_ut
- , char store_this_entry
- , uint32_t storage_flags
-) {
- RRDDIM *rd;
-
- size_t stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done()
-
- usec_t first_ut = last_stored_ut, last_ut = 0;
- ssize_t iterations = (ssize_t)((now_collect_ut - last_stored_ut) / (update_every_ut));
- if((now_collect_ut % (update_every_ut)) == 0) iterations++;
-
- size_t counter = st->counter;
- long current_entry = st->current_entry;
-
- for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) {
-
- #ifdef NETDATA_INTERNAL_CHECKS
- if(iterations < 0) { error("INTERNAL CHECK: %s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", st->name, first_ut, last_stored_ut, next_store_ut, now_collect_ut); }
- rrdset_debug(st, "last_stored_ut = %0.3" LONG_DOUBLE_MODIFIER " (last updated time)", (LONG_DOUBLE)last_stored_ut/USEC_PER_SEC);
- rrdset_debug(st, "next_store_ut = %0.3" LONG_DOUBLE_MODIFIER " (next interpolation point)", (LONG_DOUBLE)next_store_ut/USEC_PER_SEC);
- #endif
-
- last_ut = next_store_ut;
-
- rrddim_foreach_read(rd, st) {
- calculated_number new_value;
-
- switch(rd->algorithm) {
- case RRD_ALGORITHM_INCREMENTAL:
- new_value = (calculated_number)
- ( rd->calculated_value
- * (calculated_number)(next_store_ut - last_collect_ut)
- / (calculated_number)(now_collect_ut - last_collect_ut)
- );
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC2 INC "
- CALCULATED_NUMBER_FORMAT " = "
- CALCULATED_NUMBER_FORMAT
- " * (%llu - %llu)"
- " / (%llu - %llu)"
- , rd->name
- , new_value
- , rd->calculated_value
- , next_store_ut, last_collect_ut
- , now_collect_ut, last_collect_ut
- );
- #endif
-
- rd->calculated_value -= new_value;
- new_value += rd->last_calculated_value;
- rd->last_calculated_value = 0;
- new_value /= (calculated_number)st->update_every;
-
- if(unlikely(next_store_ut - last_stored_ut < update_every_ut)) {
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: COLLECTION POINT IS SHORT " CALCULATED_NUMBER_FORMAT " - EXTRAPOLATING",
- rd->name
- , (calculated_number)(next_store_ut - last_stored_ut)
- );
- #endif
-
- new_value = new_value * (calculated_number)(st->update_every * USEC_PER_SEC) / (calculated_number)(next_store_ut - last_stored_ut);
- }
- break;
-
- case RRD_ALGORITHM_ABSOLUTE:
- case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL:
- case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL:
- default:
- if(iterations == 1) {
- // this is the last iteration
- // do not interpolate
- // just show the calculated value
-
- new_value = rd->calculated_value;
- }
- else {
- // we have missed an update
- // interpolate in the middle values
-
- new_value = (calculated_number)
- ( ( (rd->calculated_value - rd->last_calculated_value)
- * (calculated_number)(next_store_ut - last_collect_ut)
- / (calculated_number)(now_collect_ut - last_collect_ut)
- )
- + rd->last_calculated_value
- );
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC2 DEF "
- CALCULATED_NUMBER_FORMAT " = ((("
- "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")"
- " * %llu"
- " / %llu) + " CALCULATED_NUMBER_FORMAT
- , rd->name
- , new_value
- , rd->calculated_value, rd->last_calculated_value
- , (next_store_ut - first_ut)
- , (now_collect_ut - first_ut), rd->last_calculated_value
- );
- #endif
- }
- break;
- }
-
- if(unlikely(!store_this_entry)) {
- rd->values[current_entry] = SN_EMPTY_SLOT; //pack_storage_number(0, SN_NOT_EXISTS);
- continue;
- }
-
- if(likely(rd->updated && rd->collections_counter > 1 && iterations < st->gap_when_lost_iterations_above)) {
- rd->values[current_entry] = pack_storage_number(new_value, storage_flags );
- rd->last_stored_value = new_value;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: STORE[%ld] "
- CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT
- , rd->name
- , current_entry
- , unpack_storage_number(rd->values[current_entry]), new_value
- );
- #endif
-
- }
- else {
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING "
- , rd->name
- , current_entry
- );
- #endif
-
- rd->values[current_entry] = SN_EMPTY_SLOT; // pack_storage_number(0, SN_NOT_EXISTS);
- rd->last_stored_value = NAN;
- }
-
- stored_entries++;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) {
- calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor;
- calculated_number t2 = unpack_storage_number(rd->values[current_entry]);
-
- calculated_number accuracy = accuracy_loss(t1, t2);
- debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)"
- , st->id, rd->name
- , current_entry
- , t2
- , get_storage_number_flags(rd->values[current_entry])
- , t1
- , accuracy
- , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
- );
-
- rd->collected_volume += t1;
- rd->stored_volume += t2;
-
- accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume);
- debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s"
- , st->id, rd->name
- , current_entry
- , rd->stored_volume
- , rd->collected_volume
- , accuracy
- , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
- );
- }
- #endif
- }
- // reset the storage flags for the next point, if any;
- storage_flags = SN_EXISTS;
-
- counter++;
- current_entry = ((current_entry + 1) >= st->entries) ? 0 : current_entry + 1;
- last_stored_ut = next_store_ut;
- }
-
- st->counter = counter;
- st->current_entry = current_entry;
-
- if(likely(last_ut)) {
- st->last_updated.tv_sec = (time_t) (last_ut / USEC_PER_SEC);
- st->last_updated.tv_usec = 0;
- }
-
- return stored_entries;
-}
-
-static inline void rrdset_done_fill_the_gap(RRDSET *st) {
- usec_t update_every_ut = st->update_every * USEC_PER_SEC;
- usec_t now_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
-
- long c = 0, entries = st->entries;
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- usec_t next_store_ut = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC;
- long current_entry = st->current_entry;
-
- for(c = 0; c < entries && next_store_ut <= now_collect_ut ; next_store_ut += update_every_ut, c++) {
- rd->values[current_entry] = SN_EMPTY_SLOT;
- current_entry = ((current_entry + 1) >= entries) ? 0 : current_entry + 1;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING (FILLED THE GAP)", rd->name, current_entry);
- #endif
- }
- }
-
- if(c > 0) {
- c--;
- st->last_updated.tv_sec += c * st->update_every;
-
- st->current_entry += c;
- if(st->current_entry >= st->entries)
- st->current_entry -= st->entries;
- }
-}
-
-void rrdset_done(RRDSET *st) {
- if(unlikely(netdata_exit)) return;
-
- if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) {
- if(unlikely(st->rrdhost->rrdpush_send_enabled))
- rrdset_done_push_exclusive(st);
-
- return;
- }
-
- debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name);
-
- RRDDIM *rd;
-
- char
- store_this_entry = 1, // boolean: 1 = store this entry, 0 = don't store this entry
- first_entry = 0; // boolean: 1 = this is the first entry seen for this chart, 0 = all other entries
-
- usec_t
- last_collect_ut, // the timestamp in microseconds, of the last collected value
- now_collect_ut, // the timestamp in microseconds, of this collected value (this is NOW)
- last_stored_ut, // the timestamp in microseconds, of the last stored entry in the db
- next_store_ut, // the timestamp in microseconds, of the next entry to store in the db
- update_every_ut = st->update_every * USEC_PER_SEC; // st->update_every in microseconds
-
- netdata_thread_disable_cancelability();
-
- // a read lock is OK here
- rrdset_rdlock(st);
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE))) {
- error("Chart '%s' has the OBSOLETE flag set, but it is collected.", st->id);
- rrdset_isnot_obsolete(st);
- }
-
- // check if the chart has a long time to be updated
- if(unlikely(st->usec_since_last_update > st->entries * update_every_ut)) {
- info("host '%s', chart %s: took too long to be updated (counter #%zu, update #%zu, %0.3" LONG_DOUBLE_MODIFIER " secs). Resetting it.", st->rrdhost->hostname, st->name, st->counter, st->counter_done, (LONG_DOUBLE)st->usec_since_last_update / USEC_PER_SEC);
- rrdset_reset(st);
- st->usec_since_last_update = update_every_ut;
- store_this_entry = 0;
- first_entry = 1;
- }
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "microseconds since last update: %llu", st->usec_since_last_update);
- #endif
-
- // set last_collected_time
- if(unlikely(!st->last_collected_time.tv_sec)) {
- // it is the first entry
- // set the last_collected_time to now
- last_collect_ut = rrdset_init_last_collected_time(st) - update_every_ut;
-
- // the first entry should not be stored
- store_this_entry = 0;
- first_entry = 1;
- }
- else {
- // it is not the first entry
- // calculate the proper last_collected_time, using usec_since_last_update
- last_collect_ut = rrdset_update_last_collected_time(st);
- }
-
- // if this set has not been updated in the past
- // we fake the last_update time to be = now - usec_since_last_update
- if(unlikely(!st->last_updated.tv_sec)) {
- // it has never been updated before
- // set a fake last_updated, in the past using usec_since_last_update
- rrdset_init_last_updated_time(st);
-
- // the first entry should not be stored
- store_this_entry = 0;
- first_entry = 1;
- }
-
- // check if we will re-write the entire data set
- if(unlikely(dt_usec(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) {
- info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Resetting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec);
- rrdset_reset(st);
- rrdset_init_last_updated_time(st);
-
- st->usec_since_last_update = update_every_ut;
-
- // the first entry should not be stored
- store_this_entry = 0;
- first_entry = 1;
- }
-
- // these are the 3 variables that will help us in interpolation
- // last_stored_ut = the last time we added a value to the storage
- // now_collect_ut = the time the current value has been collected
- // next_store_ut = the time of the next interpolation point
- now_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
- last_stored_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec;
- next_store_ut = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC;
-
- if(unlikely(!st->counter_done)) {
- // if we have not collected metrics this session (st->counter_done == 0)
- // and we have collected metrics for this chart in the past (st->counter != 0)
- // fill the gap (the chart has been just loaded from disk)
- if(unlikely(st->counter)) {
- rrdset_done_fill_the_gap(st);
- last_stored_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec;
- next_store_ut = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC;
- }
-
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_STORE_FIRST))) {
- store_this_entry = 1;
- last_collect_ut = next_store_ut - update_every_ut;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "Fixed first entry.");
- #endif
- }
- else {
- store_this_entry = 0;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "Will not store the next entry.");
- #endif
- }
- }
- st->counter_done++;
-
- if(unlikely(st->rrdhost->rrdpush_send_enabled))
- rrdset_done_push(st);
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "last_collect_ut = %0.3" LONG_DOUBLE_MODIFIER " (last collection time)", (LONG_DOUBLE)last_collect_ut/USEC_PER_SEC);
- rrdset_debug(st, "now_collect_ut = %0.3" LONG_DOUBLE_MODIFIER " (current collection time)", (LONG_DOUBLE)now_collect_ut/USEC_PER_SEC);
- rrdset_debug(st, "last_stored_ut = %0.3" LONG_DOUBLE_MODIFIER " (last updated time)", (LONG_DOUBLE)last_stored_ut/USEC_PER_SEC);
- rrdset_debug(st, "next_store_ut = %0.3" LONG_DOUBLE_MODIFIER " (next interpolation point)", (LONG_DOUBLE)next_store_ut/USEC_PER_SEC);
- #endif
-
- // calculate totals and count the dimensions
- int dimensions = 0;
- st->collected_total = 0;
- rrddim_foreach_read(rd, st) {
- dimensions++;
- if(likely(rd->updated))
- st->collected_total += rd->collected_value;
- }
-
- uint32_t storage_flags = SN_EXISTS;
-
- // process all dimensions to calculate their values
- // based on the collected figures only
- // at this stage we do not interpolate anything
- rrddim_foreach_read(rd, st) {
-
- if(unlikely(!rd->updated)) {
- rd->calculated_value = 0;
- continue;
- }
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: START "
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
- " collected_value = " COLLECTED_NUMBER_FORMAT
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
- " calculated_value = " CALCULATED_NUMBER_FORMAT
- , rd->name
- , rd->last_collected_value
- , rd->collected_value
- , rd->last_calculated_value
- , rd->calculated_value
- );
- #endif
-
- switch(rd->algorithm) {
- case RRD_ALGORITHM_ABSOLUTE:
- rd->calculated_value = (calculated_number)rd->collected_value
- * (calculated_number)rd->multiplier
- / (calculated_number)rd->divisor;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC ABS/ABS-NO-IN "
- CALCULATED_NUMBER_FORMAT " = "
- COLLECTED_NUMBER_FORMAT
- " * " CALCULATED_NUMBER_FORMAT
- " / " CALCULATED_NUMBER_FORMAT
- , rd->name
- , rd->calculated_value
- , rd->collected_value
- , (calculated_number)rd->multiplier
- , (calculated_number)rd->divisor
- );
- #endif
-
- break;
-
- case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL:
- if(unlikely(!st->collected_total))
- rd->calculated_value = 0;
- else
- // the percentage of the current value
- // over the total of all dimensions
- rd->calculated_value =
- (calculated_number)100
- * (calculated_number)rd->collected_value
- / (calculated_number)st->collected_total;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC PCENT-ROW "
- CALCULATED_NUMBER_FORMAT " = 100"
- " * " COLLECTED_NUMBER_FORMAT
- " / " COLLECTED_NUMBER_FORMAT
- , rd->name
- , rd->calculated_value
- , rd->collected_value
- , st->collected_total
- );
- #endif
-
- break;
-
- case RRD_ALGORITHM_INCREMENTAL:
- if(unlikely(rd->collections_counter <= 1)) {
- rd->calculated_value = 0;
- continue;
- }
-
- // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
- // to reset the calculation (it will give zero as the calculation for this second)
- if(unlikely(rd->last_collected_value > rd->collected_value)) {
- debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT
- , st->name, rd->name
- , rd->last_collected_value
- , rd->collected_value);
-
- if(!(rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)))
- storage_flags = SN_EXISTS_RESET;
-
- rd->last_collected_value = rd->collected_value;
- }
-
- rd->calculated_value +=
- (calculated_number)(rd->collected_value - rd->last_collected_value)
- * (calculated_number)rd->multiplier
- / (calculated_number)rd->divisor;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC INC PRE "
- CALCULATED_NUMBER_FORMAT " = ("
- COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT
- ")"
- " * " CALCULATED_NUMBER_FORMAT
- " / " CALCULATED_NUMBER_FORMAT
- , rd->name
- , rd->calculated_value
- , rd->collected_value, rd->last_collected_value
- , (calculated_number)rd->multiplier
- , (calculated_number)rd->divisor
- );
- #endif
-
- break;
-
- case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL:
- if(unlikely(rd->collections_counter <= 1)) {
- rd->calculated_value = 0;
- continue;
- }
-
- // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
- // to reset the calculation (it will give zero as the calculation for this second)
- if(unlikely(rd->last_collected_value > rd->collected_value)) {
- debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT
- , st->name, rd->name
- , rd->last_collected_value
- , rd->collected_value
- );
-
- if(!(rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)))
- storage_flags = SN_EXISTS_RESET;
-
- rd->last_collected_value = rd->collected_value;
- }
-
- // the percentage of the current increment
- // over the increment of all dimensions together
- if(unlikely(st->collected_total == st->last_collected_total))
- rd->calculated_value = 0;
- else
- rd->calculated_value =
- (calculated_number)100
- * (calculated_number)(rd->collected_value - rd->last_collected_value)
- / (calculated_number)(st->collected_total - st->last_collected_total);
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC PCENT-DIFF "
- CALCULATED_NUMBER_FORMAT " = 100"
- " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
- " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
- , rd->name
- , rd->calculated_value
- , rd->collected_value, rd->last_collected_value
- , st->collected_total, st->last_collected_total
- );
- #endif
-
- break;
-
- default:
- // make the default zero, to make sure
- // it gets noticed when we add new types
- rd->calculated_value = 0;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: CALC "
- CALCULATED_NUMBER_FORMAT " = 0"
- , rd->name
- , rd->calculated_value
- );
- #endif
-
- break;
- }
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: PHASE2 "
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
- " collected_value = " COLLECTED_NUMBER_FORMAT
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
- " calculated_value = " CALCULATED_NUMBER_FORMAT
- , rd->name
- , rd->last_collected_value
- , rd->collected_value
- , rd->last_calculated_value
- , rd->calculated_value
- );
- #endif
-
- }
-
- // at this point we have all the calculated values ready
- // it is now time to interpolate values on a second boundary
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(now_collect_ut < next_store_ut)) {
- // this is collected in the same interpolation point
- rrdset_debug(st, "THIS IS IN THE SAME INTERPOLATION POINT");
- info("INTERNAL CHECK: host '%s', chart '%s' is collected in the same interpolation point: short by %llu microseconds", st->rrdhost->hostname, st->name, next_store_ut - now_collect_ut);
- }
-#endif
-
- rrdset_done_interpolate(st
- , update_every_ut
- , last_stored_ut
- , next_store_ut
- , last_collect_ut
- , now_collect_ut
- , store_this_entry
- , storage_flags
- );
-
- st->last_collected_total = st->collected_total;
-
- rrddim_foreach_read(rd, st) {
- if(unlikely(!rd->updated))
- continue;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", rd->name, rd->last_collected_value, rd->collected_value);
- #endif
-
- rd->last_collected_value = rd->collected_value;
-
- switch(rd->algorithm) {
- case RRD_ALGORITHM_INCREMENTAL:
- if(unlikely(!first_entry)) {
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", rd->name, rd->last_calculated_value + rd->calculated_value, rd->calculated_value);
- #endif
-
- rd->last_calculated_value += rd->calculated_value;
- }
- else {
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "THIS IS THE FIRST POINT");
- #endif
- }
- break;
-
- case RRD_ALGORITHM_ABSOLUTE:
- case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL:
- case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL:
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", rd->name, rd->last_calculated_value, rd->calculated_value);
- #endif
-
- rd->last_calculated_value = rd->calculated_value;
- break;
- }
-
- rd->calculated_value = 0;
- rd->collected_value = 0;
- rd->updated = 0;
-
- #ifdef NETDATA_INTERNAL_CHECKS
- rrdset_debug(st, "%s: END "
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
- " collected_value = " COLLECTED_NUMBER_FORMAT
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
- " calculated_value = " CALCULATED_NUMBER_FORMAT
- , rd->name
- , rd->last_collected_value
- , rd->collected_value
- , rd->last_calculated_value
- , rd->calculated_value
- );
- #endif
-
- }
-
- // ALL DONE ABOUT THE DATA UPDATE
- // --------------------------------------------------------------------
-
-/*
- // find if there are any obsolete dimensions (not updated recently)
- if(unlikely(rrd_delete_unupdated_dimensions)) {
-
- for( rd = st->dimensions; likely(rd) ; rd = rd->next )
- if((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)
- break;
-
- if(unlikely(rd)) {
- RRDDIM *last;
- // there is dimension to free
- // upgrade our read lock to a write lock
- 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
-
- if(unlikely((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)) {
- info("Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id);
-
- if(unlikely(!last)) {
- st->dimensions = rd->next;
- rd->next = NULL;
- rrddim_free(st, rd);
- rd = st->dimensions;
- continue;
- }
- else {
- last->next = rd->next;
- rd->next = NULL;
- rrddim_free(st, rd);
- rd = last->next;
- continue;
- }
- }
-
- last = rd;
- rd = rd->next;
- }
-
- if(unlikely(!st->dimensions)) {
- info("Disabling chart %s (%s) since it does not have any dimensions", st->name, st->id);
- st->enabled = 0;
- }
- }
- }
-*/
-
- rrdset_unlock(st);
-
- netdata_thread_enable_cancelability();
-}
diff --git a/src/rrdsetvar.c b/src/rrdsetvar.c
deleted file mode 100644
index aec57efa9..000000000
--- a/src/rrdsetvar.c
+++ /dev/null
@@ -1,183 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDSETVAR management
-// CHART VARIABLES
-
-static inline void rrdsetvar_free_variables(RRDSETVAR *rs) {
- RRDSET *st = rs->rrdset;
- RRDHOST *host = st->rrdhost;
-
- // ------------------------------------------------------------------------
- // CHART
- rrdvar_free(host, &st->rrdvar_root_index, rs->var_local);
- rs->var_local = NULL;
-
- // ------------------------------------------------------------------------
- // FAMILY
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rs->var_family);
- rs->var_family = NULL;
-
- rrdvar_free(host, &st->rrdfamily->rrdvar_root_index, rs->var_family_name);
- rs->var_family_name = NULL;
-
- // ------------------------------------------------------------------------
- // HOST
- rrdvar_free(host, &host->rrdvar_root_index, rs->var_host);
- rs->var_host = NULL;
-
- rrdvar_free(host, &host->rrdvar_root_index, rs->var_host_name);
- rs->var_host_name = NULL;
-
- // ------------------------------------------------------------------------
- // KEYS
- freez(rs->key_fullid);
- rs->key_fullid = NULL;
-
- freez(rs->key_fullname);
- rs->key_fullname = NULL;
-}
-
-static inline void rrdsetvar_create_variables(RRDSETVAR *rs) {
- RRDSET *st = rs->rrdset;
- RRDHOST *host = st->rrdhost;
-
- // ------------------------------------------------------------------------
- // free the old ones (if any)
-
- rrdsetvar_free_variables(rs);
-
- // ------------------------------------------------------------------------
- // KEYS
-
- char buffer[RRDVAR_MAX_LENGTH + 1];
- snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rs->variable);
- rs->key_fullid = strdupz(buffer);
-
- snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable);
- rs->key_fullname = strdupz(buffer);
-
- // ------------------------------------------------------------------------
- // CHART
- rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, rs->value);
-
- // ------------------------------------------------------------------------
- // FAMILY
- rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
- rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
-
- // ------------------------------------------------------------------------
- // HOST
- rs->var_host = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
- rs->var_host_name = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
-}
-
-RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options) {
- debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable);
- RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR));
-
- rs->variable = strdupz(variable);
- rs->hash = simple_hash(rs->variable);
- rs->type = type;
- rs->value = value;
- rs->options = options;
- rs->rrdset = st;
-
- rs->next = st->variables;
- st->variables = rs;
-
- rrdsetvar_create_variables(rs);
-
- return rs;
-}
-
-void rrdsetvar_rename_all(RRDSET *st) {
- debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name);
-
- RRDSETVAR *rs;
- for(rs = st->variables; rs ; rs = rs->next)
- rrdsetvar_create_variables(rs);
-
- rrdsetcalc_link_matching(st);
-}
-
-void rrdsetvar_free(RRDSETVAR *rs) {
- RRDSET *st = rs->rrdset;
- debug(D_VARIABLES, "RRDSETVAR free for chart id '%s' name '%s', variable '%s'", st->id, st->name, rs->variable);
-
- if(st->variables == rs) {
- st->variables = rs->next;
- }
- else {
- RRDSETVAR *t;
- for (t = st->variables; t && t->next != rs; t = t->next);
- if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->key_fullname, st->id);
- else t->next = rs->next;
- }
-
- rrdsetvar_free_variables(rs);
-
- freez(rs->variable);
-
- if(rs->options & RRDVAR_OPTION_ALLOCATED)
- freez(rs->value);
-
- freez(rs);
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// custom chart variables
-
-RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) {
- RRDHOST *host = st->rrdhost;
-
- char *n = strdupz(name);
- rrdvar_fix_name(n);
- uint32_t hash = simple_hash(n);
-
- rrdset_wrlock(st);
-
- // find it
- RRDSETVAR *rs;
- for(rs = st->variables; rs ; rs = rs->next) {
- if(hash == rs->hash && strcmp(n, rs->variable) == 0) {
- rrdset_unlock(st);
- if(rs->options & RRDVAR_OPTION_ALLOCATED) {
- free(n);
- return rs;
- }
- else {
- error("RRDSETVAR: custom variable '%s' on chart '%s' of host '%s', conflicts with an internal chart variable", n, st->id, host->hostname);
- free(n);
- return NULL;
- }
- }
- }
-
- // not found, allocate one
-
- calculated_number *v = mallocz(sizeof(calculated_number));
- *v = NAN;
-
- rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED);
- rrdset_unlock(st);
-
- free(n);
- return rs;
-}
-
-void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, calculated_number value) {
- if(unlikely(!(rs->options & RRDVAR_OPTION_ALLOCATED))) {
- error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value);
- }
- else {
- calculated_number *v = rs->value;
- if(*v != value) {
- *v = value;
-
- // mark the chart to be sent upstream
- rrdset_flag_clear(rs->rrdset, RRDSET_FLAG_EXPOSED_UPSTREAM);
- }
- }
-}
diff --git a/src/rrdvar.c b/src/rrdvar.c
deleted file mode 100644
index 6936c36f1..000000000
--- a/src/rrdvar.c
+++ /dev/null
@@ -1,275 +0,0 @@
-#define NETDATA_HEALTH_INTERNALS
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// RRDVAR management
-
-inline int rrdvar_fix_name(char *variable) {
- int fixed = 0;
- while(*variable) {
- if (!isalnum(*variable) && *variable != '.' && *variable != '_') {
- *variable++ = '_';
- fixed++;
- }
- else
- variable++;
- }
-
- return fixed;
-}
-
-int rrdvar_compare(void* a, void* b) {
- if(((RRDVAR *)a)->hash < ((RRDVAR *)b)->hash) return -1;
- else if(((RRDVAR *)a)->hash > ((RRDVAR *)b)->hash) return 1;
- else return strcmp(((RRDVAR *)a)->name, ((RRDVAR *)b)->name);
-}
-
-static inline RRDVAR *rrdvar_index_add(avl_tree_lock *tree, RRDVAR *rv) {
- RRDVAR *ret = (RRDVAR *)avl_insert_lock(tree, (avl *)(rv));
- if(ret != rv)
- debug(D_VARIABLES, "Request to insert RRDVAR '%s' into index failed. Already exists.", rv->name);
-
- return ret;
-}
-
-static inline RRDVAR *rrdvar_index_del(avl_tree_lock *tree, RRDVAR *rv) {
- RRDVAR *ret = (RRDVAR *)avl_remove_lock(tree, (avl *)(rv));
- if(!ret)
- error("Request to remove RRDVAR '%s' from index failed. Not Found.", rv->name);
-
- return ret;
-}
-
-static inline RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) {
- RRDVAR tmp;
- tmp.name = (char *)name;
- tmp.hash = (hash)?hash:simple_hash(tmp.name);
-
- return (RRDVAR *)avl_search_lock(tree, (avl *)&tmp);
-}
-
-inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) {
- (void)host;
-
- if(!rv) return;
-
- if(tree) {
- debug(D_VARIABLES, "Deleting variable '%s'", rv->name);
- if(unlikely(!rrdvar_index_del(tree, rv)))
- error("RRDVAR: Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname);
- }
-
- if(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)
- freez(rv->value);
-
- freez(rv->name);
- freez(rv);
-}
-
-inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value) {
- char *variable = strdupz(name);
- rrdvar_fix_name(variable);
- uint32_t hash = simple_hash(variable);
-
- RRDVAR *rv = rrdvar_index_find(tree, variable, hash);
- if(unlikely(!rv)) {
- debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", variable, scope);
-
- rv = callocz(1, sizeof(RRDVAR));
- rv->name = variable;
- rv->hash = hash;
- rv->type = type;
- rv->value = value;
-
- RRDVAR *ret = rrdvar_index_add(tree, rv);
- if(unlikely(ret != rv)) {
- debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", variable, scope);
- freez(rv);
- freez(variable);
- rv = NULL;
- }
- else
- debug(D_VARIABLES, "Variable '%s' created in scope '%s'", variable, scope);
- }
- else {
- debug(D_VARIABLES, "Variable '%s' is already found in scope '%s'.", variable, scope);
-
- // already exists
- freez(variable);
-
- // this is important
- // it must return NULL - not the existing variable - or double-free will happen
- rv = NULL;
- }
-
- return rv;
-}
-
-void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock) {
- // FIXME: this is not bullet proof - avl should support some means to destroy it
- // with a callback for each item already in the index
-
- RRDVAR *rv, *last = NULL;
- while((rv = (RRDVAR *)tree_lock->avl_tree.root)) {
- if(unlikely(rv == last)) {
- error("RRDVAR: INTERNAL ERROR: Cannot cleanup tree of RRDVARs");
- break;
- }
- last = rv;
- rrdvar_free(host, tree_lock, rv);
- }
-}
-
-// ----------------------------------------------------------------------------
-// CUSTOM HOST VARIABLES
-
-inline int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data) {
- return avl_traverse_lock(&host->rrdvar_root_index, callback, data);
-}
-
-static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *tree_lock, const char *name) {
- calculated_number *v = callocz(1, sizeof(calculated_number));
- *v = NAN;
-
- RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v);
- if(unlikely(!rv)) {
- free(v);
- debug(D_VARIABLES, "Requested variable '%s' already exists - possibly 2 plugins are updating it at the same time.", name);
-
- char *variable = strdupz(name);
- rrdvar_fix_name(variable);
- uint32_t hash = simple_hash(variable);
-
- rv = rrdvar_index_find(tree_lock, variable, hash);
-
- freez(variable);
- }
-
- return rv;
-}
-
-RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) {
- return rrdvar_custom_variable_create("host", &host->rrdvar_root_index, name);
-}
-
-void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value) {
- if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED)
- error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value);
- else {
- calculated_number *v = rv->value;
- if(*v != value) {
- *v = value;
-
- // if the host is streaming, send this variable upstream immediately
- rrdpush_sender_send_this_host_variable_now(host, rv);
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-// RRDVAR lookup
-
-static calculated_number rrdvar2number(RRDVAR *rv) {
- switch(rv->type) {
- case RRDVAR_TYPE_CALCULATED_ALLOCATED:
- case RRDVAR_TYPE_CALCULATED: {
- calculated_number *n = (calculated_number *)rv->value;
- return *n;
- }
-
- case RRDVAR_TYPE_TIME_T: {
- time_t *n = (time_t *)rv->value;
- return *n;
- }
-
- case RRDVAR_TYPE_COLLECTED: {
- collected_number *n = (collected_number *)rv->value;
- return *n;
- }
-
- case RRDVAR_TYPE_TOTAL: {
- total_number *n = (total_number *)rv->value;
- return *n;
- }
-
- case RRDVAR_TYPE_INT: {
- int *n = (int *)rv->value;
- return *n;
- }
-
- default:
- error("I don't know how to convert RRDVAR type %u to calculated_number", rv->type);
- return NAN;
- }
-}
-
-int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) {
- RRDSET *st = rc->rrdset;
- if(!st) return 0;
-
- RRDHOST *host = st->rrdhost;
- RRDVAR *rv;
-
- rv = rrdvar_index_find(&st->rrdvar_root_index, variable, hash);
- if(rv) {
- *result = rrdvar2number(rv);
- return 1;
- }
-
- rv = rrdvar_index_find(&st->rrdfamily->rrdvar_root_index, variable, hash);
- if(rv) {
- *result = rrdvar2number(rv);
- return 1;
- }
-
- rv = rrdvar_index_find(&host->rrdvar_root_index, variable, hash);
- if(rv) {
- *result = rrdvar2number(rv);
- return 1;
- }
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// RRDVAR to JSON
-
-struct variable2json_helper {
- BUFFER *buf;
- size_t counter;
-};
-
-static int single_variable2json(void *entry, void *data) {
- struct variable2json_helper *helper = (struct variable2json_helper *)data;
- RRDVAR *rv = (RRDVAR *)entry;
- calculated_number value = rrdvar2number(rv);
-
- if(unlikely(isnan(value) || isinf(value)))
- buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": null", helper->counter?",":"", rv->name);
- else
- buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": %0.5" LONG_DOUBLE_MODIFIER, helper->counter?",":"", rv->name, (LONG_DOUBLE)value);
-
- helper->counter++;
-
- return 0;
-}
-
-void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) {
- RRDHOST *host = st->rrdhost;
-
- struct variable2json_helper helper = {
- .buf = buf,
- .counter = 0
- };
-
- buffer_sprintf(buf, "{\n\t\"chart\": \"%s\",\n\t\"chart_name\": \"%s\",\n\t\"chart_context\": \"%s\",\n\t\"chart_variables\": {", st->id, st->name, st->context);
- avl_traverse_lock(&st->rrdvar_root_index, single_variable2json, (void *)&helper);
- buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family);
- helper.counter = 0;
- avl_traverse_lock(&st->rrdfamily->rrdvar_root_index, single_variable2json, (void *)&helper);
- buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", host->hostname);
- helper.counter = 0;
- avl_traverse_lock(&host->rrdvar_root_index, single_variable2json, (void *)&helper);
- buffer_strcat(buf, "\n\t}\n}\n");
-}
-
diff --git a/src/signals.c b/src/signals.c
deleted file mode 100644
index 331e80358..000000000
--- a/src/signals.c
+++ /dev/null
@@ -1,168 +0,0 @@
-#include "common.h"
-
-typedef enum signal_action {
- NETDATA_SIGNAL_END_OF_LIST,
- NETDATA_SIGNAL_IGNORE,
- NETDATA_SIGNAL_EXIT_CLEANLY,
- NETDATA_SIGNAL_SAVE_DATABASE,
- NETDATA_SIGNAL_LOG_ROTATE,
- NETDATA_SIGNAL_RELOAD_HEALTH,
- NETDATA_SIGNAL_FATAL,
-} SIGNAL_ACTION;
-
-static struct {
- int signo; // the signal
- const char *name; // the name of the signal
- size_t count; // the number of signals received
- SIGNAL_ACTION action; // the action to take
-} signals_waiting[] = {
- { SIGPIPE, "SIGPIPE", 0, NETDATA_SIGNAL_IGNORE },
- { SIGINT , "SIGINT", 0, NETDATA_SIGNAL_EXIT_CLEANLY },
- { SIGQUIT, "SIGQUIT", 0, NETDATA_SIGNAL_EXIT_CLEANLY },
- { SIGTERM, "SIGTERM", 0, NETDATA_SIGNAL_EXIT_CLEANLY },
- { SIGHUP, "SIGHUP", 0, NETDATA_SIGNAL_LOG_ROTATE },
- { SIGUSR1, "SIGUSR1", 0, NETDATA_SIGNAL_SAVE_DATABASE },
- { SIGUSR2, "SIGUSR2", 0, NETDATA_SIGNAL_RELOAD_HEALTH },
- { SIGBUS, "SIGBUS", 0, NETDATA_SIGNAL_FATAL },
-
- // terminator
- { 0, "NONE", 0, NETDATA_SIGNAL_END_OF_LIST }
-};
-
-static void signal_handler(int signo) {
- // find the entry in the list
- int i;
- for(i = 0; signals_waiting[i].action != NETDATA_SIGNAL_END_OF_LIST ; i++) {
- if(unlikely(signals_waiting[i].signo == signo)) {
- signals_waiting[i].count++;
-
- if(signals_waiting[i].action == NETDATA_SIGNAL_FATAL) {
- char buffer[200 + 1];
- snprintfz(buffer, 200, "\nSIGNAL HANLDER: received: %s. Oops! This is bad!\n", signals_waiting[i].name);
- if(write(STDERR_FILENO, buffer, strlen(buffer)) == -1) {
- // nothing to do - we cannot write but there is no way to complaint about it
- ;
- }
- }
-
- return;
- }
- }
-}
-
-void signals_block(void) {
- sigset_t sigset;
- sigfillset(&sigset);
-
- if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1)
- error("SIGNAL: Could not block signals for threads");
-}
-
-void signals_unblock(void) {
- sigset_t sigset;
- sigfillset(&sigset);
-
- if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) {
- error("SIGNAL: Could not unblock signals for threads");
- }
-}
-
-void signals_init(void) {
- // Catch signals which we want to use
- struct sigaction sa;
- sa.sa_flags = 0;
-
- // ignore all signals while we run in a signal handler
- sigfillset(&sa.sa_mask);
-
- int i;
- for (i = 0; signals_waiting[i].action != NETDATA_SIGNAL_END_OF_LIST; i++) {
- if(signals_waiting[i].action == NETDATA_SIGNAL_IGNORE)
- sa.sa_handler = SIG_IGN;
- else
- sa.sa_handler = signal_handler;
-
- if(sigaction(signals_waiting[i].signo, &sa, NULL) == -1)
- error("SIGNAL: Failed to change signal handler for: %s", signals_waiting[i].name);
- }
-}
-
-void signals_reset(void) {
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = 0;
-
- int i;
- for (i = 0; signals_waiting[i].action != NETDATA_SIGNAL_END_OF_LIST; i++) {
- if(sigaction(signals_waiting[i].signo, &sa, NULL) == -1)
- error("SIGNAL: Failed to reset signal handler for: %s", signals_waiting[i].name);
- }
-}
-
-void signals_handle(void) {
- while(1) {
-
- // pause() causes the calling process (or thread) to sleep until a signal
- // is delivered that either terminates the process or causes the invocation
- // of a signal-catching function.
- if(pause() == -1 && errno == EINTR) {
-
- // loop once, but keep looping while signals are coming in
- // this is needed because a few operations may take some time
- // so we need to check for new signals before pausing again
- int found = 1;
- while(found) {
- found = 0;
-
- // execute the actions of the signals
- int i;
- for (i = 0; signals_waiting[i].action != NETDATA_SIGNAL_END_OF_LIST; i++) {
- if (signals_waiting[i].count) {
- found = 1;
- signals_waiting[i].count = 0;
- const char *name = signals_waiting[i].name;
-
- switch (signals_waiting[i].action) {
- case NETDATA_SIGNAL_RELOAD_HEALTH:
- error_log_limit_unlimited();
- info("SIGNAL: Received %s. Reloading HEALTH configuration...", name);
- health_reload();
- error_log_limit_reset();
- break;
-
- case NETDATA_SIGNAL_SAVE_DATABASE:
- error_log_limit_unlimited();
- info("SIGNAL: Received %s. Saving databases...", name);
- rrdhost_save_all();
- info("Databases saved.");
- error_log_limit_reset();
- break;
-
- case NETDATA_SIGNAL_LOG_ROTATE:
- error_log_limit_unlimited();
- info("SIGNAL: Received %s. Reopening all log files...", name);
- reopen_all_log_files();
- error_log_limit_reset();
- break;
-
- case NETDATA_SIGNAL_EXIT_CLEANLY:
- info("SIGNAL: Received %s. Cleaning up to exit...", name);
- netdata_cleanup_and_exit(0);
- exit(0);
-
- case NETDATA_SIGNAL_FATAL:
- fatal("SIGNAL: Received %s. netdata now exits.", name);
-
- default:
- info("SIGNAL: Received %s. No signal handler configured. Ignoring it.", name);
- break;
- }
- }
- }
- }
- }
- else
- error("SIGNAL: pause() returned but it was not interrupted by a signal.");
- }
-}
diff --git a/src/signals.h b/src/signals.h
deleted file mode 100644
index 2fdd36552..000000000
--- a/src/signals.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef NETDATA_SIGNALS_H
-#define NETDATA_SIGNALS_H
-
-extern void signals_init(void);
-extern void signals_block(void);
-extern void signals_unblock(void);
-extern void signals_reset(void);
-extern void signals_handle(void) NORETURN;
-
-#endif //NETDATA_SIGNALS_H
diff --git a/src/simple_pattern.c b/src/simple_pattern.c
deleted file mode 100644
index 747b5150a..000000000
--- a/src/simple_pattern.c
+++ /dev/null
@@ -1,260 +0,0 @@
-#include "common.h"
-
-struct simple_pattern {
- const char *match;
- size_t len;
-
- SIMPLE_PREFIX_MODE mode;
- char negative;
-
- struct simple_pattern *child;
-
- struct simple_pattern *next;
-};
-
-static inline struct simple_pattern *parse_pattern(char *str, SIMPLE_PREFIX_MODE default_mode) {
- // fprintf(stderr, "PARSING PATTERN: '%s'\n", str);
-
- SIMPLE_PREFIX_MODE mode;
- struct simple_pattern *child = NULL;
-
- char *s = str, *c = str;
-
- // skip asterisks in front
- while(*c == '*') c++;
-
- // find the next asterisk
- while(*c && *c != '*') c++;
-
- // do we have an asterisk in the middle?
- if(*c == '*' && c[1] != '\0') {
- // yes, we have
- child = parse_pattern(c, default_mode);
- c[1] = '\0';
- }
-
- // check what this one matches
-
- size_t len = strlen(s);
- if(len >= 2 && *s == '*' && s[len - 1] == '*') {
- s[len - 1] = '\0';
- s++;
- mode = SIMPLE_PATTERN_SUBSTRING;
- }
- else if(len >= 1 && *s == '*') {
- s++;
- mode = SIMPLE_PATTERN_SUFFIX;
- }
- else if(len >= 1 && s[len - 1] == '*') {
- s[len - 1] = '\0';
- mode = SIMPLE_PATTERN_PREFIX;
- }
- else
- mode = default_mode;
-
- // allocate the structure
- struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
- if(*s) {
- m->match = strdupz(s);
- m->len = strlen(m->match);
- m->mode = mode;
- }
- else {
- m->mode = SIMPLE_PATTERN_SUBSTRING;
- }
-
- m->child = child;
-
- return m;
-}
-
-SIMPLE_PATTERN *simple_pattern_create(const char *list, const char *separators, SIMPLE_PREFIX_MODE default_mode) {
- struct simple_pattern *root = NULL, *last = NULL;
-
- if(unlikely(!list || !*list)) return root;
-
- int isseparator[256] = {
- [' '] = 1 // space
- , ['\t'] = 1 // tab
- , ['\r'] = 1 // carriage return
- , ['\n'] = 1 // new line
- , ['\f'] = 1 // form feed
- , ['\v'] = 1 // vertical tab
- };
-
- if (unlikely(separators && *separators)) {
- memset(&isseparator[0], 0, sizeof(isseparator));
- while(*separators) isseparator[(unsigned char)*separators++] = 1;
- }
-
- char *buf = mallocz(strlen(list) + 1);
- const char *s = list;
-
- while(s && *s) {
- buf[0] = '\0';
- char *c = buf;
-
- char negative = 0;
-
- // skip all spaces
- while(isseparator[(unsigned char)*s])
- s++;
-
- if(*s == '!') {
- negative = 1;
- s++;
- }
-
- // empty string
- if(unlikely(!*s))
- break;
-
- // find the next space
- char escape = 0;
- while(*s) {
- if(*s == '\\' && !escape) {
- escape = 1;
- s++;
- }
- else {
- if (isseparator[(unsigned char)*s] && !escape) {
- s++;
- break;
- }
-
- *c++ = *s++;
- escape = 0;
- }
- }
-
- // terminate our string
- *c = '\0';
-
- // if we matched the empty string, skip it
- if(unlikely(!*buf))
- continue;
-
- // fprintf(stderr, "FOUND PATTERN: '%s'\n", buf);
- struct simple_pattern *m = parse_pattern(buf, default_mode);
- m->negative = negative;
-
- // link it at the end
- if(unlikely(!root))
- root = last = m;
- else {
- last->next = m;
- last = m;
- }
- }
-
- freez(buf);
- return (SIMPLE_PATTERN *)root;
-}
-
-static inline char *add_wildcarded(const char *matched, size_t matched_size, char *wildcarded, size_t *wildcarded_size) {
- //if(matched_size) {
- // char buf[matched_size + 1];
- // strncpyz(buf, matched, matched_size);
- // fprintf(stderr, "ADD WILDCARDED '%s' of length %zu\n", buf, matched_size);
- //}
-
- if(unlikely(wildcarded && *wildcarded_size && matched && *matched && matched_size)) {
- size_t wss = *wildcarded_size - 1;
- size_t len = (matched_size < wss)?matched_size:wss;
- if(likely(len)) {
- strncpyz(wildcarded, matched, len);
-
- *wildcarded_size -= len;
- return &wildcarded[len];
- }
- }
-
- return wildcarded;
-}
-
-static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len, char *wildcarded, size_t *wildcarded_size) {
- char *s;
-
- if(m->len <= len) {
- switch(m->mode) {
- case SIMPLE_PATTERN_SUBSTRING:
- if(!m->len) return 1;
- if((s = strstr(str, m->match))) {
- wildcarded = add_wildcarded(str, s - str, wildcarded, wildcarded_size);
- if(!m->child) {
- wildcarded = add_wildcarded(&s[m->len], len - (&s[m->len] - str), wildcarded, wildcarded_size);
- return 1;
- }
- return match_pattern(m->child, &s[m->len], len - (s - str) - m->len, wildcarded, wildcarded_size);
- }
- break;
-
- case SIMPLE_PATTERN_PREFIX:
- if(unlikely(strncmp(str, m->match, m->len) == 0)) {
- if(!m->child) {
- wildcarded = add_wildcarded(&str[m->len], len - m->len, wildcarded, wildcarded_size);
- return 1;
- }
- return match_pattern(m->child, &str[m->len], len - m->len, wildcarded, wildcarded_size);
- }
- break;
-
- case SIMPLE_PATTERN_SUFFIX:
- if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
- wildcarded = add_wildcarded(str, len - m->len, wildcarded, wildcarded_size);
- if(!m->child) return 1;
- return 0;
- }
- break;
-
- case SIMPLE_PATTERN_EXACT:
- default:
- if(unlikely(strcmp(str, m->match) == 0)) {
- if(!m->child) return 1;
- return 0;
- }
- break;
- }
- }
-
- return 0;
-}
-
-int simple_pattern_matches_extract(SIMPLE_PATTERN *list, const char *str, char *wildcarded, size_t wildcarded_size) {
- struct simple_pattern *m, *root = (struct simple_pattern *)list;
-
- if(unlikely(!root || !str || !*str)) return 0;
-
- size_t len = strlen(str);
- for(m = root; m ; m = m->next) {
- char *ws = wildcarded;
- size_t wss = wildcarded_size;
- if(unlikely(ws)) *ws = '\0';
-
- if (match_pattern(m, str, len, ws, &wss)) {
-
- //if(ws && wss)
- // fprintf(stderr, "FINAL WILDCARDED '%s' of length %zu\n", ws, strlen(ws));
-
- if (m->negative) return 0;
- return 1;
- }
- }
-
- return 0;
-}
-
-static inline void free_pattern(struct simple_pattern *m) {
- if(!m) return;
-
- free_pattern(m->child);
- free_pattern(m->next);
- freez((void *)m->match);
- freez(m);
-}
-
-void simple_pattern_free(SIMPLE_PATTERN *list) {
- if(!list) return;
-
- free_pattern(((struct simple_pattern *)list));
-}
diff --git a/src/simple_pattern.h b/src/simple_pattern.h
deleted file mode 100644
index d0b75af7e..000000000
--- a/src/simple_pattern.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef NETDATA_SIMPLE_PATTERN_H
-#define NETDATA_SIMPLE_PATTERN_H
-
-typedef enum {
- SIMPLE_PATTERN_EXACT,
- SIMPLE_PATTERN_PREFIX,
- SIMPLE_PATTERN_SUFFIX,
- SIMPLE_PATTERN_SUBSTRING
-} SIMPLE_PREFIX_MODE;
-
-typedef void SIMPLE_PATTERN;
-
-// create a simple_pattern from the string given
-// default_mode is used in cases where EXACT matches, without an asterisk,
-// should be considered PREFIX matches.
-extern SIMPLE_PATTERN *simple_pattern_create(const char *list, const char *separators, SIMPLE_PREFIX_MODE default_mode);
-
-// test if string str is matched from the pattern and fill 'wildcarded' with the parts matched by '*'
-extern int simple_pattern_matches_extract(SIMPLE_PATTERN *list, const char *str, char *wildcarded, size_t wildcarded_size);
-
-// test if string str is matched from the pattern
-#define simple_pattern_matches(list, str) simple_pattern_matches_extract(list, str, NULL, 0)
-
-// free a simple_pattern that was created with simple_pattern_create()
-// list can be NULL, in which case, this does nothing.
-extern void simple_pattern_free(SIMPLE_PATTERN *list);
-
-#endif //NETDATA_SIMPLE_PATTERN_H
diff --git a/src/socket.c b/src/socket.c
deleted file mode 100644
index 8bede73fd..000000000
--- a/src/socket.c
+++ /dev/null
@@ -1,1518 +0,0 @@
-#include "common.h"
-
-// --------------------------------------------------------------------------------------------------------------------
-// various library calls
-
-#ifdef __gnu_linux__
-#define LARGE_SOCK_SIZE 33554431 // don't ask why - I found it at brubeck source - I guess it is just a large number
-#else
-#define LARGE_SOCK_SIZE 4096
-#endif
-
-int sock_setnonblock(int fd) {
- int flags;
-
- flags = fcntl(fd, F_GETFL);
- flags |= O_NONBLOCK;
-
- int ret = fcntl(fd, F_SETFL, flags);
- if(ret < 0)
- error("Failed to set O_NONBLOCK on socket %d", fd);
-
- return ret;
-}
-
-int sock_delnonblock(int fd) {
- int flags;
-
- flags = fcntl(fd, F_GETFL);
- flags &= ~O_NONBLOCK;
-
- int ret = fcntl(fd, F_SETFL, flags);
- if(ret < 0)
- error("Failed to remove O_NONBLOCK on socket %d", fd);
-
- return ret;
-}
-
-int sock_setreuse(int fd, int reuse) {
- int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
-
- if(ret == -1)
- error("Failed to set SO_REUSEADDR on socket %d", fd);
-
- return ret;
-}
-
-int sock_setreuse_port(int fd, int reuse) {
- int ret = -1;
-
-#ifdef SO_REUSEPORT
- ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse));
- if(ret == -1 && errno != ENOPROTOOPT)
- error("failed to set SO_REUSEPORT on socket %d", fd);
-#endif
-
- return ret;
-}
-
-int sock_enlarge_in(int fd) {
- int ret, bs = LARGE_SOCK_SIZE;
-
- ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bs, sizeof(bs));
-
- if(ret == -1)
- error("Failed to set SO_RCVBUF on socket %d", fd);
-
- return ret;
-}
-
-int sock_enlarge_out(int fd) {
- int ret, bs = LARGE_SOCK_SIZE;
- ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bs, sizeof(bs));
-
- if(ret == -1)
- error("Failed to set SO_SNDBUF on socket %d", fd);
-
- return ret;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-
-char *strdup_client_description(int family, const char *protocol, const char *ip, int port) {
- char buffer[100 + 1];
-
- switch(family) {
- case AF_INET:
- snprintfz(buffer, 100, "%s:%s:%d", protocol, ip, port);
- break;
-
- case AF_INET6:
- default:
- snprintfz(buffer, 100, "%s:[%s]:%d", protocol, ip, port);
- break;
-
- case AF_UNIX:
- snprintfz(buffer, 100, "%s:%s", protocol, ip);
- break;
- }
-
- return strdupz(buffer);
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// listening sockets
-
-int create_listen_socket_unix(const char *path, int listen_backlog) {
- int sock;
-
- debug(D_LISTENER, "LISTENER: UNIX creating new listening socket on path '%s'", path);
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if(sock < 0) {
- error("LISTENER: UNIX socket() on path '%s' failed.", path);
- return -1;
- }
-
- sock_setnonblock(sock);
- sock_enlarge_in(sock);
-
- struct sockaddr_un name;
- memset(&name, 0, sizeof(struct sockaddr_un));
- name.sun_family = AF_UNIX;
- strncpy(name.sun_path, path, sizeof(name.sun_path)-1);
-
- errno = 0;
- if (unlink(path) == -1 && errno != ENOENT)
- error("LISTENER: failed to remove existing (probably obsolete or left-over) file on UNIX socket path '%s'.", path);
-
- if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
- close(sock);
- error("LISTENER: UNIX bind() on path '%s' failed.", path);
- return -1;
- }
-
- // we have to chmod this to 0777 so that the client will be able
- // to read from and write to this socket.
- if(chmod(path, 0777) == -1)
- error("LISTENER: failed to chmod() socket file '%s'.", path);
-
- if(listen(sock, listen_backlog) < 0) {
- close(sock);
- error("LISTENER: UNIX listen() on path '%s' failed.", path);
- return -1;
- }
-
- debug(D_LISTENER, "LISTENER: Listening on UNIX path '%s'", path);
- return sock;
-}
-
-int create_listen_socket4(int socktype, const char *ip, int port, int listen_backlog) {
- int sock;
-
- debug(D_LISTENER, "LISTENER: IPv4 creating new listening socket on ip '%s' port %d, socktype %d", ip, port, socktype);
-
- sock = socket(AF_INET, socktype, 0);
- if(sock < 0) {
- error("LISTENER: IPv4 socket() on ip '%s' port %d, socktype %d failed.", ip, port, socktype);
- return -1;
- }
-
- sock_setreuse(sock, 1);
- sock_setreuse_port(sock, 1);
- sock_setnonblock(sock);
- sock_enlarge_in(sock);
-
- struct sockaddr_in name;
- memset(&name, 0, sizeof(struct sockaddr_in));
- name.sin_family = AF_INET;
- name.sin_port = htons (port);
-
- int ret = inet_pton(AF_INET, ip, (void *)&name.sin_addr.s_addr);
- if(ret != 1) {
- error("LISTENER: Failed to convert IP '%s' to a valid IPv4 address.", ip);
- close(sock);
- return -1;
- }
-
- if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
- close(sock);
- error("LISTENER: IPv4 bind() on ip '%s' port %d, socktype %d failed.", ip, port, socktype);
- return -1;
- }
-
- if(socktype == SOCK_STREAM && listen(sock, listen_backlog) < 0) {
- close(sock);
- error("LISTENER: IPv4 listen() on ip '%s' port %d, socktype %d failed.", ip, port, socktype);
- return -1;
- }
-
- debug(D_LISTENER, "LISTENER: Listening on IPv4 ip '%s' port %d, socktype %d", ip, port, socktype);
- return sock;
-}
-
-int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int port, int listen_backlog) {
- int sock;
- int ipv6only = 1;
-
- debug(D_LISTENER, "LISTENER: IPv6 creating new listening socket on ip '%s' port %d, socktype %d", ip, port, socktype);
-
- sock = socket(AF_INET6, socktype, 0);
- if (sock < 0) {
- error("LISTENER: IPv6 socket() on ip '%s' port %d, socktype %d, failed.", ip, port, socktype);
- return -1;
- }
-
- sock_setreuse(sock, 1);
- sock_setreuse_port(sock, 1);
- sock_setnonblock(sock);
- sock_enlarge_in(sock);
-
- /* IPv6 only */
- if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&ipv6only, sizeof(ipv6only)) != 0)
- error("LISTENER: Cannot set IPV6_V6ONLY on ip '%s' port %d, socktype %d.", ip, port, socktype);
-
- struct sockaddr_in6 name;
- memset(&name, 0, sizeof(struct sockaddr_in6));
- name.sin6_family = AF_INET6;
- name.sin6_port = htons ((uint16_t) port);
- name.sin6_scope_id = scope_id;
-
- int ret = inet_pton(AF_INET6, ip, (void *)&name.sin6_addr.s6_addr);
- if(ret != 1) {
- error("LISTENER: Failed to convert IP '%s' to a valid IPv6 address.", ip);
- close(sock);
- return -1;
- }
-
- name.sin6_scope_id = scope_id;
-
- if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
- close(sock);
- error("LISTENER: IPv6 bind() on ip '%s' port %d, socktype %d failed.", ip, port, socktype);
- return -1;
- }
-
- if (socktype == SOCK_STREAM && listen(sock, listen_backlog) < 0) {
- close(sock);
- error("LISTENER: IPv6 listen() on ip '%s' port %d, socktype %d failed.", ip, port, socktype);
- return -1;
- }
-
- debug(D_LISTENER, "LISTENER: Listening on IPv6 ip '%s' port %d, socktype %d", ip, port, socktype);
- return sock;
-}
-
-static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int family, int socktype, const char *protocol, const char *ip, int port) {
- if(sockets->opened >= MAX_LISTEN_FDS) {
- error("LISTENER: Too many listening sockets. Failed to add listening %s socket at ip '%s' port %d, protocol %s, socktype %d", protocol, ip, port, protocol, socktype);
- close(fd);
- return -1;
- }
-
- sockets->fds[sockets->opened] = fd;
- sockets->fds_types[sockets->opened] = socktype;
- sockets->fds_families[sockets->opened] = family;
- sockets->fds_names[sockets->opened] = strdup_client_description(family, protocol, ip, port);
-
- sockets->opened++;
- return 0;
-}
-
-int listen_sockets_check_is_member(LISTEN_SOCKETS *sockets, int fd) {
- size_t i;
- for(i = 0; i < sockets->opened ;i++)
- if(sockets->fds[i] == fd) return 1;
-
- return 0;
-}
-
-static inline void listen_sockets_init(LISTEN_SOCKETS *sockets) {
- size_t i;
- for(i = 0; i < MAX_LISTEN_FDS ;i++) {
- sockets->fds[i] = -1;
- sockets->fds_names[i] = NULL;
- sockets->fds_types[i] = -1;
- }
-
- sockets->opened = 0;
- sockets->failed = 0;
-}
-
-void listen_sockets_close(LISTEN_SOCKETS *sockets) {
- size_t i;
- for(i = 0; i < sockets->opened ;i++) {
- close(sockets->fds[i]);
- sockets->fds[i] = -1;
-
- freez(sockets->fds_names[i]);
- sockets->fds_names[i] = NULL;
-
- sockets->fds_types[i] = -1;
- }
-
- sockets->opened = 0;
- sockets->failed = 0;
-}
-
-static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, int default_port, int listen_backlog) {
- int added = 0;
- struct addrinfo hints;
- struct addrinfo *result = NULL, *rp = NULL;
-
- char buffer[strlen(definition) + 1];
- strcpy(buffer, definition);
-
- char buffer2[10 + 1];
- snprintfz(buffer2, 10, "%d", default_port);
-
- char *ip = buffer, *port = buffer2, *interface = "";;
-
- int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
- const char *protocol_str = "tcp";
-
- if(strncmp(ip, "tcp:", 4) == 0) {
- ip += 4;
- protocol = IPPROTO_TCP;
- socktype = SOCK_STREAM;
- protocol_str = "tcp";
- }
- else if(strncmp(ip, "udp:", 4) == 0) {
- ip += 4;
- protocol = IPPROTO_UDP;
- socktype = SOCK_DGRAM;
- protocol_str = "udp";
- }
- else if(strncmp(ip, "unix:", 5) == 0) {
- char *path = ip + 5;
- socktype = SOCK_STREAM;
- protocol_str = "unix";
-
- int fd = create_listen_socket_unix(path, listen_backlog);
- if (fd == -1) {
- error("LISTENER: Cannot create unix socket '%s'", path);
- sockets->failed++;
- }
- else {
- listen_sockets_add(sockets, fd, AF_UNIX, socktype, protocol_str, path, 0);
- added++;
- }
- return added;
- }
-
- char *e = ip;
- if(*e == '[') {
- e = ++ip;
- while(*e && *e != ']') e++;
- if(*e == ']') {
- *e = '\0';
- e++;
- }
- }
- else {
- while(*e && *e != ':' && *e != '%') e++;
- }
-
- if(*e == '%') {
- *e = '\0';
- e++;
- interface = e;
- while(*e && *e != ':') e++;
- }
-
- if(*e == ':') {
- port = e + 1;
- *e = '\0';
- }
-
- uint32_t scope_id = 0;
- if(*interface) {
- scope_id = if_nametoindex(interface);
- if(!scope_id)
- error("LISTENER: Cannot find a network interface named '%s'. Continuing with limiting the network interface", interface);
- }
-
- if(!*ip || *ip == '*' || !strcmp(ip, "any") || !strcmp(ip, "all"))
- ip = NULL;
-
- if(!*port)
- port = buffer2;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
- hints.ai_socktype = socktype;
- hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
- hints.ai_protocol = protocol;
- hints.ai_canonname = NULL;
- hints.ai_addr = NULL;
- hints.ai_next = NULL;
-
- int r = getaddrinfo(ip, port, &hints, &result);
- if (r != 0) {
- error("LISTENER: getaddrinfo('%s', '%s'): %s\n", ip, port, gai_strerror(r));
- return -1;
- }
-
- for (rp = result; rp != NULL; rp = rp->ai_next) {
- int fd = -1;
- int family = -1;
-
- char rip[INET_ADDRSTRLEN + INET6_ADDRSTRLEN] = "INVALID";
- int rport = default_port;
-
- family = rp->ai_addr->sa_family;
- switch (family) {
- case AF_INET: {
- struct sockaddr_in *sin = (struct sockaddr_in *) rp->ai_addr;
- inet_ntop(AF_INET, &sin->sin_addr, rip, INET_ADDRSTRLEN);
- rport = ntohs(sin->sin_port);
- // info("Attempting to listen on IPv4 '%s' ('%s'), port %d ('%s'), socktype %d", rip, ip, rport, port, socktype);
- fd = create_listen_socket4(socktype, rip, rport, listen_backlog);
- break;
- }
-
- case AF_INET6: {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) rp->ai_addr;
- inet_ntop(AF_INET6, &sin6->sin6_addr, rip, INET6_ADDRSTRLEN);
- rport = ntohs(sin6->sin6_port);
- // info("Attempting to listen on IPv6 '%s' ('%s'), port %d ('%s'), socktype %d", rip, ip, rport, port, socktype);
- fd = create_listen_socket6(socktype, scope_id, rip, rport, listen_backlog);
- break;
- }
-
- default:
- debug(D_LISTENER, "LISTENER: Unknown socket family %d", family);
- break;
- }
-
- if (fd == -1) {
- error("LISTENER: Cannot bind to ip '%s', port %d", rip, rport);
- sockets->failed++;
- }
- else {
- listen_sockets_add(sockets, fd, family, socktype, protocol_str, rip, rport);
- added++;
- }
- }
-
- freeaddrinfo(result);
-
- return added;
-}
-
-int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
- listen_sockets_init(sockets);
-
- sockets->backlog = (int) config_get_number(sockets->config_section, "listen backlog", sockets->backlog);
-
- int old_port = sockets->default_port;
- sockets->default_port = (int) config_get_number(sockets->config_section, "default port", sockets->default_port);
- if(sockets->default_port < 1 || sockets->default_port > 65535) {
- error("LISTENER: Invalid listen port %d given. Defaulting to %d.", sockets->default_port, old_port);
- sockets->default_port = (int) config_set_number(sockets->config_section, "default port", old_port);
- }
- debug(D_OPTIONS, "LISTENER: Default listen port set to %d.", sockets->default_port);
-
- char *s = config_get(sockets->config_section, "bind to", sockets->default_bind_to);
- while(*s) {
- char *e = s;
-
- // skip separators, moving both s(tart) and e(nd)
- while(isspace(*e) || *e == ',') s = ++e;
-
- // move e(nd) to the first separator
- while(*e && !isspace(*e) && *e != ',') e++;
-
- // is there anything?
- if(!*s || s == e) break;
-
- char buf[e - s + 1];
- strncpyz(buf, s, e - s);
- bind_to_this(sockets, buf, sockets->default_port, sockets->backlog);
-
- s = e;
- }
-
- if(sockets->failed) {
- size_t i;
- for(i = 0; i < sockets->opened ;i++)
- info("LISTENER: Listen socket %s opened successfully.", sockets->fds_names[i]);
- }
-
- return (int)sockets->opened;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// connect to another host/port
-
-// connect_to_this_unix()
-// path the path of the unix socket
-// timeout the timeout for establishing a connection
-
-static inline int connect_to_unix(const char *path, struct timeval *timeout) {
- int fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(fd == -1) {
- error("Failed to create UNIX socket() for '%s'", path);
- return -1;
- }
-
- if(timeout) {
- if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
- error("Failed to set timeout on UNIX socket '%s'", path);
- }
-
- struct sockaddr_un addr;
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
-
- if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
- error("Cannot connect to UNIX socket on path '%s'.", path);
- close(fd);
- return -1;
- }
-
- debug(D_CONNECT_TO, "Connected to UNIX socket on path '%s'.", path);
-
- return fd;
-}
-
-// connect_to_this_ip46()
-// protocol IPPROTO_TCP, IPPROTO_UDP
-// socktype SOCK_STREAM, SOCK_DGRAM
-// host the destination hostname or IP address (IPv4 or IPv6) to connect to
-// if it resolves to many IPs, all are tried (IPv4 and IPv6)
-// scope_id the if_index id of the interface to use for connecting (0 = any)
-// (used only under IPv6)
-// service the service name or port to connect to
-// timeout the timeout for establishing a connection
-
-static inline int connect_to_this_ip46(int protocol, int socktype, const char *host, uint32_t scope_id, const char *service, struct timeval *timeout) {
- struct addrinfo hints;
- struct addrinfo *ai_head = NULL, *ai = NULL;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC; /* Allow IPv4 or IPv6 */
- hints.ai_socktype = socktype;
- hints.ai_protocol = protocol;
-
- int ai_err = getaddrinfo(host, service, &hints, &ai_head);
- if (ai_err != 0) {
- error("Cannot resolve host '%s', port '%s': %s", host, service, gai_strerror(ai_err));
- return -1;
- }
-
- int fd = -1;
- for (ai = ai_head; ai != NULL && fd == -1; ai = ai->ai_next) {
-
- if (ai->ai_family == PF_INET6) {
- struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
- if(pSadrIn6->sin6_scope_id == 0) {
- pSadrIn6->sin6_scope_id = scope_id;
- }
- }
-
- char hostBfr[NI_MAXHOST + 1];
- char servBfr[NI_MAXSERV + 1];
-
- getnameinfo(ai->ai_addr,
- ai->ai_addrlen,
- hostBfr,
- sizeof(hostBfr),
- servBfr,
- sizeof(servBfr),
- NI_NUMERICHOST | NI_NUMERICSERV);
-
- debug(D_CONNECT_TO, "Address info: host = '%s', service = '%s', ai_flags = 0x%02X, ai_family = %d (PF_INET = %d, PF_INET6 = %d), ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d), ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d), ai_addrlen = %lu (sockaddr_in = %lu, sockaddr_in6 = %lu)",
- hostBfr,
- servBfr,
- (unsigned int)ai->ai_flags,
- ai->ai_family,
- PF_INET,
- PF_INET6,
- ai->ai_socktype,
- SOCK_STREAM,
- SOCK_DGRAM,
- ai->ai_protocol,
- IPPROTO_TCP,
- IPPROTO_UDP,
- (unsigned long)ai->ai_addrlen,
- (unsigned long)sizeof(struct sockaddr_in),
- (unsigned long)sizeof(struct sockaddr_in6));
-
- switch (ai->ai_addr->sa_family) {
- case PF_INET: {
- struct sockaddr_in *pSadrIn = (struct sockaddr_in *)ai->ai_addr;
- debug(D_CONNECT_TO, "ai_addr = sin_family: %d (AF_INET = %d, AF_INET6 = %d), sin_addr: '%s', sin_port: '%s'",
- pSadrIn->sin_family,
- AF_INET,
- AF_INET6,
- hostBfr,
- servBfr);
- break;
- }
-
- case PF_INET6: {
- struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
- debug(D_CONNECT_TO,"ai_addr = sin6_family: %d (AF_INET = %d, AF_INET6 = %d), sin6_addr: '%s', sin6_port: '%s', sin6_flowinfo: %u, sin6_scope_id: %u",
- pSadrIn6->sin6_family,
- AF_INET,
- AF_INET6,
- hostBfr,
- servBfr,
- pSadrIn6->sin6_flowinfo,
- pSadrIn6->sin6_scope_id);
- break;
- }
-
- default: {
- debug(D_CONNECT_TO, "Unknown protocol family %d.", ai->ai_family);
- continue;
- }
- }
-
- fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if(fd != -1) {
- if(timeout) {
- if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
- error("Failed to set timeout on the socket to ip '%s' port '%s'", hostBfr, servBfr);
- }
-
- errno = 0;
- if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
- if(errno == EALREADY || errno == EINPROGRESS) {
- info("Waiting for connection to ip %s port %s to be established", hostBfr, servBfr);
-
- fd_set fds;
- FD_ZERO(&fds);
- FD_SET(0, &fds);
- int rc = select (1, NULL, &fds, NULL, timeout);
-
- if(rc > 0 && FD_ISSET(fd, &fds)) {
- info("connect() to ip %s port %s completed successfully", hostBfr, servBfr);
- }
- else if(rc == -1) {
- error("Failed to connect to '%s', port '%s'. select() returned %d", hostBfr, servBfr, rc);
- close(fd);
- fd = -1;
- }
- else {
- error("Timed out while connecting to '%s', port '%s'. select() returned %d", hostBfr, servBfr, rc);
- close(fd);
- fd = -1;
- }
- }
- else {
- error("Failed to connect to '%s', port '%s'", hostBfr, servBfr);
- close(fd);
- fd = -1;
- }
- }
-
- if(fd != -1)
- debug(D_CONNECT_TO, "Connected to '%s' on port '%s'.", hostBfr, servBfr);
- }
- }
-
- freeaddrinfo(ai_head);
-
- return fd;
-}
-
-// connect_to_this()
-//
-// definition format:
-//
-// [PROTOCOL:]IP[%INTERFACE][:PORT]
-//
-// PROTOCOL = tcp or udp
-// IP = IPv4 or IPv6 IP or hostname, optionally enclosed in [] (required for IPv6)
-// INTERFACE = for IPv6 only, the network interface to use
-// PORT = port number or service name
-
-int connect_to_this(const char *definition, int default_port, struct timeval *timeout) {
- char buffer[strlen(definition) + 1];
- strcpy(buffer, definition);
-
- char default_service[10 + 1];
- snprintfz(default_service, 10, "%d", default_port);
-
- char *host = buffer, *service = default_service, *interface = "";
- int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
- uint32_t scope_id = 0;
-
- if(strncmp(host, "tcp:", 4) == 0) {
- host += 4;
- protocol = IPPROTO_TCP;
- socktype = SOCK_STREAM;
- }
- else if(strncmp(host, "udp:", 4) == 0) {
- host += 4;
- protocol = IPPROTO_UDP;
- socktype = SOCK_DGRAM;
- }
- else if(strncmp(host, "unix:", 5) == 0) {
- char *path = host + 5;
- return connect_to_unix(path, timeout);
- }
-
- char *e = host;
- if(*e == '[') {
- e = ++host;
- while(*e && *e != ']') e++;
- if(*e == ']') {
- *e = '\0';
- e++;
- }
- }
- else {
- while(*e && *e != ':' && *e != '%') e++;
- }
-
- if(*e == '%') {
- *e = '\0';
- e++;
- interface = e;
- while(*e && *e != ':') e++;
- }
-
- if(*e == ':') {
- *e = '\0';
- e++;
- service = e;
- }
-
- debug(D_CONNECT_TO, "Attempting connection to host = '%s', service = '%s', interface = '%s', protocol = %d (tcp = %d, udp = %d)", host, service, interface, protocol, IPPROTO_TCP, IPPROTO_UDP);
-
- if(!*host) {
- error("Definition '%s' does not specify a host.", definition);
- return -1;
- }
-
- if(*interface) {
- scope_id = if_nametoindex(interface);
- if(!scope_id)
- error("Cannot find a network interface named '%s'. Continuing with limiting the network interface", interface);
- }
-
- if(!*service)
- service = default_service;
-
-
- return connect_to_this_ip46(protocol, socktype, host, scope_id, service, timeout);
-}
-
-int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) {
- int sock = -1;
-
- const char *s = destination;
- while(*s) {
- const char *e = s;
-
- // skip separators, moving both s(tart) and e(nd)
- while(isspace(*e) || *e == ',') s = ++e;
-
- // move e(nd) to the first separator
- while(*e && !isspace(*e) && *e != ',') e++;
-
- // is there anything?
- if(!*s || s == e) break;
-
- char buf[e - s + 1];
- strncpyz(buf, s, e - s);
- if(reconnects_counter) *reconnects_counter += 1;
- sock = connect_to_this(buf, default_port, timeout);
- if(sock != -1) {
- if(connected_to && connected_to_size) {
- strncpy(connected_to, buf, connected_to_size);
- connected_to[connected_to_size - 1] = '\0';
- }
- break;
- }
- s = e;
- }
-
- return sock;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// helpers to send/receive data in one call, in blocking mode, with a timeout
-
-ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout) {
- for(;;) {
- struct pollfd fd = {
- .fd = sockfd,
- .events = POLLIN,
- .revents = 0
- };
-
- errno = 0;
- int retval = poll(&fd, 1, timeout * 1000);
-
- if(retval == -1) {
- // failed
-
- if(errno == EINTR || errno == EAGAIN)
- continue;
-
- return -1;
- }
-
- if(!retval) {
- // timeout
- return 0;
- }
-
- if(fd.events & POLLIN) break;
- }
-
- return recv(sockfd, buf, len, flags);
-}
-
-ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout) {
- for(;;) {
- struct pollfd fd = {
- .fd = sockfd,
- .events = POLLOUT,
- .revents = 0
- };
-
- errno = 0;
- int retval = poll(&fd, 1, timeout * 1000);
-
- if(retval == -1) {
- // failed
-
- if(errno == EINTR || errno == EAGAIN)
- continue;
-
- return -1;
- }
-
- if(!retval) {
- // timeout
- return 0;
- }
-
- if(fd.events & POLLOUT) break;
- }
-
- return send(sockfd, buf, len, flags);
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// accept4() replacement for systems that do not have one
-
-#ifndef HAVE_ACCEPT4
-int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {
- int fd = accept(sock, addr, addrlen);
- int newflags = 0;
-
- if (fd < 0) return fd;
-
- if (flags & SOCK_NONBLOCK) {
- newflags |= O_NONBLOCK;
- flags &= ~SOCK_NONBLOCK;
- }
-
-#ifdef SOCK_CLOEXEC
-#ifdef O_CLOEXEC
- if (flags & SOCK_CLOEXEC) {
- newflags |= O_CLOEXEC;
- flags &= ~SOCK_CLOEXEC;
- }
-#endif
-#endif
-
- if (flags) {
- close(fd);
- errno = EINVAL;
- return -1;
- }
-
- if (fcntl(fd, F_SETFL, newflags) < 0) {
- int saved_errno = errno;
- close(fd);
- errno = saved_errno;
- return -1;
- }
-
- return fd;
-}
-#endif
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// accept_socket() - accept a socket and store client IP and port
-
-int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list) {
- struct sockaddr_storage sadr;
- socklen_t addrlen = sizeof(sadr);
-
- int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags);
- if (likely(nfd >= 0)) {
- if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize, client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
- error("LISTENER: cannot getnameinfo() on received client connection.");
- strncpyz(client_ip, "UNKNOWN", ipsize - 1);
- strncpyz(client_port, "UNKNOWN", portsize - 1);
- }
-
- client_ip[ipsize - 1] = '\0';
- client_port[portsize - 1] = '\0';
-
- switch (((struct sockaddr *)&sadr)->sa_family) {
- case AF_UNIX:
- debug(D_LISTENER, "New UNIX domain web client from %s on socket %d.", client_ip, fd);
- // set the port - certain versions of libc return garbage on unix sockets
- strncpy(client_port, "UNIX", portsize);
- client_port[portsize - 1] = '\0';
- break;
-
- case AF_INET:
- debug(D_LISTENER, "New IPv4 web client from %s port %s on socket %d.", client_ip, client_port, fd);
- break;
-
- case AF_INET6:
- if (strncmp(client_ip, "::ffff:", 7) == 0) {
- memmove(client_ip, &client_ip[7], strlen(&client_ip[7]) + 1);
- debug(D_LISTENER, "New IPv4 web client from %s port %s on socket %d.", client_ip, client_port, fd);
- }
- else
- debug(D_LISTENER, "New IPv6 web client from %s port %s on socket %d.", client_ip, client_port, fd);
- break;
-
- default:
- debug(D_LISTENER, "New UNKNOWN web client from %s port %s on socket %d.", client_ip, client_port, fd);
- break;
- }
-
- if(access_list) {
- if(!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
- strncpy(client_ip, "localhost", ipsize);
- client_ip[ipsize - 1] = '\0';
- }
-
- if(unlikely(!simple_pattern_matches(access_list, client_ip))) {
- errno = 0;
- debug(D_LISTENER, "Permission denied for client '%s', port '%s'", client_ip, client_port);
- error("DENIED ACCESS to client '%s'", client_ip);
- close(nfd);
- nfd = -1;
- errno = EPERM;
- }
- }
- }
-#ifdef HAVE_ACCEPT4
- else if(errno == ENOSYS)
- error("netdata has been compiled with the assumption that the system has the accept4() call, but it is not here. Recompile netdata like this: ./configure --disable-accept4 ...");
-#endif
-
- return nfd;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// poll() based listener
-// this should be the fastest possible listener for up to 100 sockets
-// above 100, an epoll() interface is needed on Linux
-
-#define POLL_FDS_INCREASE_STEP 10
-
-inline POLLINFO *poll_add_fd(POLLJOB *p
- , int fd
- , int socktype
- , uint32_t flags
- , const char *client_ip
- , const char *client_port
- , void *(*add_callback)(POLLINFO *pi, short int *events, void *data)
- , void (*del_callback)(POLLINFO *pi)
- , int (*rcv_callback)(POLLINFO *pi, short int *events)
- , int (*snd_callback)(POLLINFO *pi, short int *events)
- , void *data
-) {
- debug(D_POLLFD, "POLLFD: ADD: request to add fd %d, slots = %zu, used = %zu, min = %zu, max = %zu, next free = %zd", fd, p->slots, p->used, p->min, p->max, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1);
-
- if(unlikely(fd < 0)) return NULL;
-
- //if(p->limit && p->used >= p->limit) {
- // info("Max sockets limit reached (%zu sockets), dropping connection", p->used);
- // close(fd);
- // return NULL;
- //}
-
- if(unlikely(!p->first_free)) {
- size_t new_slots = p->slots + POLL_FDS_INCREASE_STEP;
- debug(D_POLLFD, "POLLFD: ADD: increasing size (current = %zu, new = %zu, used = %zu, min = %zu, max = %zu)", p->slots, new_slots, p->used, p->min, p->max);
-
- p->fds = reallocz(p->fds, sizeof(struct pollfd) * new_slots);
- p->inf = reallocz(p->inf, sizeof(POLLINFO) * new_slots);
-
- // reset all the newly added slots
- ssize_t i;
- for(i = new_slots - 1; i >= (ssize_t)p->slots ; i--) {
- debug(D_POLLFD, "POLLFD: ADD: resetting new slot %zd", i);
- p->fds[i].fd = -1;
- p->fds[i].events = 0;
- p->fds[i].revents = 0;
-
- p->inf[i].p = p;
- p->inf[i].slot = (size_t)i;
- p->inf[i].flags = 0;
- p->inf[i].socktype = -1;
- p->inf[i].client_ip = NULL;
- p->inf[i].client_port = NULL;
- p->inf[i].del_callback = p->del_callback;
- p->inf[i].rcv_callback = p->rcv_callback;
- p->inf[i].snd_callback = p->snd_callback;
- p->inf[i].data = NULL;
-
- // link them so that the first free will be earlier in the array
- // (we loop decrementing i)
- p->inf[i].next = p->first_free;
- p->first_free = &p->inf[i];
- }
-
- p->slots = new_slots;
- }
-
- POLLINFO *pi = p->first_free;
- p->first_free = p->first_free->next;
-
- debug(D_POLLFD, "POLLFD: ADD: selected slot %zu, next free is %zd", pi->slot, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1);
-
- struct pollfd *pf = &p->fds[pi->slot];
- pf->fd = fd;
- pf->events = POLLIN;
- pf->revents = 0;
-
- pi->fd = fd;
- pi->p = p;
- pi->socktype = socktype;
- pi->flags = flags;
- pi->next = NULL;
- pi->client_ip = strdupz(client_ip);
- pi->client_port = strdupz(client_port);
-
- pi->del_callback = del_callback;
- pi->rcv_callback = rcv_callback;
- pi->snd_callback = snd_callback;
-
- pi->connected_t = now_boottime_sec();
- pi->last_received_t = 0;
- pi->last_sent_t = 0;
- pi->last_sent_t = 0;
- pi->recv_count = 0;
- pi->send_count = 0;
-
- netdata_thread_disable_cancelability();
- p->used++;
- if(unlikely(pi->slot > p->max))
- p->max = pi->slot;
-
- if(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET) {
- pi->data = add_callback(pi, &pf->events, data);
- }
-
- if(pi->flags & POLLINFO_FLAG_SERVER_SOCKET) {
- p->min = pi->slot;
- }
- netdata_thread_enable_cancelability();
-
- debug(D_POLLFD, "POLLFD: ADD: completed, slots = %zu, used = %zu, min = %zu, max = %zu, next free = %zd", p->slots, p->used, p->min, p->max, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1);
-
- return pi;
-}
-
-inline void poll_close_fd(POLLINFO *pi) {
- POLLJOB *p = pi->p;
-
- struct pollfd *pf = &p->fds[pi->slot];
- debug(D_POLLFD, "POLLFD: DEL: request to clear slot %zu (fd %d), old next free was %zd", pi->slot, pf->fd, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1);
-
- if(unlikely(pf->fd == -1)) return;
-
- netdata_thread_disable_cancelability();
-
- if(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET) {
- pi->del_callback(pi);
-
- if(likely(!(pi->flags & POLLINFO_FLAG_DONT_CLOSE))) {
- if(close(pf->fd) == -1)
- error("Failed to close() poll_events() socket %d", pf->fd);
- }
- }
-
- pf->fd = -1;
- pf->events = 0;
- pf->revents = 0;
-
- pi->fd = -1;
- pi->socktype = -1;
- pi->flags = 0;
- pi->data = NULL;
-
- pi->del_callback = NULL;
- pi->rcv_callback = NULL;
- pi->snd_callback = NULL;
-
- freez(pi->client_ip);
- pi->client_ip = NULL;
-
- freez(pi->client_port);
- pi->client_port = NULL;
-
- pi->next = p->first_free;
- p->first_free = pi;
-
- p->used--;
- if(unlikely(p->max == pi->slot)) {
- p->max = p->min;
- ssize_t i;
- for(i = (ssize_t)pi->slot; i > (ssize_t)p->min ;i--) {
- if (unlikely(p->fds[i].fd != -1)) {
- p->max = (size_t)i;
- break;
- }
- }
- }
- netdata_thread_enable_cancelability();
-
- debug(D_POLLFD, "POLLFD: DEL: completed, slots = %zu, used = %zu, min = %zu, max = %zu, next free = %zd", p->slots, p->used, p->min, p->max, p->first_free?(ssize_t)p->first_free->slot:(ssize_t)-1);
-}
-
-void *poll_default_add_callback(POLLINFO *pi, short int *events, void *data) {
- (void)pi;
- (void)events;
- (void)data;
-
- // error("POLLFD: internal error: poll_default_add_callback() called");
-
- return NULL;
-}
-
-void poll_default_del_callback(POLLINFO *pi) {
- if(pi->data)
- error("POLLFD: internal error: del_callback_default() called with data pointer - possible memory leak");
-}
-
-int poll_default_rcv_callback(POLLINFO *pi, short int *events) {
- *events |= POLLIN;
-
- char buffer[1024 + 1];
-
- ssize_t rc;
- do {
- rc = recv(pi->fd, buffer, 1024, MSG_DONTWAIT);
- if (rc < 0) {
- // read failed
- if (errno != EWOULDBLOCK && errno != EAGAIN) {
- error("POLLFD: poll_default_rcv_callback(): recv() failed with %zd.", rc);
- return -1;
- }
- } else if (rc) {
- // data received
- info("POLLFD: internal error: poll_default_rcv_callback() is discarding %zd bytes received on socket %d", rc, pi->fd);
- }
- } while (rc != -1);
-
- return 0;
-}
-
-int poll_default_snd_callback(POLLINFO *pi, short int *events) {
- *events &= ~POLLOUT;
-
- info("POLLFD: internal error: poll_default_snd_callback(): nothing to send on socket %d", pi->fd);
- return 0;
-}
-
-void poll_default_tmr_callback(void *timer_data) {
- (void)timer_data;
-}
-
-static void poll_events_cleanup(void *data) {
- POLLJOB *p = (POLLJOB *)data;
-
- size_t i;
- for(i = 0 ; i <= p->max ; i++) {
- POLLINFO *pi = &p->inf[i];
- poll_close_fd(pi);
- }
-
- freez(p->fds);
- freez(p->inf);
-}
-
-static void poll_events_process(POLLJOB *p, POLLINFO *pi, struct pollfd *pf, short int revents, time_t now) {
- short int events = pf->events;
- int fd = pf->fd;
- pf->revents = 0;
- size_t i = pi->slot;
-
- if(unlikely(fd == -1)) {
- debug(D_POLLFD, "POLLFD: LISTENER: ignoring slot %zu, it does not have an fd", i);
- return;
- }
-
- debug(D_POLLFD, "POLLFD: LISTENER: processing events for slot %zu (events = %d, revents = %d)", i, events, revents);
-
- if(revents & POLLIN || revents & POLLPRI) {
- // receiving data
-
- pi->last_received_t = now;
- pi->recv_count++;
-
- if(likely(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET)) {
- // read data from client TCP socket
- debug(D_POLLFD, "POLLFD: LISTENER: reading data from TCP client slot %zu (fd %d)", i, fd);
-
- pf->events = 0;
- if (pi->rcv_callback(pi, &pf->events) == -1) {
- poll_close_fd(&p->inf[i]);
- return;
- }
- pf = &p->fds[i];
- pi = &p->inf[i];
-
-#ifdef NETDATA_INTERNAL_CHECKS
- // this is common - it is used for web server file copies
- if(unlikely(!(pf->events & (POLLIN|POLLOUT)))) {
- error("POLLFD: LISTENER: after reading, client slot %zu (fd %d) from '%s:%s' was left without expecting input or output. ", i, fd, pi->client_ip?pi->client_ip:"<undefined-ip>", pi->client_port?pi->client_port:"<undefined-port>");
- //poll_close_fd(pi);
- //return;
- }
-#endif
- }
- else if(likely(pi->flags & POLLINFO_FLAG_SERVER_SOCKET)) {
- // new connection
- // debug(D_POLLFD, "POLLFD: LISTENER: accepting connections from slot %zu (fd %d)", i, fd);
-
- switch(pi->socktype) {
- case SOCK_STREAM: {
- // a TCP socket
- // we accept the connection
-
- int nfd;
- do {
- char client_ip[NI_MAXHOST + 1];
- char client_port[NI_MAXSERV + 1];
-
- debug(D_POLLFD, "POLLFD: LISTENER: calling accept4() slot %zu (fd %d)", i, fd);
- nfd = accept_socket(fd, SOCK_NONBLOCK, client_ip, NI_MAXHOST + 1, client_port, NI_MAXSERV + 1, p->access_list);
- if (unlikely(nfd < 0)) {
- // accept failed
-
- debug(D_POLLFD, "POLLFD: LISTENER: accept4() slot %zu (fd %d) failed.", i, fd);
-
- if(unlikely(errno == EMFILE)) {
- error("POLLFD: LISTENER: too many open files - sleeping for 1ms - used by this thread %zu, max for this thread %zu", p->used, p->limit);
- usleep(1000); // 10ms
- }
- else if(unlikely(errno != EWOULDBLOCK && errno != EAGAIN))
- error("POLLFD: LISTENER: accept() failed.");
-
- break;
- }
- else {
- // accept ok
- // info("POLLFD: LISTENER: client '[%s]:%s' connected to '%s' on fd %d", client_ip, client_port, sockets->fds_names[i], nfd);
- poll_add_fd(p
- , nfd
- , SOCK_STREAM
- , POLLINFO_FLAG_CLIENT_SOCKET
- , client_ip
- , client_port
- , p->add_callback
- , p->del_callback
- , p->rcv_callback
- , p->snd_callback
- , NULL
- );
-
- // it may have reallocated them, so refresh our pointers
- pf = &p->fds[i];
- pi = &p->inf[i];
- }
- } while (nfd >= 0 && (!p->limit || p->used < p->limit));
- break;
- }
-
- case SOCK_DGRAM: {
- // a UDP socket
- // we read data from the server socket
-
- debug(D_POLLFD, "POLLFD: LISTENER: reading data from UDP slot %zu (fd %d)", i, fd);
-
- // FIXME: access_list is not applied to UDP
-
- pf->events = 0;
- pi->rcv_callback(pi, &pf->events);
- break;
- }
-
- default: {
- error("POLLFD: LISTENER: Unknown socktype %d on slot %zu", pi->socktype, pi->slot);
- break;
- }
- }
- }
- }
-
- if(unlikely(revents & POLLOUT)) {
- // sending data
- debug(D_POLLFD, "POLLFD: LISTENER: sending data to socket on slot %zu (fd %d)", i, fd);
-
- pi->last_sent_t = now;
- pi->send_count++;
-
- pf->events = 0;
- if (pi->snd_callback(pi, &pf->events) == -1) {
- poll_close_fd(&p->inf[i]);
- return;
- }
- pf = &p->fds[i];
- pi = &p->inf[i];
-
-#ifdef NETDATA_INTERNAL_CHECKS
- // this is common - it is used for streaming
- if(unlikely(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET && !(pf->events & (POLLIN|POLLOUT)))) {
- error("POLLFD: LISTENER: after sending, client slot %zu (fd %d) from '%s:%s' was left without expecting input or output. ", i, fd, pi->client_ip?pi->client_ip:"<undefined-ip>", pi->client_port?pi->client_port:"<undefined-port>");
- //poll_close_fd(pi);
- //return;
- }
-#endif
- }
-
- if(unlikely(revents & POLLERR)) {
- error("POLLFD: LISTENER: processing POLLERR events for slot %zu fd %d (events = %d, revents = %d)", i, events, revents, fd);
- pf->events = 0;
- poll_close_fd(pi);
- return;
- }
-
- if(unlikely(revents & POLLHUP)) {
- error("POLLFD: LISTENER: processing POLLHUP events for slot %zu fd %d (events = %d, revents = %d)", i, events, revents, fd);
- pf->events = 0;
- poll_close_fd(pi);
- return;
- }
-
- if(unlikely(revents & POLLNVAL)) {
- error("POLLFD: LISTENER: processing POLLNVAL events for slot %zu fd %d (events = %d, revents = %d)", i, events, revents, fd);
- pf->events = 0;
- poll_close_fd(pi);
- return;
- }
-}
-
-void poll_events(LISTEN_SOCKETS *sockets
- , void *(*add_callback)(POLLINFO *pi, short int *events, void *data)
- , void (*del_callback)(POLLINFO *pi)
- , int (*rcv_callback)(POLLINFO *pi, short int *events)
- , int (*snd_callback)(POLLINFO *pi, short int *events)
- , void (*tmr_callback)(void *timer_data)
- , SIMPLE_PATTERN *access_list
- , void *data
- , time_t tcp_request_timeout_seconds
- , time_t tcp_idle_timeout_seconds
- , time_t timer_milliseconds
- , void *timer_data
- , size_t max_tcp_sockets
-) {
- if(!sockets || !sockets->opened) {
- error("POLLFD: internal error: no listening sockets are opened");
- return;
- }
-
- if(timer_milliseconds <= 0) timer_milliseconds = 0;
-
- int retval;
-
- POLLJOB p = {
- .slots = 0,
- .used = 0,
- .max = 0,
- .limit = max_tcp_sockets,
- .fds = NULL,
- .inf = NULL,
- .first_free = NULL,
-
- .complete_request_timeout = tcp_request_timeout_seconds,
- .idle_timeout = tcp_idle_timeout_seconds,
- .checks_every = (tcp_idle_timeout_seconds / 3) + 1,
-
- .access_list = access_list,
-
- .timer_milliseconds = timer_milliseconds,
- .timer_data = timer_data,
-
- .add_callback = add_callback?add_callback:poll_default_add_callback,
- .del_callback = del_callback?del_callback:poll_default_del_callback,
- .rcv_callback = rcv_callback?rcv_callback:poll_default_rcv_callback,
- .snd_callback = snd_callback?snd_callback:poll_default_snd_callback,
- .tmr_callback = tmr_callback?tmr_callback:poll_default_tmr_callback
- };
-
- size_t i;
- for(i = 0; i < sockets->opened ;i++) {
-
- POLLINFO *pi = poll_add_fd(&p
- , sockets->fds[i]
- , sockets->fds_types[i]
- , POLLINFO_FLAG_SERVER_SOCKET
- , (sockets->fds_names[i])?sockets->fds_names[i]:"UNKNOWN"
- , ""
- , p.add_callback
- , p.del_callback
- , p.rcv_callback
- , p.snd_callback
- , NULL
- );
-
- pi->data = data;
- info("POLLFD: LISTENER: listening on '%s'", (sockets->fds_names[i])?sockets->fds_names[i]:"UNKNOWN");
- }
-
- int listen_sockets_active = 1;
-
- int timeout_ms = 1000; // in milliseconds
- time_t last_check = now_boottime_sec();
-
- usec_t timer_usec = timer_milliseconds * USEC_PER_MS;
- usec_t now_usec = 0, next_timer_usec = 0, last_timer_usec = 0;
- if(unlikely(timer_usec)) {
- now_usec = now_boottime_usec();
- next_timer_usec = now_usec - (now_usec % timer_usec) + timer_usec;
- }
-
- netdata_thread_cleanup_push(poll_events_cleanup, &p);
-
- while(!netdata_exit) {
- if(unlikely(timer_usec)) {
- now_usec = now_boottime_usec();
-
- if(unlikely(timer_usec && now_usec >= next_timer_usec)) {
- debug(D_POLLFD, "Calling timer callback after %zu usec", (size_t)(now_usec - last_timer_usec));
- last_timer_usec = now_usec;
- p.tmr_callback(p.timer_data);
- now_usec = now_boottime_usec();
- next_timer_usec = now_usec - (now_usec % timer_usec) + timer_usec;
- }
-
- usec_t dt_usec = next_timer_usec - now_usec;
- if(dt_usec > 1000 * USEC_PER_MS)
- timeout_ms = 1000;
- else
- timeout_ms = (int)(dt_usec / USEC_PER_MS);
- }
-
- // enable or disable the TCP listening sockets, based on the current number of sockets used and the limit set
- if((listen_sockets_active && (p.limit && p.used >= p.limit)) || (!listen_sockets_active && (!p.limit || p.used < p.limit))) {
- listen_sockets_active = !listen_sockets_active;
- info("%s listening sockets (used TCP sockets %zu, max allowed for this worker %zu)", (listen_sockets_active)?"ENABLING":"DISABLING", p.used, p.limit);
- for (i = 0; i <= p.max; i++) {
- if(p.inf[i].flags & POLLINFO_FLAG_SERVER_SOCKET && p.inf[i].socktype == SOCK_STREAM) {
- p.fds[i].events = (short int) ((listen_sockets_active) ? POLLIN : 0);
- }
- }
- }
-
- debug(D_POLLFD, "POLLFD: LISTENER: Waiting on %zu sockets for %zu ms...", p.max + 1, (size_t)timeout_ms);
- retval = poll(p.fds, p.max + 1, timeout_ms);
- time_t now = now_boottime_sec();
-
- if(unlikely(retval == -1)) {
- error("POLLFD: LISTENER: poll() failed while waiting on %zu sockets.", p.max + 1);
- break;
- }
- else if(unlikely(!retval)) {
- debug(D_POLLFD, "POLLFD: LISTENER: poll() timeout.");
- }
- else {
- for (i = 0; i <= p.max; i++) {
- struct pollfd *pf = &p.fds[i];
- short int revents = pf->revents;
- if (unlikely(revents))
- poll_events_process(&p, &p.inf[i], pf, revents, now);
- }
- }
-
- if(unlikely(p.checks_every > 0 && now - last_check > p.checks_every)) {
- last_check = now;
-
- // security checks
- for(i = 0; i <= p.max; i++) {
- POLLINFO *pi = &p.inf[i];
-
- if(likely(pi->flags & POLLINFO_FLAG_CLIENT_SOCKET)) {
- if (unlikely(pi->send_count == 0 && p.complete_request_timeout > 0 && (now - pi->connected_t) >= p.complete_request_timeout)) {
- info("POLLFD: LISTENER: client slot %zu (fd %d) from '%s:%s' has not sent a complete request in %zu seconds - closing it. "
- , i
- , pi->fd
- , pi->client_ip ? pi->client_ip : "<undefined-ip>"
- , pi->client_port ? pi->client_port : "<undefined-port>"
- , (size_t) p.complete_request_timeout
- );
- poll_close_fd(pi);
- }
- else if(unlikely(pi->recv_count && p.idle_timeout > 0 && now - ((pi->last_received_t > pi->last_sent_t) ? pi->last_received_t : pi->last_sent_t) >= p.idle_timeout )) {
- info("POLLFD: LISTENER: client slot %zu (fd %d) from '%s:%s' is idle for more than %zu seconds - closing it. "
- , i
- , pi->fd
- , pi->client_ip ? pi->client_ip : "<undefined-ip>"
- , pi->client_port ? pi->client_port : "<undefined-port>"
- , (size_t) p.idle_timeout
- );
- poll_close_fd(pi);
- }
- }
- }
- }
- }
-
- netdata_thread_cleanup_pop(1);
- debug(D_POLLFD, "POLLFD: LISTENER: cleanup completed");
-}
diff --git a/src/socket.h b/src/socket.h
deleted file mode 100644
index 7b3e726ec..000000000
--- a/src/socket.h
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef NETDATA_SOCKET_H
-#define NETDATA_SOCKET_H
-
-#ifndef MAX_LISTEN_FDS
-#define MAX_LISTEN_FDS 50
-#endif
-
-typedef struct listen_sockets {
- const char *config_section; // the netdata configuration section to read settings from
- const char *default_bind_to; // the default bind to configuration string
- int default_port; // the default port to use
- int backlog; // the default listen backlog to use
-
- size_t opened; // the number of sockets opened
- size_t failed; // the number of sockets attempted to open, but failed
- int fds[MAX_LISTEN_FDS]; // the open sockets
- char *fds_names[MAX_LISTEN_FDS]; // descriptions for the open sockets
- int fds_types[MAX_LISTEN_FDS]; // the socktype for the open sockets (SOCK_STREAM, SOCK_DGRAM)
- int fds_families[MAX_LISTEN_FDS]; // the family of the open sockets (AF_UNIX, AF_INET, AF_INET6)
-} LISTEN_SOCKETS;
-
-extern char *strdup_client_description(int family, const char *protocol, const char *ip, int port);
-
-extern int listen_sockets_setup(LISTEN_SOCKETS *sockets);
-extern void listen_sockets_close(LISTEN_SOCKETS *sockets);
-
-extern int connect_to_this(const char *definition, int default_port, struct timeval *timeout);
-extern int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size);
-
-extern ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);
-extern ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);
-
-extern int sock_setnonblock(int fd);
-extern int sock_delnonblock(int fd);
-extern int sock_setreuse(int fd, int reuse);
-extern int sock_setreuse_port(int fd, int reuse);
-extern int sock_enlarge_in(int fd);
-extern int sock_enlarge_out(int fd);
-
-extern int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize, SIMPLE_PATTERN *access_list);
-
-#ifndef HAVE_ACCEPT4
-extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);
-
-#ifndef SOCK_NONBLOCK
-#define SOCK_NONBLOCK 00004000
-#endif /* #ifndef SOCK_NONBLOCK */
-
-#ifndef SOCK_CLOEXEC
-#define SOCK_CLOEXEC 02000000
-#endif /* #ifndef SOCK_CLOEXEC */
-
-#endif /* #ifndef HAVE_ACCEPT4 */
-
-
-// ----------------------------------------------------------------------------
-// poll() based listener
-
-#define POLLINFO_FLAG_SERVER_SOCKET 0x00000001
-#define POLLINFO_FLAG_CLIENT_SOCKET 0x00000002
-#define POLLINFO_FLAG_DONT_CLOSE 0x00000004
-
-typedef struct poll POLLJOB;
-
-typedef struct pollinfo {
- POLLJOB *p; // the parent
- size_t slot; // the slot id
-
- int fd; // the file descriptor
- int socktype; // the client socket type
- char *client_ip; // the connected client IP
- char *client_port; // the connected client port
-
- time_t connected_t; // the time the socket connected
- time_t last_received_t; // the time the socket last received data
- time_t last_sent_t; // the time the socket last sent data
-
- size_t recv_count; // the number of times the socket was ready for inbound traffic
- size_t send_count; // the number of times the socket was ready for outbound traffic
-
- uint32_t flags; // internal flags
-
- // callbacks for this socket
- void (*del_callback)(struct pollinfo *pi);
- int (*rcv_callback)(struct pollinfo *pi, short int *events);
- int (*snd_callback)(struct pollinfo *pi, short int *events);
-
- // the user data
- void *data;
-
- // linking of free pollinfo structures
- // for quickly finding the next available
- // this is like a stack, it grows and shrinks
- // (with gaps - lower empty slots are preferred)
- struct pollinfo *next;
-} POLLINFO;
-
-struct poll {
- size_t slots;
- size_t used;
- size_t min;
- size_t max;
-
- size_t limit;
-
- time_t complete_request_timeout;
- time_t idle_timeout;
- time_t checks_every;
-
- time_t timer_milliseconds;
- void *timer_data;
-
- struct pollfd *fds;
- struct pollinfo *inf;
- struct pollinfo *first_free;
-
- SIMPLE_PATTERN *access_list;
-
- void *(*add_callback)(POLLINFO *pi, short int *events, void *data);
- void (*del_callback)(POLLINFO *pi);
- int (*rcv_callback)(POLLINFO *pi, short int *events);
- int (*snd_callback)(POLLINFO *pi, short int *events);
- void (*tmr_callback)(void *timer_data);
-};
-
-#define pollinfo_from_slot(p, slot) (&((p)->inf[(slot)]))
-
-extern int poll_default_snd_callback(POLLINFO *pi, short int *events);
-extern int poll_default_rcv_callback(POLLINFO *pi, short int *events);
-extern void poll_default_del_callback(POLLINFO *pi);
-extern void *poll_default_add_callback(POLLINFO *pi, short int *events, void *data);
-
-extern POLLINFO *poll_add_fd(POLLJOB *p
- , int fd
- , int socktype
- , uint32_t flags
- , const char *client_ip
- , const char *client_port
- , void *(*add_callback)(POLLINFO *pi, short int *events, void *data)
- , void (*del_callback)(POLLINFO *pi)
- , int (*rcv_callback)(POLLINFO *pi, short int *events)
- , int (*snd_callback)(POLLINFO *pi, short int *events)
- , void *data
-);
-extern void poll_close_fd(POLLINFO *pi);
-
-extern void poll_events(LISTEN_SOCKETS *sockets
- , void *(*add_callback)(POLLINFO *pi, short int *events, void *data)
- , void (*del_callback)(POLLINFO *pi)
- , int (*rcv_callback)(POLLINFO *pi, short int *events)
- , int (*snd_callback)(POLLINFO *pi, short int *events)
- , void (*tmr_callback)(void *timer_data)
- , SIMPLE_PATTERN *access_list
- , void *data
- , time_t tcp_request_timeout_seconds
- , time_t tcp_idle_timeout_seconds
- , time_t timer_milliseconds
- , void *timer_data
- , size_t max_tcp_sockets
-);
-
-#endif //NETDATA_SOCKET_H
diff --git a/src/statistical.c b/src/statistical.c
deleted file mode 100644
index d4b33fd5a..000000000
--- a/src/statistical.c
+++ /dev/null
@@ -1,459 +0,0 @@
-#include "common.h"
-
-// --------------------------------------------------------------------------------------------------------------------
-
-inline LONG_DOUBLE sum_and_count(const LONG_DOUBLE *series, size_t entries, size_t *count) {
- if(unlikely(entries == 0)) {
- if(likely(count))
- *count = 0;
-
- return NAN;
- }
-
- if(unlikely(entries == 1)) {
- if(likely(count))
- *count = (isnan(series[0])?0:1);
-
- return series[0];
- }
-
- size_t i, c = 0;
- LONG_DOUBLE sum = 0;
-
- for(i = 0; i < entries ; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
- c++;
- sum += value;
- }
-
- if(likely(count))
- *count = c;
-
- if(unlikely(c == 0))
- return NAN;
-
- return sum;
-}
-
-inline LONG_DOUBLE sum(const LONG_DOUBLE *series, size_t entries) {
- return sum_and_count(series, entries, NULL);
-}
-
-inline LONG_DOUBLE average(const LONG_DOUBLE *series, size_t entries) {
- size_t count = 0;
- LONG_DOUBLE sum = sum_and_count(series, entries, &count);
-
- if(unlikely(count == 0))
- return NAN;
-
- return sum / (LONG_DOUBLE)count;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-LONG_DOUBLE moving_average(const LONG_DOUBLE *series, size_t entries, size_t period) {
- if(unlikely(period <= 0))
- return 0.0;
-
- size_t i, count;
- LONG_DOUBLE sum = 0, avg = 0;
- LONG_DOUBLE p[period];
-
- for(count = 0; count < period ; count++)
- p[count] = 0.0;
-
- for(i = 0, count = 0; i < entries; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
-
- if(unlikely(count < period)) {
- sum += value;
- avg = (count == period - 1) ? sum / (LONG_DOUBLE)period : 0;
- }
- else {
- sum = sum - p[count % period] + value;
- avg = sum / (LONG_DOUBLE)period;
- }
-
- p[count % period] = value;
- count++;
- }
-
- return avg;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-static int qsort_compare(const void *a, const void *b) {
- LONG_DOUBLE *p1 = (LONG_DOUBLE *)a, *p2 = (LONG_DOUBLE *)b;
- LONG_DOUBLE n1 = *p1, n2 = *p2;
-
- if(unlikely(isnan(n1) || isnan(n2))) {
- if(isnan(n1) && !isnan(n2)) return -1;
- if(!isnan(n1) && isnan(n2)) return 1;
- return 0;
- }
- if(unlikely(isinf(n1) || isinf(n2))) {
- if(!isinf(n1) && isinf(n2)) return -1;
- if(isinf(n1) && !isinf(n2)) return 1;
- return 0;
- }
-
- if(unlikely(n1 < n2)) return -1;
- if(unlikely(n1 > n2)) return 1;
- return 0;
-}
-
-inline void sort_series(LONG_DOUBLE *series, size_t entries) {
- qsort(series, entries, sizeof(LONG_DOUBLE), qsort_compare);
-}
-
-inline LONG_DOUBLE *copy_series(const LONG_DOUBLE *series, size_t entries) {
- LONG_DOUBLE *copy = mallocz(sizeof(LONG_DOUBLE) * entries);
- memcpy(copy, series, sizeof(LONG_DOUBLE) * entries);
- return copy;
-}
-
-LONG_DOUBLE median_on_sorted_series(const LONG_DOUBLE *series, size_t entries) {
- if(unlikely(entries == 0))
- return NAN;
-
- if(unlikely(entries == 1))
- return series[0];
-
- if(unlikely(entries == 2))
- return (series[0] + series[1]) / 2;
-
- LONG_DOUBLE avg;
- if(entries % 2 == 0) {
- size_t m = entries / 2;
- avg = (series[m] + series[m + 1]) / 2;
- }
- else {
- avg = series[entries / 2];
- }
-
- return avg;
-}
-
-LONG_DOUBLE median(const LONG_DOUBLE *series, size_t entries) {
- if(unlikely(entries == 0))
- return NAN;
-
- if(unlikely(entries == 1))
- return series[0];
-
- if(unlikely(entries == 2))
- return (series[0] + series[1]) / 2;
-
- LONG_DOUBLE *copy = copy_series(series, entries);
- sort_series(copy, entries);
-
- LONG_DOUBLE avg = median_on_sorted_series(copy, entries);
-
- freez(copy);
- return avg;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-LONG_DOUBLE moving_median(const LONG_DOUBLE *series, size_t entries, size_t period) {
- if(entries <= period)
- return median(series, entries);
-
- LONG_DOUBLE *data = copy_series(series, entries);
-
- size_t i;
- for(i = period; i < entries; i++) {
- data[i - period] = median(&series[i - period], period);
- }
-
- LONG_DOUBLE avg = median(data, entries - period);
- freez(data);
- return avg;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-// http://stackoverflow.com/a/15150143/4525767
-LONG_DOUBLE running_median_estimate(const LONG_DOUBLE *series, size_t entries) {
- LONG_DOUBLE median = 0.0f;
- LONG_DOUBLE average = 0.0f;
- size_t i;
-
- for(i = 0; i < entries ; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
-
- average += ( value - average ) * 0.1f; // rough running average.
- median += copysignl( average * 0.01, value - median );
- }
-
- return median;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-LONG_DOUBLE standard_deviation(const LONG_DOUBLE *series, size_t entries) {
- if(unlikely(entries < 1))
- return NAN;
-
- if(unlikely(entries == 1))
- return series[0];
-
- size_t i, count = 0;
- LONG_DOUBLE sum = 0;
-
- for(i = 0; i < entries ; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
-
- count++;
- sum += value;
- }
-
- if(unlikely(count == 0))
- return NAN;
-
- if(unlikely(count == 1))
- return sum;
-
- LONG_DOUBLE average = sum / (LONG_DOUBLE)count;
-
- for(i = 0, count = 0, sum = 0; i < entries ; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
-
- count++;
- sum += powl(value - average, 2);
- }
-
- if(unlikely(count == 0))
- return NAN;
-
- if(unlikely(count == 1))
- return average;
-
- LONG_DOUBLE variance = sum / (LONG_DOUBLE)(count - 1); // remove -1 to have a population stddev
-
- LONG_DOUBLE stddev = sqrtl(variance);
- return stddev;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-LONG_DOUBLE single_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha) {
- size_t i, count = 0;
- LONG_DOUBLE level = 0, sum = 0;
-
- if(unlikely(isnan(alpha)))
- alpha = 0.3;
-
- for(i = 0; i < entries ; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
- count++;
-
- sum += value;
-
- LONG_DOUBLE last_level = level;
- level = alpha * value + (1.0 - alpha) * last_level;
- }
-
- return level;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-// http://grisha.org/blog/2016/02/16/triple-exponential-smoothing-forecasting-part-ii/
-LONG_DOUBLE double_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE *forecast) {
- size_t i, count = 0;
- LONG_DOUBLE level = series[0], trend, sum;
-
- if(unlikely(isnan(alpha)))
- alpha = 0.3;
-
- if(unlikely(isnan(beta)))
- beta = 0.05;
-
- if(likely(entries > 1))
- trend = series[1] - series[0];
- else
- trend = 0;
-
- sum = series[0];
-
- for(i = 1; i < entries ; i++) {
- LONG_DOUBLE value = series[i];
- if(unlikely(isnan(value) || isinf(value))) continue;
- count++;
-
- sum += value;
-
- LONG_DOUBLE last_level = level;
-
- level = alpha * value + (1.0 - alpha) * (level + trend);
- trend = beta * (level - last_level) + (1.0 - beta) * trend;
- }
-
- if(forecast)
- *forecast = level + trend;
-
- return level;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-/*
- * Based on th R implementation
- *
- * a: level component
- * b: trend component
- * s: seasonal component
- *
- * Additive:
- *
- * Yhat[t+h] = a[t] + h * b[t] + s[t + 1 + (h - 1) mod p],
- * a[t] = α (Y[t] - s[t-p]) + (1-α) (a[t-1] + b[t-1])
- * b[t] = β (a[t] - a[t-1]) + (1-β) b[t-1]
- * s[t] = γ (Y[t] - a[t]) + (1-γ) s[t-p]
- *
- * Multiplicative:
- *
- * Yhat[t+h] = (a[t] + h * b[t]) * s[t + 1 + (h - 1) mod p],
- * a[t] = α (Y[t] / s[t-p]) + (1-α) (a[t-1] + b[t-1])
- * b[t] = β (a[t] - a[t-1]) + (1-β) b[t-1]
- * s[t] = γ (Y[t] / a[t]) + (1-γ) s[t-p]
- */
-static int __HoltWinters(
- const LONG_DOUBLE *series,
- int entries, // start_time + h
-
- LONG_DOUBLE alpha, // alpha parameter of Holt-Winters Filter.
- LONG_DOUBLE beta, // beta parameter of Holt-Winters Filter. If set to 0, the function will do exponential smoothing.
- LONG_DOUBLE gamma, // gamma parameter used for the seasonal component. If set to 0, an non-seasonal model is fitted.
-
- const int *seasonal,
- const int *period,
- const LONG_DOUBLE *a, // Start value for level (a[0]).
- const LONG_DOUBLE *b, // Start value for trend (b[0]).
- LONG_DOUBLE *s, // Vector of start values for the seasonal component (s_1[0] ... s_p[0])
-
- /* return values */
- LONG_DOUBLE *SSE, // The final sum of squared errors achieved in optimizing
- LONG_DOUBLE *level, // Estimated values for the level component (size entries - t + 2)
- LONG_DOUBLE *trend, // Estimated values for the trend component (size entries - t + 2)
- LONG_DOUBLE *season // Estimated values for the seasonal component (size entries - t + 2)
-)
-{
- if(unlikely(entries < 4))
- return 0;
-
- int start_time = 2;
-
- LONG_DOUBLE res = 0, xhat = 0, stmp = 0;
- int i, i0, s0;
-
- /* copy start values to the beginning of the vectors */
- level[0] = *a;
- if(beta > 0) trend[0] = *b;
- if(gamma > 0) memcpy(season, s, *period * sizeof(LONG_DOUBLE));
-
- for(i = start_time - 1; i < entries; i++) {
- /* indices for period i */
- i0 = i - start_time + 2;
- s0 = i0 + *period - 1;
-
- /* forecast *for* period i */
- xhat = level[i0 - 1] + (beta > 0 ? trend[i0 - 1] : 0);
- stmp = gamma > 0 ? season[s0 - *period] : (*seasonal != 1);
- if (*seasonal == 1)
- xhat += stmp;
- else
- xhat *= stmp;
-
- /* Sum of Squared Errors */
- res = series[i] - xhat;
- *SSE += res * res;
-
- /* estimate of level *in* period i */
- if (*seasonal == 1)
- level[i0] = alpha * (series[i] - stmp)
- + (1 - alpha) * (level[i0 - 1] + trend[i0 - 1]);
- else
- level[i0] = alpha * (series[i] / stmp)
- + (1 - alpha) * (level[i0 - 1] + trend[i0 - 1]);
-
- /* estimate of trend *in* period i */
- if (beta > 0)
- trend[i0] = beta * (level[i0] - level[i0 - 1])
- + (1 - beta) * trend[i0 - 1];
-
- /* estimate of seasonal component *in* period i */
- if (gamma > 0) {
- if (*seasonal == 1)
- season[s0] = gamma * (series[i] - level[i0])
- + (1 - gamma) * stmp;
- else
- season[s0] = gamma * (series[i] / level[i0])
- + (1 - gamma) * stmp;
- }
- }
-
- return 1;
-}
-
-LONG_DOUBLE holtwinters(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE gamma, LONG_DOUBLE *forecast) {
- if(unlikely(isnan(alpha)))
- alpha = 0.3;
-
- if(unlikely(isnan(beta)))
- beta = 0.05;
-
- if(unlikely(isnan(gamma)))
- gamma = 0;
-
- int seasonal = 0;
- int period = 0;
- LONG_DOUBLE a0 = series[0];
- LONG_DOUBLE b0 = 0;
- LONG_DOUBLE s[] = {};
-
- LONG_DOUBLE errors = 0.0;
- size_t nb_computations = entries;
- LONG_DOUBLE *estimated_level = callocz(nb_computations, sizeof(LONG_DOUBLE));
- LONG_DOUBLE *estimated_trend = callocz(nb_computations, sizeof(LONG_DOUBLE));
- LONG_DOUBLE *estimated_season = callocz(nb_computations, sizeof(LONG_DOUBLE));
-
- int ret = __HoltWinters(
- series,
- (int)entries,
- alpha,
- beta,
- gamma,
- &seasonal,
- &period,
- &a0,
- &b0,
- s,
- &errors,
- estimated_level,
- estimated_trend,
- estimated_season
- );
-
- LONG_DOUBLE value = estimated_level[nb_computations - 1];
-
- if(forecast)
- *forecast = 0.0;
-
- freez(estimated_level);
- freez(estimated_trend);
- freez(estimated_season);
-
- if(!ret)
- return 0.0;
-
- return value;
-}
diff --git a/src/statistical.h b/src/statistical.h
deleted file mode 100644
index 675389021..000000000
--- a/src/statistical.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef NETDATA_STATISTICAL_H
-#define NETDATA_STATISTICAL_H
-
-extern LONG_DOUBLE average(const LONG_DOUBLE *series, size_t entries);
-extern LONG_DOUBLE moving_average(const LONG_DOUBLE *series, size_t entries, size_t period);
-extern LONG_DOUBLE median(const LONG_DOUBLE *series, size_t entries);
-extern LONG_DOUBLE moving_median(const LONG_DOUBLE *series, size_t entries, size_t period);
-extern LONG_DOUBLE running_median_estimate(const LONG_DOUBLE *series, size_t entries);
-extern LONG_DOUBLE standard_deviation(const LONG_DOUBLE *series, size_t entries);
-extern LONG_DOUBLE single_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha);
-extern LONG_DOUBLE double_exponential_smoothing(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE *forecast);
-extern LONG_DOUBLE holtwinters(const LONG_DOUBLE *series, size_t entries, LONG_DOUBLE alpha, LONG_DOUBLE beta, LONG_DOUBLE gamma, LONG_DOUBLE *forecast);
-extern LONG_DOUBLE sum_and_count(const LONG_DOUBLE *series, size_t entries, size_t *count);
-extern LONG_DOUBLE sum(const LONG_DOUBLE *series, size_t entries);
-extern LONG_DOUBLE median_on_sorted_series(const LONG_DOUBLE *series, size_t entries);
-extern LONG_DOUBLE *copy_series(const LONG_DOUBLE *series, size_t entries);
-extern void sort_series(LONG_DOUBLE *series, size_t entries);
-
-#endif //NETDATA_STATISTICAL_H
diff --git a/src/statsd.c b/src/statsd.c
deleted file mode 100644
index 44ebd8894..000000000
--- a/src/statsd.c
+++ /dev/null
@@ -1,2499 +0,0 @@
-#include "common.h"
-
-#define STATSD_CHART_PREFIX "statsd"
-#define STATSD_CHART_PRIORITY 90000
-
-// --------------------------------------------------------------------------------------
-
-// #define STATSD_MULTITHREADED 1
-
-#ifdef STATSD_MULTITHREADED
-// DO NOT ENABLE MULTITHREADING - IT IS NOT WELL TESTED
-#define STATSD_AVL_TREE avl_tree_lock
-#define STATSD_AVL_INSERT avl_insert_lock
-#define STATSD_AVL_SEARCH avl_search_lock
-#define STATSD_AVL_INDEX_INIT { .avl_tree = { NULL, statsd_metric_compare }, .rwlock = AVL_LOCK_INITIALIZER }
-#define STATSD_FIRST_PTR_MUTEX netdata_mutex_t first_mutex
-#define STATSD_FIRST_PTR_MUTEX_INIT .first_mutex = NETDATA_MUTEX_INITIALIZER
-#define STATSD_FIRST_PTR_MUTEX_LOCK(index) netdata_mutex_lock(&((index)->first_mutex))
-#define STATSD_FIRST_PTR_MUTEX_UNLOCK(index) netdata_mutex_unlock(&((index)->first_mutex))
-#define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_DEFAULT
-#else
-#define STATSD_AVL_TREE avl_tree
-#define STATSD_AVL_INSERT avl_insert
-#define STATSD_AVL_SEARCH avl_search
-#define STATSD_AVL_INDEX_INIT { .root = NULL, .compar = statsd_metric_compare }
-#define STATSD_FIRST_PTR_MUTEX
-#define STATSD_FIRST_PTR_MUTEX_INIT
-#define STATSD_FIRST_PTR_MUTEX_LOCK(index)
-#define STATSD_FIRST_PTR_MUTEX_UNLOCK(index)
-#define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_SINGLE_THREADED
-#endif
-
-#define STATSD_DECIMAL_DETAIL 1000 // floating point values get multiplied by this, with the same divisor
-
-// --------------------------------------------------------------------------------------------------------------------
-// data specific to each metric type
-
-typedef struct statsd_metric_gauge {
- LONG_DOUBLE value;
-} STATSD_METRIC_GAUGE;
-
-typedef struct statsd_metric_counter { // counter and meter
- long long value;
-} STATSD_METRIC_COUNTER;
-
-typedef struct statsd_histogram_extensions {
- netdata_mutex_t mutex;
-
- // average is stored in metric->last
- collected_number last_min;
- collected_number last_max;
- collected_number last_percentile;
- collected_number last_median;
- collected_number last_stddev;
- collected_number last_sum;
-
- int zeroed;
-
- RRDDIM *rd_min;
- RRDDIM *rd_max;
- RRDDIM *rd_percentile;
- RRDDIM *rd_median;
- RRDDIM *rd_stddev;
- RRDDIM *rd_sum;
-
- size_t size;
- size_t used;
- LONG_DOUBLE *values; // dynamic array of values collected
-} STATSD_METRIC_HISTOGRAM_EXTENSIONS;
-
-typedef struct statsd_metric_histogram { // histogram and timer
- STATSD_METRIC_HISTOGRAM_EXTENSIONS *ext;
-} STATSD_METRIC_HISTOGRAM;
-
-typedef struct statsd_metric_set {
- DICTIONARY *dict;
- size_t unique;
-} STATSD_METRIC_SET;
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// this is a metric - for all types of metrics
-
-typedef enum statsd_metric_options {
- STATSD_METRIC_OPTION_NONE = 0x00000000, // no options set
- STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED = 0x00000001, // do not update the chart dimension, when this metric is not collected
- STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED = 0x00000002, // render a private chart for this metric
- STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED = 0x00000004, // the metric has been checked if it should get private chart or not
- STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT = 0x00000008, // show the count of events for this private chart
- STATSD_METRIC_OPTION_CHECKED_IN_APPS = 0x00000010, // set when this metric has been checked agains apps
-} STATS_METRIC_OPTIONS;
-
-typedef enum statsd_metric_type {
- STATSD_METRIC_TYPE_GAUGE,
- STATSD_METRIC_TYPE_COUNTER,
- STATSD_METRIC_TYPE_METER,
- STATSD_METRIC_TYPE_TIMER,
- STATSD_METRIC_TYPE_HISTOGRAM,
- STATSD_METRIC_TYPE_SET
-} STATSD_METRIC_TYPE;
-
-
-typedef struct statsd_metric {
- avl avl; // indexing
-
- const char *name; // the name of the metric
- uint32_t hash; // hash of the name
-
- STATSD_METRIC_TYPE type;
-
- // metadata about data collection
- collected_number events; // the number of times this metric has been collected (never resets)
- size_t count; // the number of times this metric has been collected since the last flush
-
- // the actual collected data
- union {
- STATSD_METRIC_GAUGE gauge;
- STATSD_METRIC_COUNTER counter;
- STATSD_METRIC_HISTOGRAM histogram;
- STATSD_METRIC_SET set;
- };
-
- // chart related members
- STATS_METRIC_OPTIONS options; // STATSD_METRIC_OPTION_* (bitfield)
- char reset; // set to 1 to reset this metric to zero
- collected_number last; // the last value sent to netdata
- RRDSET *st; // the chart of this metric
- RRDDIM *rd_value; // the dimension of this metric value
- RRDDIM *rd_count; // the dimension for the number of events received
-
- // linking, used for walking through all metrics
- struct statsd_metric *next;
-} STATSD_METRIC;
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// each type of metric has its own index
-
-typedef struct statsd_index {
- char *name; // the name of the index of metrics
- size_t events; // the number of events processed for this index
- size_t metrics; // the number of metrics in this index
-
- STATSD_AVL_TREE index; // the AVL tree
-
- STATSD_METRIC *first; // the linked list of metrics (new metrics are added in front)
- STATSD_FIRST_PTR_MUTEX; // when mutli-threading is enabled, a lock to protect the linked list
-
- STATS_METRIC_OPTIONS default_options; // default options for all metrics in this index
-} STATSD_INDEX;
-
-static int statsd_metric_compare(void* a, void* b);
-
-// --------------------------------------------------------------------------------------------------------------------
-// synthetic charts
-
-typedef enum statsd_app_chart_dimension_value_type {
- STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS,
- STATSD_APP_CHART_DIM_VALUE_TYPE_LAST,
- STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE,
- STATSD_APP_CHART_DIM_VALUE_TYPE_SUM,
- STATSD_APP_CHART_DIM_VALUE_TYPE_MIN,
- STATSD_APP_CHART_DIM_VALUE_TYPE_MAX,
- STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE,
- STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN,
- STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV
-} STATSD_APP_CHART_DIM_VALUE_TYPE;
-
-typedef struct statsd_app_chart_dimension {
- const char *name; // the name of this dimension
- const char *metric; // the source metric name of this dimension
- uint32_t metric_hash; // hash for fast string comparisons
-
- SIMPLE_PATTERN *metric_pattern; // set when the 'metric' is a simple pattern
-
- collected_number multiplier; // the multipler of the dimension
- collected_number divisor; // the divisor of the dimension
- RRDDIM_FLAGS flags; // the RRDDIM flags for this dimension
-
- STATSD_APP_CHART_DIM_VALUE_TYPE value_type; // which value to use of the source metric
-
- RRDDIM *rd; // a pointer to the RRDDIM that has been created for this dimension
- collected_number *value_ptr; // a pointer to the source metric value
- RRD_ALGORITHM algorithm; // the algorithm of this dimension
-
- struct statsd_app_chart_dimension *next; // the next dimension for this chart
-} STATSD_APP_CHART_DIM;
-
-typedef struct statsd_app_chart {
- const char *source;
- const char *id;
- const char *name;
- const char *title;
- const char *family;
- const char *context;
- const char *units;
- long priority;
- RRDSET_TYPE chart_type;
- STATSD_APP_CHART_DIM *dimensions;
- size_t dimensions_count;
- size_t dimensions_linked_count;
-
- RRDSET *st;
- struct statsd_app_chart *next;
-} STATSD_APP_CHART;
-
-typedef struct statsd_app {
- const char *name;
- SIMPLE_PATTERN *metrics;
- STATS_METRIC_OPTIONS default_options;
- RRD_MEMORY_MODE rrd_memory_mode;
- DICTIONARY *dict;
- long rrd_history_entries;
-
- const char *source;
- STATSD_APP_CHART *charts;
- struct statsd_app *next;
-} STATSD_APP;
-
-// --------------------------------------------------------------------------------------------------------------------
-// global statsd data
-
-struct collection_thread_status {
- int status;
- size_t max_sockets;
-
- netdata_thread_t thread;
- struct rusage rusage;
- RRDSET *st_cpu;
- RRDDIM *rd_user;
- RRDDIM *rd_system;
-};
-
-static struct statsd {
- STATSD_INDEX gauges;
- STATSD_INDEX counters;
- STATSD_INDEX timers;
- STATSD_INDEX histograms;
- STATSD_INDEX meters;
- STATSD_INDEX sets;
- size_t unknown_types;
- size_t socket_errors;
- size_t tcp_socket_connects;
- size_t tcp_socket_disconnects;
- size_t tcp_socket_connected;
- size_t tcp_socket_reads;
- size_t tcp_packets_received;
- size_t tcp_bytes_read;
- size_t udp_socket_reads;
- size_t udp_packets_received;
- size_t udp_bytes_read;
-
- int enabled;
- int update_every;
- SIMPLE_PATTERN *charts_for;
-
- size_t tcp_idle_timeout;
- size_t decimal_detail;
- size_t private_charts;
- size_t max_private_charts;
- size_t max_private_charts_hard;
- RRD_MEMORY_MODE private_charts_memory_mode;
- long private_charts_rrd_history_entries;
- int private_charts_hidden;
-
- STATSD_APP *apps;
- size_t recvmmsg_size;
- size_t histogram_increase_step;
- double histogram_percentile;
- char *histogram_percentile_str;
-
- int threads;
- struct collection_thread_status *collection_threads_status;
-
- LISTEN_SOCKETS sockets;
-} statsd = {
- .enabled = 1,
- .max_private_charts = 200,
- .max_private_charts_hard = 1000,
- .private_charts_hidden = 0,
- .recvmmsg_size = 10,
- .decimal_detail = STATSD_DECIMAL_DETAIL,
-
- .gauges = {
- .name = "gauge",
- .events = 0,
- .metrics = 0,
- .index = STATSD_AVL_INDEX_INIT,
- .default_options = STATSD_METRIC_OPTION_NONE,
- .first = NULL,
- STATSD_FIRST_PTR_MUTEX_INIT
- },
- .counters = {
- .name = "counter",
- .events = 0,
- .metrics = 0,
- .index = STATSD_AVL_INDEX_INIT,
- .default_options = STATSD_METRIC_OPTION_NONE,
- .first = NULL,
- STATSD_FIRST_PTR_MUTEX_INIT
- },
- .timers = {
- .name = "timer",
- .events = 0,
- .metrics = 0,
- .index = STATSD_AVL_INDEX_INIT,
- .default_options = STATSD_METRIC_OPTION_NONE,
- .first = NULL,
- STATSD_FIRST_PTR_MUTEX_INIT
- },
- .histograms = {
- .name = "histogram",
- .events = 0,
- .metrics = 0,
- .index = STATSD_AVL_INDEX_INIT,
- .default_options = STATSD_METRIC_OPTION_NONE,
- .first = NULL,
- STATSD_FIRST_PTR_MUTEX_INIT
- },
- .meters = {
- .name = "meter",
- .events = 0,
- .metrics = 0,
- .index = STATSD_AVL_INDEX_INIT,
- .default_options = STATSD_METRIC_OPTION_NONE,
- .first = NULL,
- STATSD_FIRST_PTR_MUTEX_INIT
- },
- .sets = {
- .name = "set",
- .events = 0,
- .metrics = 0,
- .index = STATSD_AVL_INDEX_INIT,
- .default_options = STATSD_METRIC_OPTION_NONE,
- .first = NULL,
- STATSD_FIRST_PTR_MUTEX_INIT
- },
-
- .tcp_idle_timeout = 600,
-
- .apps = NULL,
- .histogram_percentile = 95.0,
- .histogram_increase_step = 10,
- .threads = 0,
- .collection_threads_status = NULL,
- .sockets = {
- .config_section = CONFIG_SECTION_STATSD,
- .default_bind_to = "udp:localhost tcp:localhost",
- .default_port = STATSD_LISTEN_PORT,
- .backlog = STATSD_LISTEN_BACKLOG
- },
-};
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd index management - add/find metrics
-
-static int statsd_metric_compare(void* a, void* b) {
- if(((STATSD_METRIC *)a)->hash < ((STATSD_METRIC *)b)->hash) return -1;
- else if(((STATSD_METRIC *)a)->hash > ((STATSD_METRIC *)b)->hash) return 1;
- else return strcmp(((STATSD_METRIC *)a)->name, ((STATSD_METRIC *)b)->name);
-}
-
-static inline STATSD_METRIC *statsd_metric_index_find(STATSD_INDEX *index, const char *name, uint32_t hash) {
- STATSD_METRIC tmp;
- tmp.name = name;
- tmp.hash = (hash)?hash:simple_hash(tmp.name);
-
- return (STATSD_METRIC *)STATSD_AVL_SEARCH(&index->index, (avl *)&tmp);
-}
-
-static inline STATSD_METRIC *statsd_find_or_add_metric(STATSD_INDEX *index, const char *name, STATSD_METRIC_TYPE type) {
- debug(D_STATSD, "searching for metric '%s' under '%s'", name, index->name);
-
- uint32_t hash = simple_hash(name);
-
- STATSD_METRIC *m = statsd_metric_index_find(index, name, hash);
- if(unlikely(!m)) {
- debug(D_STATSD, "Creating new %s metric '%s'", index->name, name);
-
- m = (STATSD_METRIC *)callocz(sizeof(STATSD_METRIC), 1);
- m->name = strdupz(name);
- m->hash = hash;
- m->type = type;
- m->options = index->default_options;
-
- if(type == STATSD_METRIC_TYPE_HISTOGRAM || type == STATSD_METRIC_TYPE_TIMER) {
- m->histogram.ext = callocz(sizeof(STATSD_METRIC_HISTOGRAM_EXTENSIONS), 1);
- netdata_mutex_init(&m->histogram.ext->mutex);
- }
- STATSD_METRIC *n = (STATSD_METRIC *)STATSD_AVL_INSERT(&index->index, (avl *)m);
- if(unlikely(n != m)) {
- freez((void *)m->histogram.ext);
- freez((void *)m->name);
- freez((void *)m);
- m = n;
- }
- else {
- STATSD_FIRST_PTR_MUTEX_LOCK(index);
- index->metrics++;
- m->next = index->first;
- index->first = m;
- STATSD_FIRST_PTR_MUTEX_UNLOCK(index);
- }
- }
-
- index->events++;
- return m;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd parsing numbers
-
-static inline LONG_DOUBLE statsd_parse_float(const char *v, LONG_DOUBLE def) {
- LONG_DOUBLE value;
-
- if(likely(v && *v)) {
- char *e = NULL;
- value = str2ld(v, &e);
- if(unlikely(e && *e))
- error("STATSD: excess data '%s' after value '%s'", e, v);
- }
- else
- value = def;
-
- return value;
-}
-
-static inline long long statsd_parse_int(const char *v, long long def) {
- long long value;
-
- if(likely(v && *v)) {
- char *e = NULL;
- value = str2ll(v, &e);
- if(unlikely(e && *e))
- error("STATSD: excess data '%s' after value '%s'", e, v);
- }
- else
- value = def;
-
- return value;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd processors per metric type
-
-static inline void statsd_reset_metric(STATSD_METRIC *m) {
- m->reset = 0;
- m->count = 0;
-}
-
-static inline int value_is_zinit(const char *value) {
- return (value && *value == 'z' && *++value == 'i' && *++value == 'n' && *++value == 'i' && *++value == 't' && *++value == '\0');
-}
-
-static inline void statsd_process_gauge(STATSD_METRIC *m, const char *value, const char *sampling) {
- if(unlikely(!value || !*value)) {
- error("STATSD: metric '%s' of type gauge, with empty value is ignored.", m->name);
- return;
- }
-
- if(unlikely(m->reset)) {
- // no need to reset anything specific for gauges
- statsd_reset_metric(m);
- }
-
- if(unlikely(value_is_zinit(value))) {
- // magic loading of metric, without affecting anything
- }
- else {
- if (unlikely(*value == '+' || *value == '-'))
- m->gauge.value += statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0);
- else
- m->gauge.value = statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0);
-
- m->events++;
- m->count++;
- }
-}
-
-static inline void statsd_process_counter(STATSD_METRIC *m, const char *value, const char *sampling) {
- // we accept empty values for counters
-
- if(unlikely(m->reset)) statsd_reset_metric(m);
-
- if(unlikely(value_is_zinit(value))) {
- // magic loading of metric, without affecting anything
- }
- else {
- m->counter.value += llrintl((LONG_DOUBLE) statsd_parse_int(value, 1) / statsd_parse_float(sampling, 1.0));
-
- m->events++;
- m->count++;
- }
-}
-
-static inline void statsd_process_meter(STATSD_METRIC *m, const char *value, const char *sampling) {
- // this is the same with the counter
- statsd_process_counter(m, value, sampling);
-}
-
-static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value, const char *sampling) {
- if(unlikely(!value || !*value)) {
- error("STATSD: metric '%s' of type histogram, with empty value is ignored.", m->name);
- return;
- }
-
- if(unlikely(m->reset)) {
- m->histogram.ext->used = 0;
- statsd_reset_metric(m);
- }
-
- if(unlikely(value_is_zinit(value))) {
- // magic loading of metric, without affecting anything
- }
- else {
- if (unlikely(m->histogram.ext->used == m->histogram.ext->size)) {
- netdata_mutex_lock(&m->histogram.ext->mutex);
- m->histogram.ext->size += statsd.histogram_increase_step;
- m->histogram.ext->values = reallocz(m->histogram.ext->values, sizeof(LONG_DOUBLE) * m->histogram.ext->size);
- netdata_mutex_unlock(&m->histogram.ext->mutex);
- }
-
- m->histogram.ext->values[m->histogram.ext->used++] = statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0);
-
- m->events++;
- m->count++;
- }
-}
-
-static inline void statsd_process_timer(STATSD_METRIC *m, const char *value, const char *sampling) {
- if(unlikely(!value || !*value)) {
- error("STATSD: metric of type timer, with empty value is ignored.");
- return;
- }
-
- // timers are a use case of histogram
- statsd_process_histogram(m, value, sampling);
-}
-
-static inline void statsd_process_set(STATSD_METRIC *m, const char *value) {
- if(unlikely(!value || !*value)) {
- error("STATSD: metric of type set, with empty value is ignored.");
- return;
- }
-
- if(unlikely(m->reset)) {
- if(likely(m->set.dict)) {
- dictionary_destroy(m->set.dict);
- m->set.dict = NULL;
- }
- statsd_reset_metric(m);
- }
-
- if (unlikely(!m->set.dict)) {
- m->set.dict = dictionary_create(STATSD_DICTIONARY_OPTIONS | DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE);
- m->set.unique = 0;
- }
-
- if(unlikely(value_is_zinit(value))) {
- // magic loading of metric, without affecting anything
- }
- else {
- void *t = dictionary_get(m->set.dict, value);
- if (unlikely(!t)) {
- dictionary_set(m->set.dict, value, NULL, 1);
- m->set.unique++;
- }
-
- m->events++;
- m->count++;
- }
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd parsing
-
-static void statsd_process_metric(const char *name, const char *value, const char *type, const char *sampling) {
- debug(D_STATSD, "STATSD: raw metric '%s', value '%s', type '%s', rate '%s'", name?name:"(null)", value?value:"(null)", type?type:"(null)", sampling?sampling:"(null)");
-
- if(unlikely(!name || !*name)) return;
- if(unlikely(!type || !*type)) type = "m";
-
- char t0 = type[0], t1 = type[1];
-
- if(unlikely(t0 == 'g' && t1 == '\0')) {
- statsd_process_gauge(
- statsd_find_or_add_metric(&statsd.gauges, name, STATSD_METRIC_TYPE_GAUGE),
- value, sampling);
- }
- else if(unlikely((t0 == 'c' || t0 == 'C') && t1 == '\0')) {
- // etsy/statsd uses 'c'
- // brubeck uses 'C'
- statsd_process_counter(
- statsd_find_or_add_metric(&statsd.counters, name, STATSD_METRIC_TYPE_COUNTER),
- value, sampling);
- }
- else if(unlikely(t0 == 'm' && t1 == '\0')) {
- statsd_process_meter(
- statsd_find_or_add_metric(&statsd.meters, name, STATSD_METRIC_TYPE_METER),
- value, sampling);
- }
- else if(unlikely(t0 == 'h' && t1 == '\0')) {
- statsd_process_histogram(
- statsd_find_or_add_metric(&statsd.histograms, name, STATSD_METRIC_TYPE_HISTOGRAM),
- value, sampling);
- }
- else if(unlikely(t0 == 's' && t1 == '\0')) {
- statsd_process_set(
- statsd_find_or_add_metric(&statsd.sets, name, STATSD_METRIC_TYPE_SET),
- value);
- }
- else if(unlikely(t0 == 'm' && t1 == 's' && type[2] == '\0')) {
- statsd_process_timer(
- statsd_find_or_add_metric(&statsd.timers, name, STATSD_METRIC_TYPE_TIMER),
- value, sampling);
- }
- else {
- statsd.unknown_types++;
- error("STATSD: metric '%s' with value '%s' is sent with unknown metric type '%s'", name, value?value:"", type);
- }
-}
-
-static inline const char *statsd_parse_skip_up_to(const char *s, char d1, char d2) {
- char c;
-
- for(c = *s; c && c != d1 && c != d2 && c != '\r' && c != '\n'; c = *++s) ;
-
- return s;
-}
-
-const char *statsd_parse_skip_spaces(const char *s) {
- char c;
-
- for(c = *s; c && ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); c = *++s) ;
-
- return s;
-}
-
-static inline const char *statsd_parse_field_trim(const char *start, char *end) {
- if(unlikely(!start)) {
- start = end;
- return start;
- }
-
- while(start <= end && (*start == ' ' || *start == '\t'))
- start++;
-
- *end = '\0';
- end--;
- while(end >= start && (*end == ' ' || *end == '\t'))
- *end-- = '\0';
-
- return start;
-}
-
-static inline size_t statsd_process(char *buffer, size_t size, int require_newlines) {
- buffer[size] = '\0';
- debug(D_STATSD, "RECEIVED: %zu bytes: '%s'", size, buffer);
-
- const char *s = buffer;
- while(*s) {
- const char *name = NULL, *value = NULL, *type = NULL, *sampling = NULL;
- char *name_end = NULL, *value_end = NULL, *type_end = NULL, *sampling_end = NULL;
-
- s = name_end = (char *)statsd_parse_skip_up_to(name = s, ':', '|');
- if(name == name_end) {
- s = statsd_parse_skip_spaces(s);
- continue;
- }
-
- if(likely(*s == ':'))
- s = value_end = (char *) statsd_parse_skip_up_to(value = ++s, '|', '|');
-
- if(likely(*s == '|'))
- s = type_end = (char *) statsd_parse_skip_up_to(type = ++s, '|', '@');
-
- if(likely(*s == '|' || *s == '@')) {
- s = sampling_end = (char *) statsd_parse_skip_up_to(sampling = ++s, '\r', '\n');
- if(*sampling == '@') sampling++;
- }
-
- // skip everything until the end of the line
- while(*s && *s != '\n') s++;
-
- if(unlikely(require_newlines && *s != '\n' && s > buffer)) {
- // move the remaining data to the beginning
- size -= (name - buffer);
- memmove(buffer, name, size);
- return size;
- }
- else
- s = statsd_parse_skip_spaces(s);
-
- statsd_process_metric(
- statsd_parse_field_trim(name, name_end)
- , statsd_parse_field_trim(value, value_end)
- , statsd_parse_field_trim(type, type_end)
- , statsd_parse_field_trim(sampling, sampling_end)
- );
- }
-
- return 0;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd pollfd interface
-
-#define STATSD_TCP_BUFFER_SIZE 65536 // minimize tcp reads
-#define STATSD_UDP_BUFFER_SIZE 9000 // this should be up to MTU
-
-typedef enum {
- STATSD_SOCKET_DATA_TYPE_TCP,
- STATSD_SOCKET_DATA_TYPE_UDP
-} STATSD_SOCKET_DATA_TYPE;
-
-struct statsd_tcp {
- STATSD_SOCKET_DATA_TYPE type;
- size_t size;
- size_t len;
- char buffer[];
-};
-
-#ifdef HAVE_RECVMMSG
-struct statsd_udp {
- int *running;
- STATSD_SOCKET_DATA_TYPE type;
- size_t size;
- struct iovec *iovecs;
- struct mmsghdr *msgs;
-};
-#else
-struct statsd_udp {
- int *running;
- STATSD_SOCKET_DATA_TYPE type;
- char buffer[STATSD_UDP_BUFFER_SIZE];
-};
-#endif
-
-// new TCP client connected
-static void *statsd_add_callback(POLLINFO *pi, short int *events, void *data) {
- (void)pi;
- (void)data;
-
- *events = POLLIN;
-
- struct statsd_tcp *t = (struct statsd_tcp *)callocz(sizeof(struct statsd_tcp) + STATSD_TCP_BUFFER_SIZE, 1);
- t->type = STATSD_SOCKET_DATA_TYPE_TCP;
- t->size = STATSD_TCP_BUFFER_SIZE - 1;
- statsd.tcp_socket_connects++;
- statsd.tcp_socket_connected++;
-
- return t;
-}
-
-// TCP client disconnected
-static void statsd_del_callback(POLLINFO *pi) {
- struct statsd_tcp *t = pi->data;
-
- if(likely(t)) {
- if(t->type == STATSD_SOCKET_DATA_TYPE_TCP) {
- if(t->len != 0) {
- statsd.socket_errors++;
- error("STATSD: client is probably sending unterminated metrics. Closed socket left with '%s'. Trying to process it.", t->buffer);
- statsd_process(t->buffer, t->len, 0);
- }
- statsd.tcp_socket_disconnects++;
- statsd.tcp_socket_connected--;
- }
- else
- error("STATSD: internal error: received socket data type is %d, but expected %d", (int)t->type, (int)STATSD_SOCKET_DATA_TYPE_TCP);
-
- freez(t);
- }
-}
-
-// Receive data
-static int statsd_rcv_callback(POLLINFO *pi, short int *events) {
- *events = POLLIN;
-
- int fd = pi->fd;
-
- switch(pi->socktype) {
- case SOCK_STREAM: {
- struct statsd_tcp *d = (struct statsd_tcp *)pi->data;
- if(unlikely(!d)) {
- error("STATSD: internal error: expected TCP data pointer is NULL");
- statsd.socket_errors++;
- return -1;
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(d->type != STATSD_SOCKET_DATA_TYPE_TCP)) {
- error("STATSD: internal error: socket data type should be %d, but it is %d", (int)STATSD_SOCKET_DATA_TYPE_TCP, (int)d->type);
- statsd.socket_errors++;
- return -1;
- }
-#endif
-
- int ret = 0;
- ssize_t rc;
- do {
- rc = recv(fd, &d->buffer[d->len], d->size - d->len, MSG_DONTWAIT);
- if (rc < 0) {
- // read failed
- if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
- error("STATSD: recv() on TCP socket %d failed.", fd);
- statsd.socket_errors++;
- ret = -1;
- }
- }
- else if (!rc) {
- // connection closed
- debug(D_STATSD, "STATSD: client disconnected.");
- ret = -1;
- }
- else {
- // data received
- d->len += rc;
- statsd.tcp_socket_reads++;
- statsd.tcp_bytes_read += rc;
- }
-
- if(likely(d->len > 0)) {
- statsd.tcp_packets_received++;
- d->len = statsd_process(d->buffer, d->len, 1);
- }
-
- if(unlikely(ret == -1))
- return -1;
-
- } while (rc != -1);
- break;
- }
-
- case SOCK_DGRAM: {
- struct statsd_udp *d = (struct statsd_udp *)pi->data;
- if(unlikely(!d)) {
- error("STATSD: internal error: expected UDP data pointer is NULL");
- statsd.socket_errors++;
- return -1;
- }
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(d->type != STATSD_SOCKET_DATA_TYPE_UDP)) {
- error("STATSD: internal error: socket data should be %d, but it is %d", (int)d->type, (int)STATSD_SOCKET_DATA_TYPE_UDP);
- statsd.socket_errors++;
- return -1;
- }
-#endif
-
-#ifdef HAVE_RECVMMSG
- ssize_t rc;
- do {
- rc = recvmmsg(fd, d->msgs, (unsigned int)d->size, MSG_DONTWAIT, NULL);
- if (rc < 0) {
- // read failed
- if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
- error("STATSD: recvmmsg() on UDP socket %d failed.", fd);
- statsd.socket_errors++;
- return -1;
- }
- } else if (rc) {
- // data received
- statsd.udp_socket_reads++;
- statsd.udp_packets_received += rc;
-
- size_t i;
- for (i = 0; i < (size_t)rc; ++i) {
- size_t len = (size_t)d->msgs[i].msg_len;
- statsd.udp_bytes_read += len;
- statsd_process(d->msgs[i].msg_hdr.msg_iov->iov_base, len, 0);
- }
- }
- } while (rc != -1);
-
-#else // !HAVE_RECVMMSG
- ssize_t rc;
- do {
- rc = recv(fd, d->buffer, STATSD_UDP_BUFFER_SIZE - 1, MSG_DONTWAIT);
- if (rc < 0) {
- // read failed
- if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
- error("STATSD: recv() on UDP socket %d failed.", fd);
- statsd.socket_errors++;
- return -1;
- }
- } else if (rc) {
- // data received
- statsd.udp_socket_reads++;
- statsd.udp_packets_received++;
- statsd.udp_bytes_read += rc;
- statsd_process(d->buffer, (size_t) rc, 0);
- }
- } while (rc != -1);
-#endif
-
- break;
- }
-
- default: {
- error("STATSD: internal error: unknown socktype %d on socket %d", pi->socktype, fd);
- statsd.socket_errors++;
- return -1;
- }
- }
-
- return 0;
-}
-
-static int statsd_snd_callback(POLLINFO *pi, short int *events) {
- (void)pi;
- (void)events;
-
- error("STATSD: snd_callback() called, but we never requested to send data to statsd clients.");
- return -1;
-}
-
-static void statsd_timer_callback(void *timer_data) {
- struct collection_thread_status *status = timer_data;
- getrusage(RUSAGE_THREAD, &status->rusage);
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd child thread to collect metrics from network
-
-void statsd_collector_thread_cleanup(void *data) {
- struct statsd_udp *d = data;
- *d->running = 0;
-
- info("cleaning up...");
-
-#ifdef HAVE_RECVMMSG
- size_t i;
- for (i = 0; i < d->size; i++)
- freez(d->iovecs[i].iov_base);
-
- freez(d->iovecs);
- freez(d->msgs);
-#endif
-
- freez(d);
-}
-
-void *statsd_collector_thread(void *ptr) {
- struct collection_thread_status *status = ptr;
- status->status = 1;
-
- info("STATSD collector thread started with taskid %d", gettid());
-
- struct statsd_udp *d = callocz(sizeof(struct statsd_udp), 1);
- d->running = &status->status;
-
- netdata_thread_cleanup_push(statsd_collector_thread_cleanup, d);
-
-#ifdef HAVE_RECVMMSG
- d->type = STATSD_SOCKET_DATA_TYPE_UDP;
- d->size = statsd.recvmmsg_size;
- d->iovecs = callocz(sizeof(struct iovec), d->size);
- d->msgs = callocz(sizeof(struct mmsghdr), d->size);
-
- size_t i;
- for (i = 0; i < d->size; i++) {
- d->iovecs[i].iov_base = mallocz(STATSD_UDP_BUFFER_SIZE);
- d->iovecs[i].iov_len = STATSD_UDP_BUFFER_SIZE - 1;
- d->msgs[i].msg_hdr.msg_iov = &d->iovecs[i];
- d->msgs[i].msg_hdr.msg_iovlen = 1;
- }
-#endif
-
- poll_events(&statsd.sockets
- , statsd_add_callback
- , statsd_del_callback
- , statsd_rcv_callback
- , statsd_snd_callback
- , statsd_timer_callback
- , NULL
- , (void *)d
- , 0 // tcp request timeout, 0 = disabled
- , statsd.tcp_idle_timeout // tcp idle timeout, 0 = disabled
- , statsd.update_every * 1000
- , ptr // timer_data
- , status->max_sockets
- );
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd applications configuration files parsing
-
-#define STATSD_CONF_LINE_MAX 8192
-
-static STATSD_APP_CHART_DIM_VALUE_TYPE string2valuetype(const char *type, size_t line, const char *path, const char *filename) {
- if(!type || !*type) type = "last";
-
- if(!strcmp(type, "events")) return STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS;
- else if(!strcmp(type, "last")) return STATSD_APP_CHART_DIM_VALUE_TYPE_LAST;
- else if(!strcmp(type, "min")) return STATSD_APP_CHART_DIM_VALUE_TYPE_MIN;
- else if(!strcmp(type, "max")) return STATSD_APP_CHART_DIM_VALUE_TYPE_MAX;
- else if(!strcmp(type, "sum")) return STATSD_APP_CHART_DIM_VALUE_TYPE_SUM;
- else if(!strcmp(type, "average")) return STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE;
- else if(!strcmp(type, "median")) return STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN;
- else if(!strcmp(type, "stddev")) return STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV;
- else if(!strcmp(type, "percentile")) return STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE;
-
- error("STATSD: invalid type '%s' at line %zu of file '%s/%s'. Using 'last'.", type, line, path, filename);
- return STATSD_APP_CHART_DIM_VALUE_TYPE_LAST;
-}
-
-static const char *valuetype2string(STATSD_APP_CHART_DIM_VALUE_TYPE type) {
- switch(type) {
- case STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS: return "events";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_LAST: return "last";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_MIN: return "min";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_MAX: return "max";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_SUM: return "sum";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE: return "average";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN: return "median";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV: return "stddev";
- case STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE: return "percentile";
- }
-
- return "unknown";
-}
-
-static STATSD_APP_CHART_DIM *add_dimension_to_app_chart(
- STATSD_APP *app
- , STATSD_APP_CHART *chart
- , const char *metric_name
- , const char *dim_name
- , collected_number multiplier
- , collected_number divisor
- , RRDDIM_FLAGS flags
- , STATSD_APP_CHART_DIM_VALUE_TYPE value_type
-) {
- STATSD_APP_CHART_DIM *dim = callocz(sizeof(STATSD_APP_CHART_DIM), 1);
-
- dim->metric = strdupz(metric_name);
- dim->metric_hash = simple_hash(dim->metric);
-
- dim->name = strdupz((dim_name)?dim_name:"");
- dim->multiplier = multiplier;
- dim->divisor = divisor;
- dim->value_type = value_type;
- dim->flags = flags;
-
- if(!dim->multiplier)
- dim->multiplier = 1;
-
- if(!dim->divisor)
- dim->divisor = 1;
-
- // append it to the list of dimension
- STATSD_APP_CHART_DIM *tdim;
- for(tdim = chart->dimensions; tdim && tdim->next ; tdim = tdim->next) ;
- if(!tdim) {
- dim->next = chart->dimensions;
- chart->dimensions = dim;
- }
- else {
- dim->next = tdim->next;
- tdim->next = dim;
- }
- chart->dimensions_count++;
-
- debug(D_STATSD, "Added dimension '%s' to chart '%s' of app '%s', for metric '%s', with type %u, multiplier " COLLECTED_NUMBER_FORMAT ", divisor " COLLECTED_NUMBER_FORMAT,
- dim->name, chart->id, app->name, dim->metric, dim->value_type, dim->multiplier, dim->divisor);
-
- return dim;
-}
-
-static int statsd_readfile(const char *path, const char *filename, STATSD_APP *app, STATSD_APP_CHART *chart, DICTIONARY *dict) {
- debug(D_STATSD, "STATSD configuration reading file '%s/%s'", path, filename);
-
- char *buffer = mallocz(STATSD_CONF_LINE_MAX + 1);
-
- if(filename[0] == '/')
- strncpyz(buffer, filename, STATSD_CONF_LINE_MAX);
- else
- snprintfz(buffer, STATSD_CONF_LINE_MAX, "%s/%s", path, filename);
-
- FILE *fp = fopen(buffer, "r");
- if(!fp) {
- error("STATSD: cannot open file '%s'.", buffer);
- freez(buffer);
- return -1;
- }
-
- size_t line = 0;
- char *s;
- while(fgets(buffer, STATSD_CONF_LINE_MAX, fp) != NULL) {
- buffer[STATSD_CONF_LINE_MAX] = '\0';
- line++;
-
- s = trim(buffer);
- if (!s || *s == '#') {
- debug(D_STATSD, "STATSD: ignoring line %zu of file '%s/%s', it is empty.", line, path, filename);
- continue;
- }
-
- debug(D_STATSD, "STATSD: processing line %zu of file '%s/%s': %s", line, path, filename, buffer);
-
- if(*s == 'i' && strncmp(s, "include", 7) == 0) {
- s = trim(&s[7]);
- if(s && *s)
- statsd_readfile(path, s, app, chart, dict);
- else
- error("STATSD: ignoring line %zu of file '%s/%s', include filename is empty", line, path, s);
-
- continue;
- }
-
- int len = (int) strlen(s);
- if (*s == '[' && s[len - 1] == ']') {
- // new section
- s[len - 1] = '\0';
- s++;
-
- if (!strcmp(s, "app")) {
- // a new app
- app = callocz(sizeof(STATSD_APP), 1);
- app->name = strdupz("unnamed");
- app->rrd_memory_mode = localhost->rrd_memory_mode;
- app->rrd_history_entries = localhost->rrd_history_entries;
-
- app->next = statsd.apps;
- statsd.apps = app;
- chart = NULL;
- dict = NULL;
-
- {
- char lineandfile[FILENAME_MAX + 1];
- snprintfz(lineandfile, FILENAME_MAX, "%zu@%s", line, filename);
- app->source = strdupz(lineandfile);
- }
- }
- else if(app) {
- if(!strcmp(s, "dictionary")) {
- if(!app->dict)
- app->dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
-
- dict = app->dict;
- }
- else {
- dict = NULL;
-
- // a new chart
- chart = callocz(sizeof(STATSD_APP_CHART), 1);
- netdata_fix_chart_id(s);
- chart->id = strdupz(s);
- chart->name = strdupz(s);
- chart->title = strdupz("Statsd chart");
- chart->context = strdupz(s);
- chart->family = strdupz("overview");
- chart->units = strdupz("value");
- chart->priority = STATSD_CHART_PRIORITY;
- chart->chart_type = RRDSET_TYPE_LINE;
-
- chart->next = app->charts;
- app->charts = chart;
-
- {
- char lineandfile[FILENAME_MAX + 1];
- snprintfz(lineandfile, FILENAME_MAX, "%zu@%s", line, filename);
- chart->source = strdupz(lineandfile);
- }
- }
- }
- else
- error("STATSD: ignoring line %zu ('%s') of file '%s/%s', [app] is not defined.", line, s, path, filename);
-
- continue;
- }
-
- if(!app) {
- error("STATSD: ignoring line %zu ('%s') of file '%s/%s', it is outside all sections.", line, s, path, filename);
- continue;
- }
-
- char *name = s;
- char *value = strchr(s, '=');
- if(!value) {
- error("STATSD: ignoring line %zu ('%s') of file '%s/%s', there is no = in it.", line, s, path, filename);
- continue;
- }
- *value = '\0';
- value++;
-
- name = trim(name);
- value = trim(value);
-
- if(!name || *name == '#') {
- error("STATSD: ignoring line %zu of file '%s/%s', name is empty.", line, path, filename);
- continue;
- }
- if(!value) {
- debug(D_CONFIG, "STATSD: ignoring line %zu of file '%s/%s', value is empty.", line, path, filename);
- continue;
- }
-
- if(unlikely(dict)) {
- // parse [dictionary] members
-
- dictionary_set(dict, name, value, strlen(value) + 1);
- }
- else if(!chart) {
- // parse [app] members
-
- if(!strcmp(name, "name")) {
- freez((void *)app->name);
- netdata_fix_chart_name(value);
- app->name = strdupz(value);
- }
- else if (!strcmp(name, "metrics")) {
- simple_pattern_free(app->metrics);
- app->metrics = simple_pattern_create(value, NULL, SIMPLE_PATTERN_EXACT);
- }
- else if (!strcmp(name, "private charts")) {
- if (!strcmp(value, "yes") || !strcmp(value, "on"))
- app->default_options |= STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
- else
- app->default_options &= ~STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
- }
- else if (!strcmp(name, "gaps when not collected")) {
- if (!strcmp(value, "yes") || !strcmp(value, "on"))
- app->default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
- }
- else if (!strcmp(name, "memory mode")) {
- app->rrd_memory_mode = rrd_memory_mode_id(value);
- }
- else if (!strcmp(name, "history")) {
- app->rrd_history_entries = atol(value);
- if (app->rrd_history_entries < 5)
- app->rrd_history_entries = 5;
- }
- else {
- error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [app] section.", line, name, path, filename);
- continue;
- }
- }
- else {
- // parse [chart] members
-
- if(!strcmp(name, "name")) {
- freez((void *)chart->name);
- netdata_fix_chart_id(value);
- chart->name = strdupz(value);
- }
- else if(!strcmp(name, "title")) {
- freez((void *)chart->title);
- chart->title = strdupz(value);
- }
- else if (!strcmp(name, "family")) {
- freez((void *)chart->family);
- chart->family = strdupz(value);
- }
- else if (!strcmp(name, "context")) {
- freez((void *)chart->context);
- netdata_fix_chart_id(value);
- chart->context = strdupz(value);
- }
- else if (!strcmp(name, "units")) {
- freez((void *)chart->units);
- chart->units = strdupz(value);
- }
- else if (!strcmp(name, "priority")) {
- chart->priority = atol(value);
- }
- else if (!strcmp(name, "type")) {
- chart->chart_type = rrdset_type_id(value);
- }
- else if (!strcmp(name, "dimension")) {
- // metric [name [type [multiplier [divisor]]]]
- char *words[10];
- pluginsd_split_words(value, words, 10);
-
- int pattern = 0;
- size_t i = 0;
- char *metric_name = words[i++];
-
- if(strcmp(metric_name, "pattern") == 0) {
- metric_name = words[i++];
- pattern = 1;
- }
-
- char *dim_name = words[i++];
- char *type = words[i++];
- char *multipler = words[i++];
- char *divisor = words[i++];
- char *options = words[i++];
-
- RRDDIM_FLAGS flags = RRDDIM_FLAG_NONE;
- if(options && *options) {
- if(strstr(options, "hidden") != NULL) flags |= RRDDIM_FLAG_HIDDEN;
- if(strstr(options, "noreset") != NULL) flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
- if(strstr(options, "nooverflow") != NULL) flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
- }
-
- if(!pattern) {
- if(app->dict) {
- if(dim_name && *dim_name) {
- char *n = dictionary_get(app->dict, dim_name);
- if(n) dim_name = n;
- }
- else {
- dim_name = dictionary_get(app->dict, metric_name);
- }
- }
-
- if(!dim_name || !*dim_name)
- dim_name = metric_name;
- }
-
- STATSD_APP_CHART_DIM *dim = add_dimension_to_app_chart(
- app
- , chart
- , metric_name
- , dim_name
- , (multipler && *multipler)?str2l(multipler):1
- , (divisor && *divisor)?str2l(divisor):1
- , flags
- , string2valuetype(type, line, path, filename)
- );
-
- if(pattern)
- dim->metric_pattern = simple_pattern_create(dim->metric, NULL, SIMPLE_PATTERN_EXACT);
- }
- else {
- error("STATSD: ignoring line %zu ('%s') of file '%s/%s'. Unknown keyword for the [%s] section.", line, name, path, filename, chart->id);
- continue;
- }
- }
- }
-
- freez(buffer);
- fclose(fp);
- return 0;
-}
-
-static void statsd_readdir(const char *path) {
- size_t pathlen = strlen(path);
-
- debug(D_STATSD, "STATSD configuration reading directory '%s'", path);
-
- DIR *dir = opendir(path);
- if (!dir) {
- error("STATSD configuration cannot open directory '%s'.", path);
- return;
- }
-
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- size_t len = strlen(de->d_name);
-
- if(de->d_type == DT_DIR
- && (
- (de->d_name[0] == '.' && de->d_name[1] == '\0')
- || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- )) {
- debug(D_STATSD, "STATSD: ignoring directory '%s'", de->d_name);
- continue;
- }
-
- else if(de->d_type == DT_DIR) {
- char *s = mallocz(pathlen + strlen(de->d_name) + 2);
- strcpy(s, path);
- strcat(s, "/");
- strcat(s, de->d_name);
- statsd_readdir(s);
- freez(s);
- continue;
- }
-
- else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) &&
- len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
- statsd_readfile(path, de->d_name, NULL, NULL, NULL);
- }
-
- else debug(D_STATSD, "STATSD: ignoring file '%s'", de->d_name);
- }
-
- closedir(dir);
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// send metrics to netdata - in private charts - called from the main thread
-
-// extract chart type and chart id from metric name
-static inline void statsd_get_metric_type_and_id(STATSD_METRIC *m, char *type, char *id, const char *defid, size_t len) {
- char *s;
-
- snprintfz(type, len, "%s_%s_%s", STATSD_CHART_PREFIX, defid, m->name);
- for(s = type; *s ;s++)
- if(unlikely(*s == '.')) break;
-
- if(*s == '.') {
- *s++ = '\0';
- strncpyz(id, s, len);
- }
- else {
- strncpyz(id, defid, len);
- }
-
- netdata_fix_chart_id(type);
- netdata_fix_chart_id(id);
-}
-
-static inline RRDSET *statsd_private_rrdset_create(
- STATSD_METRIC *m
- , const char *type
- , const char *id
- , const char *name
- , const char *family
- , const char *context
- , const char *title
- , const char *units
- , long priority
- , int update_every
- , RRDSET_TYPE chart_type
-) {
- RRD_MEMORY_MODE memory_mode = statsd.private_charts_memory_mode;
- long history = statsd.private_charts_rrd_history_entries;
-
- if(unlikely(statsd.private_charts >= statsd.max_private_charts)) {
- debug(D_STATSD, "STATSD: metric '%s' will be charted with memory mode = none, because the maximum number of charts has been reached.", m->name);
- info("STATSD: metric '%s' will be charted with memory mode = none, because the maximum number of charts (%zu) has been reached. Increase the number of charts by editing netdata.conf, [statsd] section.", m->name, statsd.max_private_charts);
- memory_mode = RRD_MEMORY_MODE_NONE;
- history = 5;
- }
-
- statsd.private_charts++;
- RRDSET *st = rrdset_create_custom(
- localhost // host
- , type // type
- , id // id
- , name // name
- , family // family
- , context // context
- , title // title
- , units // units
- , "statsd" // plugin
- , "private_chart" // module
- , priority // priority
- , update_every // update every
- , chart_type // chart type
- , memory_mode // memory mode
- , history // history
- );
- rrdset_flag_set(st, RRDSET_FLAG_STORE_FIRST);
-
- if(statsd.private_charts_hidden)
- rrdset_flag_set(st, RRDSET_FLAG_HIDDEN);
-
- // rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
- return st;
-}
-
-static inline void statsd_private_chart_gauge(STATSD_METRIC *m) {
- debug(D_STATSD, "updating private chart for gauge metric '%s'", m->name);
-
- if(unlikely(!m->st)) {
- char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1];
- statsd_get_metric_type_and_id(m, type, id, "gauge", RRD_ID_LENGTH_MAX);
-
- char context[RRD_ID_LENGTH_MAX + 1];
- snprintfz(context, RRD_ID_LENGTH_MAX, "statsd_gauge.%s", m->name);
-
- char title[RRD_ID_LENGTH_MAX + 1];
- snprintfz(title, RRD_ID_LENGTH_MAX, "statsd private chart for gauge %s", m->name);
-
- m->st = statsd_private_rrdset_create(
- m
- , type
- , id
- , NULL // name
- , "gauges" // family (submenu)
- , context // context
- , title // title
- , "value" // units
- , STATSD_CHART_PRIORITY
- , statsd.update_every
- , RRDSET_TYPE_LINE
- );
-
- m->rd_value = rrddim_add(m->st, "gauge", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
-
- if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
- m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(m->st);
-
- rrddim_set_by_pointer(m->st, m->rd_value, m->last);
-
- if(m->rd_count)
- rrddim_set_by_pointer(m->st, m->rd_count, m->events);
-
- rrdset_done(m->st);
-}
-
-static inline void statsd_private_chart_counter_or_meter(STATSD_METRIC *m, const char *dim, const char *family) {
- debug(D_STATSD, "updating private chart for %s metric '%s'", dim, m->name);
-
- if(unlikely(!m->st)) {
- char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1];
- statsd_get_metric_type_and_id(m, type, id, dim, RRD_ID_LENGTH_MAX);
-
- char context[RRD_ID_LENGTH_MAX + 1];
- snprintfz(context, RRD_ID_LENGTH_MAX, "statsd_%s.%s", dim, m->name);
-
- char title[RRD_ID_LENGTH_MAX + 1];
- snprintfz(title, RRD_ID_LENGTH_MAX, "statsd private chart for %s %s", dim, m->name);
-
- m->st = statsd_private_rrdset_create(
- m
- , type
- , id
- , NULL // name
- , family // family (submenu)
- , context // context
- , title // title
- , "events/s" // units
- , STATSD_CHART_PRIORITY
- , statsd.update_every
- , RRDSET_TYPE_AREA
- );
-
- m->rd_value = rrddim_add(m->st, dim, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
- m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(m->st);
-
- rrddim_set_by_pointer(m->st, m->rd_value, m->last);
-
- if(m->rd_count)
- rrddim_set_by_pointer(m->st, m->rd_count, m->events);
-
- rrdset_done(m->st);
-}
-
-static inline void statsd_private_chart_set(STATSD_METRIC *m) {
- debug(D_STATSD, "updating private chart for set metric '%s'", m->name);
-
- if(unlikely(!m->st)) {
- char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1];
- statsd_get_metric_type_and_id(m, type, id, "set", RRD_ID_LENGTH_MAX);
-
- char context[RRD_ID_LENGTH_MAX + 1];
- snprintfz(context, RRD_ID_LENGTH_MAX, "statsd_set.%s", m->name);
-
- char title[RRD_ID_LENGTH_MAX + 1];
- snprintfz(title, RRD_ID_LENGTH_MAX, "statsd private chart for set %s", m->name);
-
- m->st = statsd_private_rrdset_create(
- m
- , type
- , id
- , NULL // name
- , "sets" // family (submenu)
- , context // context
- , title // title
- , "entries" // units
- , STATSD_CHART_PRIORITY
- , statsd.update_every
- , RRDSET_TYPE_LINE
- );
-
- m->rd_value = rrddim_add(m->st, "set", "set size", 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
- m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(m->st);
-
- rrddim_set_by_pointer(m->st, m->rd_value, m->last);
-
- if(m->rd_count)
- rrddim_set_by_pointer(m->st, m->rd_count, m->events);
-
- rrdset_done(m->st);
-}
-
-static inline void statsd_private_chart_timer_or_histogram(STATSD_METRIC *m, const char *dim, const char *family, const char *units) {
- debug(D_STATSD, "updating private chart for %s metric '%s'", dim, m->name);
-
- if(unlikely(!m->st)) {
- char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1];
- statsd_get_metric_type_and_id(m, type, id, dim, RRD_ID_LENGTH_MAX);
-
- char context[RRD_ID_LENGTH_MAX + 1];
- snprintfz(context, RRD_ID_LENGTH_MAX, "statsd_%s.%s", dim, m->name);
-
- char title[RRD_ID_LENGTH_MAX + 1];
- snprintfz(title, RRD_ID_LENGTH_MAX, "statsd private chart for %s %s", dim, m->name);
-
- m->st = statsd_private_rrdset_create(
- m
- , type
- , id
- , NULL // name
- , family // family (submenu)
- , context // context
- , title // title
- , units // units
- , STATSD_CHART_PRIORITY
- , statsd.update_every
- , RRDSET_TYPE_AREA
- );
-
- m->histogram.ext->rd_min = rrddim_add(m->st, "min", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
- m->histogram.ext->rd_max = rrddim_add(m->st, "max", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
- m->rd_value = rrddim_add(m->st, "average", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
- m->histogram.ext->rd_percentile = rrddim_add(m->st, statsd.histogram_percentile_str, NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
- m->histogram.ext->rd_median = rrddim_add(m->st, "median", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
- m->histogram.ext->rd_stddev = rrddim_add(m->st, "stddev", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
- m->histogram.ext->rd_sum = rrddim_add(m->st, "sum", NULL, 1, statsd.decimal_detail, RRD_ALGORITHM_ABSOLUTE);
-
- if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
- m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else rrdset_next(m->st);
-
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_min, m->histogram.ext->last_min);
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_max, m->histogram.ext->last_max);
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_percentile, m->histogram.ext->last_percentile);
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_median, m->histogram.ext->last_median);
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_stddev, m->histogram.ext->last_stddev);
- rrddim_set_by_pointer(m->st, m->histogram.ext->rd_sum, m->histogram.ext->last_sum);
- rrddim_set_by_pointer(m->st, m->rd_value, m->last);
-
- if(m->rd_count)
- rrddim_set_by_pointer(m->st, m->rd_count, m->events);
-
- rrdset_done(m->st);
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-// statsd flush metrics
-
-static inline void statsd_flush_gauge(STATSD_METRIC *m) {
- debug(D_STATSD, "flushing gauge metric '%s'", m->name);
-
- int updated = 0;
- if(m->count && !m->reset) {
- m->last = (collected_number) (m->gauge.value * statsd.decimal_detail);
-
- m->reset = 1;
- updated = 1;
- }
-
- if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))
- statsd_private_chart_gauge(m);
-}
-
-static inline void statsd_flush_counter_or_meter(STATSD_METRIC *m, const char *dim, const char *family) {
- debug(D_STATSD, "flushing %s metric '%s'", dim, m->name);
-
- int updated = 0;
- if(m->count && !m->reset) {
- m->last = m->counter.value;
-
- m->reset = 1;
- updated = 1;
- }
-
- if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))
- statsd_private_chart_counter_or_meter(m, dim, family);
-}
-
-static inline void statsd_flush_counter(STATSD_METRIC *m) {
- statsd_flush_counter_or_meter(m, "counter", "counters");
-}
-
-static inline void statsd_flush_meter(STATSD_METRIC *m) {
- statsd_flush_counter_or_meter(m, "meter", "meters");
-}
-
-static inline void statsd_flush_set(STATSD_METRIC *m) {
- debug(D_STATSD, "flushing set metric '%s'", m->name);
-
- int updated = 0;
- if(m->count && !m->reset) {
- m->last = (collected_number)m->set.unique;
-
- m->reset = 1;
- updated = 1;
- }
-
- if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))
- statsd_private_chart_set(m);
-}
-
-static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char *dim, const char *family, const char *units) {
- debug(D_STATSD, "flushing %s metric '%s'", dim, m->name);
-
- netdata_mutex_lock(&m->histogram.ext->mutex);
-
- if(unlikely(!m->histogram.ext->zeroed)) {
- // reset the metrics
- // if we collected anything, they will be updated below
- // this ensures that we report zeros if nothing is collected
-
- m->histogram.ext->last_min = 0;
- m->histogram.ext->last_max = 0;
- m->last = 0;
- m->histogram.ext->last_median = 0;
- m->histogram.ext->last_stddev = 0;
- m->histogram.ext->last_sum = 0;
- m->histogram.ext->last_percentile = 0;
-
- m->histogram.ext->zeroed = 1;
- }
-
- int updated = 0;
- if(m->count && !m->reset && m->histogram.ext->used > 0) {
- size_t len = m->histogram.ext->used;
- LONG_DOUBLE *series = m->histogram.ext->values;
- sort_series(series, len);
-
- m->histogram.ext->last_min = (collected_number)roundl(series[0] * statsd.decimal_detail);
- m->histogram.ext->last_max = (collected_number)roundl(series[len - 1] * statsd.decimal_detail);
- m->last = (collected_number)roundl(average(series, len) * statsd.decimal_detail);
- m->histogram.ext->last_median = (collected_number)roundl(median_on_sorted_series(series, len) * statsd.decimal_detail);
- m->histogram.ext->last_stddev = (collected_number)roundl(standard_deviation(series, len) * statsd.decimal_detail);
- m->histogram.ext->last_sum = (collected_number)roundl(sum(series, len) * statsd.decimal_detail);
-
- size_t pct_len = (size_t)floor((double)len * statsd.histogram_percentile / 100.0);
- if(pct_len < 1)
- m->histogram.ext->last_percentile = (collected_number)(series[0] * statsd.decimal_detail);
- else
- m->histogram.ext->last_percentile = (collected_number)roundl(series[pct_len - 1] * statsd.decimal_detail);
-
- debug(D_STATSD, "STATSD %s metric %s: min " COLLECTED_NUMBER_FORMAT ", max " COLLECTED_NUMBER_FORMAT ", last " COLLECTED_NUMBER_FORMAT ", pcent " COLLECTED_NUMBER_FORMAT ", median " COLLECTED_NUMBER_FORMAT ", stddev " COLLECTED_NUMBER_FORMAT ", sum " COLLECTED_NUMBER_FORMAT,
- dim, m->name, m->histogram.ext->last_min, m->histogram.ext->last_max, m->last, m->histogram.ext->last_percentile, m->histogram.ext->last_median, m->histogram.ext->last_stddev, m->histogram.ext->last_sum);
-
- m->histogram.ext->zeroed = 0;
- m->reset = 1;
- updated = 1;
- }
-
- if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))
- statsd_private_chart_timer_or_histogram(m, dim, family, units);
-
- netdata_mutex_unlock(&m->histogram.ext->mutex);
-}
-
-static inline void statsd_flush_timer(STATSD_METRIC *m) {
- statsd_flush_timer_or_histogram(m, "timer", "timers", "milliseconds");
-}
-
-static inline void statsd_flush_histogram(STATSD_METRIC *m) {
- statsd_flush_timer_or_histogram(m, "histogram", "histograms", "value");
-}
-
-static inline RRD_ALGORITHM statsd_algorithm_for_metric(STATSD_METRIC *m) {
- switch(m->type) {
- default:
- case STATSD_METRIC_TYPE_GAUGE:
- case STATSD_METRIC_TYPE_SET:
- case STATSD_METRIC_TYPE_TIMER:
- case STATSD_METRIC_TYPE_HISTOGRAM:
- return RRD_ALGORITHM_ABSOLUTE;
-
- case STATSD_METRIC_TYPE_METER:
- case STATSD_METRIC_TYPE_COUNTER:
- return RRD_ALGORITHM_INCREMENTAL;
- }
-}
-
-static inline void link_metric_to_app_dimension(STATSD_APP *app, STATSD_METRIC *m, STATSD_APP_CHART *chart, STATSD_APP_CHART_DIM *dim) {
- if(dim->value_type == STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS) {
- dim->value_ptr = &m->events;
- dim->algorithm = RRD_ALGORITHM_INCREMENTAL;
- }
- else if(m->type == STATSD_METRIC_TYPE_HISTOGRAM || m->type == STATSD_METRIC_TYPE_TIMER) {
- dim->algorithm = RRD_ALGORITHM_ABSOLUTE;
- dim->divisor *= statsd.decimal_detail;
-
- switch(dim->value_type) {
- case STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS:
- // will never match - added to avoid warning
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_LAST:
- case STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE:
- dim->value_ptr = &m->last;
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_SUM:
- dim->value_ptr = &m->histogram.ext->last_sum;
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_MIN:
- dim->value_ptr = &m->histogram.ext->last_min;
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_MAX:
- dim->value_ptr = &m->histogram.ext->last_max;
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN:
- dim->value_ptr = &m->histogram.ext->last_median;
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE:
- dim->value_ptr = &m->histogram.ext->last_percentile;
- break;
-
- case STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV:
- dim->value_ptr = &m->histogram.ext->last_stddev;
- break;
- }
- }
- else {
- if (dim->value_type != STATSD_APP_CHART_DIM_VALUE_TYPE_LAST)
- error("STATSD: unsupported value type for dimension '%s' of chart '%s' of app '%s' on metric '%s'", dim->name, chart->id, app->name, m->name);
-
- dim->value_ptr = &m->last;
- dim->algorithm = statsd_algorithm_for_metric(m);
-
- if(m->type == STATSD_METRIC_TYPE_GAUGE)
- dim->divisor *= statsd.decimal_detail;
- }
-
- if(unlikely(chart->st && dim->rd)) {
- rrddim_set_algorithm(chart->st, dim->rd, dim->algorithm);
- rrddim_set_multiplier(chart->st, dim->rd, dim->multiplier);
- rrddim_set_divisor(chart->st, dim->rd, dim->divisor);
- }
-
- chart->dimensions_linked_count++;
- debug(D_STATSD, "metric '%s' of type %u linked with app '%s', chart '%s', dimension '%s', algorithm '%s'", m->name, m->type, app->name, chart->id, dim->name, rrd_algorithm_name(dim->algorithm));
-}
-
-static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC *m) {
- (void)index;
-
- STATSD_APP *app;
- for(app = statsd.apps; app ;app = app->next) {
- if(unlikely(simple_pattern_matches(app->metrics, m->name))) {
- debug(D_STATSD, "metric '%s' matches app '%s'", m->name, app->name);
-
- // the metric should get the options from the app
-
- if(app->default_options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED)
- m->options |= STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
- else
- m->options &= ~STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
-
- if(app->default_options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)
- m->options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
- else
- m->options &= ~STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- m->options |= STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED;
-
- // check if there is a chart in this app, willing to get this metric
- STATSD_APP_CHART *chart;
- for(chart = app->charts; chart; chart = chart->next) {
-
- STATSD_APP_CHART_DIM *dim;
- for(dim = chart->dimensions; dim ; dim = dim->next) {
- if(unlikely(dim->metric_pattern)) {
- size_t dim_name_len = strlen(dim->name);
- size_t wildcarded_len = dim_name_len + strlen(m->name) + 1;
- char wildcarded[wildcarded_len];
-
- strcpy(wildcarded, dim->name);
- char *ws = &wildcarded[dim_name_len];
-
- if(simple_pattern_matches_extract(dim->metric_pattern, m->name, ws, wildcarded_len - dim_name_len)) {
-
- char *final_name = NULL;
-
- if(app->dict) {
- if(likely(*wildcarded)) {
- // use the name of the wildcarded string
- final_name = dictionary_get(app->dict, wildcarded);
- }
-
- if(unlikely(!final_name)) {
- // use the name of the metric
- final_name = dictionary_get(app->dict, m->name);
- }
- }
-
- if(unlikely(!final_name))
- final_name = wildcarded;
-
- add_dimension_to_app_chart(
- app
- , chart
- , m->name
- , final_name
- , dim->multiplier
- , dim->divisor
- , dim->flags
- , dim->value_type
- );
-
- // the new dimension is appended to the list
- // so, it will be matched and linked later too
- }
- }
- else if(!dim->value_ptr && dim->metric_hash == m->hash && !strcmp(dim->metric, m->name)) {
- // we have a match - this metric should be linked to this dimension
- link_metric_to_app_dimension(app, m, chart, dim);
- }
- }
-
- }
- }
- }
-}
-
-static inline RRDDIM *statsd_add_dim_to_app_chart(STATSD_APP *app, STATSD_APP_CHART *chart, STATSD_APP_CHART_DIM *dim) {
- (void)app;
-
- // allow the same statsd metric to be added multiple times to the same chart
-
- STATSD_APP_CHART_DIM *tdim;
- size_t count_same_metric = 0, count_same_metric_value_type = 0;
- size_t pos_same_metric_value_type = 0;
-
- for (tdim = chart->dimensions; tdim && tdim->next; tdim = tdim->next) {
- if (dim->metric_hash == tdim->metric_hash && !strcmp(dim->metric, tdim->metric)) {
- count_same_metric++;
-
- if(dim->value_type == tdim->value_type) {
- count_same_metric_value_type++;
- if (tdim == dim)
- pos_same_metric_value_type = count_same_metric_value_type;
- }
- }
- }
-
- if(count_same_metric > 1) {
- // the same metric is found multiple times
-
- size_t len = strlen(dim->metric) + 100;
- char metric[ len + 1 ];
-
- if(count_same_metric_value_type > 1) {
- // the same metric, with the same value type, is added multiple times
- snprintfz(metric, len, "%s_%s%zu", dim->metric, valuetype2string(dim->value_type), pos_same_metric_value_type);
- }
- else {
- // the same metric, with different value type is added
- snprintfz(metric, len, "%s_%s", dim->metric, valuetype2string(dim->value_type));
- }
-
- dim->rd = rrddim_add(chart->st, metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm);
- if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags;
- return dim->rd;
- }
-
- dim->rd = rrddim_add(chart->st, dim->metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm);
- if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags;
- return dim->rd;
-}
-
-static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *chart) {
- debug(D_STATSD, "updating chart '%s' for app '%s'", chart->id, app->name);
-
- if(!chart->st) {
- chart->st = rrdset_create_custom(
- localhost // host
- , app->name // type
- , chart->id // id
- , chart->name // name
- , chart->family // family
- , chart->context // context
- , chart->title // title
- , chart->units // units
- , "statsd" // plugin
- , chart->source // module
- , chart->priority // priority
- , statsd.update_every // update every
- , chart->chart_type // chart type
- , app->rrd_memory_mode // memory mode
- , app->rrd_history_entries // history
- );
-
- rrdset_flag_set(chart->st, RRDSET_FLAG_STORE_FIRST);
- // rrdset_flag_set(chart->st, RRDSET_FLAG_DEBUG);
- }
- else rrdset_next(chart->st);
-
- STATSD_APP_CHART_DIM *dim;
- for(dim = chart->dimensions; dim ;dim = dim->next) {
- if(likely(!dim->metric_pattern)) {
- if (unlikely(!dim->rd))
- statsd_add_dim_to_app_chart(app, chart, dim);
-
- if (unlikely(dim->value_ptr)) {
- debug(D_STATSD, "updating dimension '%s' (%s) of chart '%s' (%s) for app '%s' with value " COLLECTED_NUMBER_FORMAT, dim->name, dim->rd->id, chart->id, chart->st->id, app->name, *dim->value_ptr);
- rrddim_set_by_pointer(chart->st, dim->rd, *dim->value_ptr);
- }
- }
- }
-
- rrdset_done(chart->st);
- debug(D_STATSD, "completed update of chart '%s' for app '%s'", chart->id, app->name);
-}
-
-static inline void statsd_update_all_app_charts(void) {
- // debug(D_STATSD, "updating app charts");
-
- STATSD_APP *app;
- for(app = statsd.apps; app ;app = app->next) {
- // debug(D_STATSD, "updating charts for app '%s'", app->name);
-
- STATSD_APP_CHART *chart;
- for(chart = app->charts; chart ;chart = chart->next) {
- if(unlikely(chart->dimensions_linked_count)) {
- statsd_update_app_chart(app, chart);
- }
- }
- }
-
- // debug(D_STATSD, "completed update of app charts");
-}
-
-const char *statsd_metric_type_string(STATSD_METRIC_TYPE type) {
- switch(type) {
- case STATSD_METRIC_TYPE_COUNTER: return "counter";
- case STATSD_METRIC_TYPE_GAUGE: return "gauge";
- case STATSD_METRIC_TYPE_HISTOGRAM: return "histogram";
- case STATSD_METRIC_TYPE_METER: return "meter";
- case STATSD_METRIC_TYPE_SET: return "set";
- case STATSD_METRIC_TYPE_TIMER: return "timer";
- default: return "unknown";
- }
-}
-
-static inline void statsd_flush_index_metrics(STATSD_INDEX *index, void (*flush_metric)(STATSD_METRIC *)) {
- STATSD_METRIC *m;
- for(m = index->first; m ; m = m->next) {
- if(unlikely(!(m->options & STATSD_METRIC_OPTION_CHECKED_IN_APPS))) {
- log_access("NEW STATSD METRIC '%s': '%s'", statsd_metric_type_string(m->type), m->name);
- check_if_metric_is_for_app(index, m);
- m->options |= STATSD_METRIC_OPTION_CHECKED_IN_APPS;
- }
-
- if(unlikely(!(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED))) {
- if(statsd.private_charts >= statsd.max_private_charts_hard) {
- debug(D_STATSD, "STATSD: metric '%s' will not be charted, because the hard limit of the maximum number of charts has been reached.", m->name);
- info("STATSD: metric '%s' will not be charted, because the hard limit of the maximum number of charts (%zu) has been reached. Increase the number of charts by editing netdata.conf, [statsd] section.", m->name, statsd.max_private_charts);
- m->options &= ~STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
- }
- else {
- if (simple_pattern_matches(statsd.charts_for, m->name)) {
- debug(D_STATSD, "STATSD: metric '%s' will be charted.", m->name);
- m->options |= STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
- } else {
- debug(D_STATSD, "STATSD: metric '%s' will not be charted.", m->name);
- m->options &= ~STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED;
- }
- }
-
- m->options |= STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED;
- }
-
- flush_metric(m);
- }
-}
-
-
-// --------------------------------------------------------------------------------------
-// statsd main thread
-
-static int statsd_listen_sockets_setup(void) {
- return listen_sockets_setup(&statsd.sockets);
-}
-
-static void statsd_main_cleanup(void *data) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)data;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
- info("cleaning up...");
-
- if (statsd.collection_threads_status) {
- int i;
- for (i = 0; i < statsd.threads; i++) {
- if(statsd.collection_threads_status[i].status) {
- info("STATSD: stopping data collection thread %d...", i + 1);
- netdata_thread_cancel(statsd.collection_threads_status[i].thread);
- }
- else {
- info("STATSD: data collection thread %d found stopped.", i + 1);
- }
- }
- }
-
- info("STATSD: closing sockets...");
- listen_sockets_close(&statsd.sockets);
-
- info("STATSD: cleanup completed.");
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *statsd_main(void *ptr) {
- netdata_thread_cleanup_push(statsd_main_cleanup, ptr);
-
- // ----------------------------------------------------------------------------------------------------------------
- // statsd configuration
-
- statsd.enabled = config_get_boolean(CONFIG_SECTION_STATSD, "enabled", statsd.enabled);
-
- statsd.update_every = default_rrd_update_every;
- statsd.update_every = (int)config_get_number(CONFIG_SECTION_STATSD, "update every (flushInterval)", statsd.update_every);
- if(statsd.update_every < default_rrd_update_every) {
- error("STATSD: minimum flush interval %d given, but the minimum is the update every of netdata. Using %d", statsd.update_every, default_rrd_update_every);
- statsd.update_every = default_rrd_update_every;
- }
-
-#ifdef HAVE_RECVMMSG
- statsd.recvmmsg_size = (size_t)config_get_number(CONFIG_SECTION_STATSD, "udp messages to process at once", (long long)statsd.recvmmsg_size);
-#endif
-
- statsd.charts_for = simple_pattern_create(config_get(CONFIG_SECTION_STATSD, "create private charts for metrics matching", "*"), NULL, SIMPLE_PATTERN_EXACT);
- statsd.max_private_charts = (size_t)config_get_number(CONFIG_SECTION_STATSD, "max private charts allowed", (long long)statsd.max_private_charts);
- statsd.max_private_charts_hard = (size_t)config_get_number(CONFIG_SECTION_STATSD, "max private charts hard limit", (long long)statsd.max_private_charts * 5);
- statsd.private_charts_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_STATSD, "private charts memory mode", rrd_memory_mode_name(default_rrd_memory_mode)));
- statsd.private_charts_rrd_history_entries = (int)config_get_number(CONFIG_SECTION_STATSD, "private charts history", default_rrd_history_entries);
- statsd.decimal_detail = (size_t)config_get_number(CONFIG_SECTION_STATSD, "decimal detail", (long long int)statsd.decimal_detail);
- statsd.tcp_idle_timeout = (size_t) config_get_number(CONFIG_SECTION_STATSD, "disconnect idle tcp clients after seconds", (long long int)statsd.tcp_idle_timeout);
- statsd.private_charts_hidden = (int)config_get_boolean(CONFIG_SECTION_STATSD, "private charts hidden", statsd.private_charts_hidden);
-
- statsd.histogram_percentile = (double)config_get_float(CONFIG_SECTION_STATSD, "histograms and timers percentile (percentThreshold)", statsd.histogram_percentile);
- if(isless(statsd.histogram_percentile, 0) || isgreater(statsd.histogram_percentile, 100)) {
- error("STATSD: invalid histograms and timers percentile %0.5f given", statsd.histogram_percentile);
- statsd.histogram_percentile = 95.0;
- }
- {
- char buffer[100 + 1];
- snprintf(buffer, 100, "%0.1f%%", statsd.histogram_percentile);
- statsd.histogram_percentile_str = strdupz(buffer);
- }
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "add dimension for number of events received", 1)) {
- statsd.gauges.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
- statsd.counters.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
- statsd.meters.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
- statsd.sets.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
- statsd.histograms.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
- statsd.timers.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
- }
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "gaps on gauges (deleteGauges)", 0))
- statsd.gauges.default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "gaps on counters (deleteCounters)", 0))
- statsd.counters.default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "gaps on meters (deleteMeters)", 0))
- statsd.meters.default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "gaps on sets (deleteSets)", 0))
- statsd.sets.default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "gaps on histograms (deleteHistograms)", 0))
- statsd.histograms.default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- if(config_get_boolean(CONFIG_SECTION_STATSD, "gaps on timers (deleteTimers)", 0))
- statsd.timers.default_options |= STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED;
-
- size_t max_sockets = (size_t)config_get_number(CONFIG_SECTION_STATSD, "statsd server max TCP sockets", (long long int)(rlimit_nofile.rlim_cur / 4));
-
-#ifdef STATSD_MULTITHREADED
- statsd.threads = (int)config_get_number(CONFIG_SECTION_STATSD, "threads", processors);
- if(statsd.threads < 1) {
- error("STATSD: Invalid number of threads %d, using %d", statsd.threads, processors);
- statsd.threads = processors;
- config_set_number(CONFIG_SECTION_STATSD, "collector threads", statsd.threads);
- }
-#else
- statsd.threads = 1;
-#endif
-
- // read custom application definitions
- {
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/statsd.d", netdata_configured_config_dir);
- statsd_readdir(filename);
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // statsd setup
-
- if(!statsd.enabled) return NULL;
-
- statsd_listen_sockets_setup();
- if(!statsd.sockets.opened) {
- error("STATSD: No statsd sockets to listen to. statsd will be disabled.");
- goto cleanup;
- }
-
- statsd.collection_threads_status = callocz((size_t)statsd.threads, sizeof(struct collection_thread_status));
-
- int i;
- for(i = 0; i < statsd.threads ;i++) {
- statsd.collection_threads_status[i].max_sockets = max_sockets / statsd.threads;
- char tag[NETDATA_THREAD_TAG_MAX + 1];
- snprintfz(tag, NETDATA_THREAD_TAG_MAX, "STATSD_COLLECTOR[%d]", i + 1);
- netdata_thread_create(&statsd.collection_threads_status[i].thread, tag, NETDATA_THREAD_OPTION_DEFAULT, statsd_collector_thread, &statsd.collection_threads_status[i]);
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // statsd monitoring charts
-
- RRDSET *st_metrics = rrdset_create_localhost(
- "netdata"
- , "statsd_metrics"
- , NULL
- , "statsd"
- , NULL
- , "Metrics in the netdata statsd database"
- , "metrics"
- , "statsd"
- , "stats"
- , 132010
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
- RRDDIM *rd_metrics_gauge = rrddim_add(st_metrics, "gauges", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_metrics_counter = rrddim_add(st_metrics, "counters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_metrics_timer = rrddim_add(st_metrics, "timers", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_metrics_meter = rrddim_add(st_metrics, "meters", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_metrics_histogram = rrddim_add(st_metrics, "histograms", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDDIM *rd_metrics_set = rrddim_add(st_metrics, "sets", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- RRDSET *st_events = rrdset_create_localhost(
- "netdata"
- , "statsd_events"
- , NULL
- , "statsd"
- , NULL
- , "Events processed by the netdata statsd server"
- , "events/s"
- , "statsd"
- , "stats"
- , 132011
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
- RRDDIM *rd_events_gauge = rrddim_add(st_events, "gauges", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_counter = rrddim_add(st_events, "counters", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_timer = rrddim_add(st_events, "timers", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_meter = rrddim_add(st_events, "meters", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_histogram = rrddim_add(st_events, "histograms", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_set = rrddim_add(st_events, "sets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_unknown = rrddim_add(st_events, "unknown", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_events_errors = rrddim_add(st_events, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- RRDSET *st_reads = rrdset_create_localhost(
- "netdata"
- , "statsd_reads"
- , NULL
- , "statsd"
- , NULL
- , "Read operations made by the netdata statsd server"
- , "reads/s"
- , "statsd"
- , "stats"
- , 132012
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
- RRDDIM *rd_reads_tcp = rrddim_add(st_reads, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_reads_udp = rrddim_add(st_reads, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- RRDSET *st_bytes = rrdset_create_localhost(
- "netdata"
- , "statsd_bytes"
- , NULL
- , "statsd"
- , NULL
- , "Bytes read by the netdata statsd server"
- , "kilobits/s"
- , "netdata"
- , "stats"
- , 132013
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
- RRDDIM *rd_bytes_tcp = rrddim_add(st_bytes, "tcp", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_bytes_udp = rrddim_add(st_bytes, "udp", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
-
- RRDSET *st_packets = rrdset_create_localhost(
- "netdata"
- , "statsd_packets"
- , NULL
- , "statsd"
- , NULL
- , "Network packets processed by the netdata statsd server"
- , "packets/s"
- , "netdata"
- , "stats"
- , 132014
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
- RRDDIM *rd_packets_tcp = rrddim_add(st_packets, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_packets_udp = rrddim_add(st_packets, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- RRDSET *st_tcp_connects = rrdset_create_localhost(
- "netdata"
- , "tcp_connects"
- , NULL
- , "statsd"
- , NULL
- , "statsd server TCP connects and disconnects"
- , "events"
- , "statsd"
- , "stats"
- , 132015
- , statsd.update_every
- , RRDSET_TYPE_LINE
- );
- RRDDIM *rd_tcp_connects = rrddim_add(st_tcp_connects, "connects", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_tcp_disconnects = rrddim_add(st_tcp_connects, "disconnects", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- RRDSET *st_tcp_connected = rrdset_create_localhost(
- "netdata"
- , "tcp_connected"
- , NULL
- , "statsd"
- , NULL
- , "statsd server TCP connected sockets"
- , "connected"
- , "statsd"
- , "stats"
- , 132016
- , statsd.update_every
- , RRDSET_TYPE_LINE
- );
- RRDDIM *rd_tcp_connected = rrddim_add(st_tcp_connected, "connected", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- RRDSET *st_pcharts = rrdset_create_localhost(
- "netdata"
- , "private_charts"
- , NULL
- , "statsd"
- , NULL
- , "Private metric charts created by the netdata statsd server"
- , "charts"
- , "statsd"
- , "stats"
- , 132020
- , statsd.update_every
- , RRDSET_TYPE_AREA
- );
- RRDDIM *rd_pcharts = rrddim_add(st_pcharts, "charts", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
-
- RRDSET *stcpu_thread = rrdset_create_localhost(
- "netdata"
- , "plugin_statsd_charting_cpu"
- , NULL
- , "statsd"
- , "netdata.statsd_cpu"
- , "NetData statsd charting thread CPU usage"
- , "milliseconds/s"
- , "statsd"
- , "stats"
- , 132001
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
-
- RRDDIM *rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- RRDDIM *rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- struct rusage thread;
-
- for(i = 0; i < statsd.threads ;i++) {
- char id[100 + 1];
- char title[100 + 1];
-
- snprintfz(id, 100, "plugin_statsd_collector%d_cpu", i + 1);
- snprintfz(title, 100, "NetData statsd collector thread No %d CPU usage", i + 1);
-
- statsd.collection_threads_status[i].st_cpu = rrdset_create_localhost(
- "netdata"
- , id
- , NULL
- , "statsd"
- , "netdata.statsd_cpu"
- , title
- , "milliseconds/s"
- , "statsd"
- , "stats"
- , 132002 + i
- , statsd.update_every
- , RRDSET_TYPE_STACKED
- );
-
- statsd.collection_threads_status[i].rd_user = rrddim_add(statsd.collection_threads_status[i].st_cpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- statsd.collection_threads_status[i].rd_system = rrddim_add(statsd.collection_threads_status[i].st_cpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // statsd thread to turn metrics into charts
-
- usec_t step = statsd.update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
- while(!netdata_exit) {
- usec_t hb_dt = heartbeat_next(&hb, step);
-
- statsd_flush_index_metrics(&statsd.gauges, statsd_flush_gauge);
- statsd_flush_index_metrics(&statsd.counters, statsd_flush_counter);
- statsd_flush_index_metrics(&statsd.meters, statsd_flush_meter);
- statsd_flush_index_metrics(&statsd.timers, statsd_flush_timer);
- statsd_flush_index_metrics(&statsd.histograms, statsd_flush_histogram);
- statsd_flush_index_metrics(&statsd.sets, statsd_flush_set);
-
- statsd_update_all_app_charts();
-
- getrusage(RUSAGE_THREAD, &thread);
-
- if(unlikely(netdata_exit))
- break;
-
- if(likely(hb_dt)) {
- rrdset_next(st_metrics);
- rrdset_next(st_events);
- rrdset_next(st_reads);
- rrdset_next(st_bytes);
- rrdset_next(st_packets);
- rrdset_next(st_tcp_connects);
- rrdset_next(st_tcp_connected);
- rrdset_next(st_pcharts);
- rrdset_next(stcpu_thread);
- for(i = 0; i < statsd.threads ;i++)
- rrdset_next(statsd.collection_threads_status[i].st_cpu);
- }
-
- rrddim_set_by_pointer(st_metrics, rd_metrics_gauge, (collected_number)statsd.gauges.metrics);
- rrddim_set_by_pointer(st_metrics, rd_metrics_counter, (collected_number)statsd.counters.metrics);
- rrddim_set_by_pointer(st_metrics, rd_metrics_timer, (collected_number)statsd.timers.metrics);
- rrddim_set_by_pointer(st_metrics, rd_metrics_meter, (collected_number)statsd.meters.metrics);
- rrddim_set_by_pointer(st_metrics, rd_metrics_histogram, (collected_number)statsd.histograms.metrics);
- rrddim_set_by_pointer(st_metrics, rd_metrics_set, (collected_number)statsd.sets.metrics);
- rrdset_done(st_metrics);
-
- rrddim_set_by_pointer(st_events, rd_events_gauge, (collected_number)statsd.gauges.events);
- rrddim_set_by_pointer(st_events, rd_events_counter, (collected_number)statsd.counters.events);
- rrddim_set_by_pointer(st_events, rd_events_timer, (collected_number)statsd.timers.events);
- rrddim_set_by_pointer(st_events, rd_events_meter, (collected_number)statsd.meters.events);
- rrddim_set_by_pointer(st_events, rd_events_histogram, (collected_number)statsd.histograms.events);
- rrddim_set_by_pointer(st_events, rd_events_set, (collected_number)statsd.sets.events);
- rrddim_set_by_pointer(st_events, rd_events_unknown, (collected_number)statsd.unknown_types);
- rrddim_set_by_pointer(st_events, rd_events_errors, (collected_number)statsd.socket_errors);
- rrdset_done(st_events);
-
- rrddim_set_by_pointer(st_reads, rd_reads_tcp, (collected_number)statsd.tcp_socket_reads);
- rrddim_set_by_pointer(st_reads, rd_reads_udp, (collected_number)statsd.udp_socket_reads);
- rrdset_done(st_reads);
-
- rrddim_set_by_pointer(st_bytes, rd_bytes_tcp, (collected_number)statsd.tcp_bytes_read);
- rrddim_set_by_pointer(st_bytes, rd_bytes_udp, (collected_number)statsd.udp_bytes_read);
- rrdset_done(st_bytes);
-
- rrddim_set_by_pointer(st_packets, rd_packets_tcp, (collected_number)statsd.tcp_packets_received);
- rrddim_set_by_pointer(st_packets, rd_packets_udp, (collected_number)statsd.udp_packets_received);
- rrdset_done(st_packets);
-
- rrddim_set_by_pointer(st_tcp_connects, rd_tcp_connects, (collected_number)statsd.tcp_socket_connects);
- rrddim_set_by_pointer(st_tcp_connects, rd_tcp_disconnects, (collected_number)statsd.tcp_socket_disconnects);
- rrdset_done(st_tcp_connects);
-
- rrddim_set_by_pointer(st_tcp_connected, rd_tcp_connected, (collected_number)statsd.tcp_socket_connected);
- rrdset_done(st_tcp_connected);
-
- rrddim_set_by_pointer(st_pcharts, rd_pcharts, (collected_number)statsd.private_charts);
- rrdset_done(st_pcharts);
-
- rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
- rrddim_set_by_pointer(stcpu_thread, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
- rrdset_done(stcpu_thread);
-
- for(i = 0; i < statsd.threads ;i++) {
- rrddim_set_by_pointer(statsd.collection_threads_status[i].st_cpu, statsd.collection_threads_status[i].rd_user, statsd.collection_threads_status[i].rusage.ru_utime.tv_sec * 1000000ULL + statsd.collection_threads_status[i].rusage.ru_utime.tv_usec);
- rrddim_set_by_pointer(statsd.collection_threads_status[i].st_cpu, statsd.collection_threads_status[i].rd_system, statsd.collection_threads_status[i].rusage.ru_stime.tv_sec * 1000000ULL + statsd.collection_threads_status[i].rusage.ru_stime.tv_usec);
- rrdset_done(statsd.collection_threads_status[i].st_cpu);
- }
- }
-
-cleanup: ; // added semi-colon to prevent older gcc error: label at end of compound statement
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/statsd.h b/src/statsd.h
deleted file mode 100644
index 17af098e8..000000000
--- a/src/statsd.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef NETDATA_STATSD_H
-#define NETDATA_STATSD_H
-
-#define STATSD_LISTEN_PORT 8125
-#define STATSD_LISTEN_BACKLOG 4096
-
-extern void *statsd_main(void *ptr);
-
-#endif //NETDATA_STATSD_H
diff --git a/src/storage_number.c b/src/storage_number.c
deleted file mode 100644
index c7bbaa8d9..000000000
--- a/src/storage_number.c
+++ /dev/null
@@ -1,231 +0,0 @@
-#include "common.h"
-
-storage_number pack_storage_number(calculated_number value, uint32_t flags)
-{
- // bit 32 = sign 0:positive, 1:negative
- // bit 31 = 0:divide, 1:multiply
- // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total)
- // bit 27, 26, 25 flags
- // bit 24 to bit 1 = the value
-
- storage_number r = get_storage_number_flags(flags);
- if(!value) return r;
-
- int m = 0;
- calculated_number n = value;
-
- // if the value is negative
- // add the sign bit and make it positive
- if(n < 0) {
- r += (1 << 31); // the sign bit 32
- n = -n;
- }
-
- // make its integer part fit in 0x00ffffff
- // by dividing it by 10 up to 7 times
- // and increasing the multiplier
- while(m < 7 && n > (calculated_number)0x00ffffff) {
- n /= 10;
- m++;
- }
-
- if(m) {
- // the value was too big and we divided it
- // so we add a multiplier to unpack it
- r += (1 << 30) + (m << 27); // the multiplier m
-
- if(n > (calculated_number)0x00ffffff) {
- #ifdef NETDATA_INTERNAL_CHECKS
- error("Number " CALCULATED_NUMBER_FORMAT " is too big.", value);
- #endif
- r += 0x00ffffff;
- return r;
- }
- }
- else {
- // 0x0019999e is the number that can be multiplied
- // by 10 to give 0x00ffffff
- // while the value is below 0x0019999e we can
- // multiply it by 10, up to 7 times, increasing
- // the multiplier
- while(m < 7 && n < (calculated_number)0x0019999e) {
- n *= 10;
- m++;
- }
-
- // the value was small enough and we multiplied it
- // so we add a divider to unpack it
- r += (0 << 30) + (m << 27); // the divider m
- }
-
-#ifdef STORAGE_WITH_MATH
- // without this there are rounding problems
- // example: 0.9 becomes 0.89
- r += lrint((double) n);
-#else
- r += (storage_number)n;
-#endif
-
- return r;
-}
-
-calculated_number unpack_storage_number(storage_number value)
-{
- if(!value) return 0;
-
- int sign = 0, exp = 0;
-
- value ^= get_storage_number_flags(value);
-
- if(value & (1 << 31)) {
- sign = 1;
- value ^= 1 << 31;
- }
-
- if(value & (1 << 30)) {
- exp = 1;
- value ^= 1 << 30;
- }
-
- int mul = value >> 27;
- value ^= mul << 27;
-
- calculated_number n = value;
-
- // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, n);
-
- while(mul > 0) {
- if(exp) n *= 10;
- else n /= 10;
- mul--;
- }
-
- if(sign) n = -n;
- return n;
-}
-
-/*
-int print_calculated_number(char *str, calculated_number value)
-{
- char *wstr = str;
-
- int sign = (value < 0) ? 1 : 0;
- if(sign) value = -value;
-
-#ifdef STORAGE_WITH_MATH
- // without llrintl() there are rounding problems
- // for example 0.9 becomes 0.89
- unsigned long long uvalue = (unsigned long long int) llrintl(value * (calculated_number)100000);
-#else
- unsigned long long uvalue = value * (calculated_number)100000;
-#endif
-
- wstr = print_number_llu_r_smart(str, uvalue);
-
- // make sure we have 6 bytes at least
- while((wstr - str) < 6) *wstr++ = '0';
-
- // put the sign back
- if(sign) *wstr++ = '-';
-
- // reverse it
- char *begin = str, *end = --wstr, aux;
- while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
- // wstr--;
- // strreverse(str, wstr);
-
- // remove trailing zeros
- int decimal = 5;
- while(decimal > 0 && *wstr == '0') {
- *wstr-- = '\0';
- decimal--;
- }
-
- // terminate it, one position to the right
- // to let space for a dot
- wstr[2] = '\0';
-
- // make space for the dot
- int i;
- for(i = 0; i < decimal ;i++) {
- wstr[1] = wstr[0];
- wstr--;
- }
-
- // put the dot
- if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
- else wstr[1] = '.';
-
- // return the buffer length
- return (int) ((wstr - str) + 2 + decimal );
-}
-*/
-
-int print_calculated_number(char *str, calculated_number value) {
- // info("printing number " CALCULATED_NUMBER_FORMAT, value);
- char integral_str[50], fractional_str[50];
-
- char *wstr = str;
-
- if(unlikely(value < 0)) {
- *wstr++ = '-';
- value = -value;
- }
-
- calculated_number integral, fractional;
-
-#ifdef STORAGE_WITH_MATH
- fractional = calculated_number_modf(value, &integral) * 10000000.0;
-#else
- fractional = ((unsigned long long)(value * 10000000ULL) % 10000000ULL);
-#endif
-
- unsigned long long integral_int = (unsigned long long)integral;
- unsigned long long fractional_int = (unsigned long long)calculated_number_llrint(fractional);
- if(unlikely(fractional_int >= 10000000)) {
- integral_int += 1;
- fractional_int -= 10000000;
- }
-
- // info("integral " CALCULATED_NUMBER_FORMAT " (%llu), fractional " CALCULATED_NUMBER_FORMAT " (%llu)", integral, integral_int, fractional, fractional_int);
-
- char *istre;
- if(unlikely(integral_int == 0)) {
- integral_str[0] = '0';
- istre = &integral_str[1];
- }
- else
- // convert the integral part to string (reversed)
- istre = print_number_llu_r_smart(integral_str, integral_int);
-
- // copy reversed the integral string
- istre--;
- while( istre >= integral_str ) *wstr++ = *istre--;
-
- if(likely(fractional_int != 0)) {
- // add a dot
- *wstr++ = '.';
-
- // convert the fractional part to string (reversed)
- char *fstre = print_number_llu_r_smart(fractional_str, fractional_int);
-
- // prepend zeros to reach 7 digits length
- int decimal = 7;
- int len = (int)(fstre - fractional_str);
- while(len < decimal) {
- *wstr++ = '0';
- len++;
- }
-
- char *begin = fractional_str;
- while(begin < fstre && *begin == '0') begin++;
-
- // copy reversed the fractional string
- fstre--;
- while( fstre >= begin ) *wstr++ = *fstre--;
- }
-
- *wstr = '\0';
- // info("printed number '%s'", str);
- return (int)(wstr - str);
-}
diff --git a/src/storage_number.h b/src/storage_number.h
deleted file mode 100644
index ef81863fd..000000000
--- a/src/storage_number.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef NETDATA_STORAGE_NUMBER_H
-#define NETDATA_STORAGE_NUMBER_H
-
-#ifdef NETDATA_WITHOUT_LONG_DOUBLE
-
-#define powl pow
-#define modfl modf
-#define llrintl llrint
-#define roundl round
-#define sqrtl sqrt
-#define copysignl copysign
-#define strtold strtod
-
-typedef double calculated_number;
-#define CALCULATED_NUMBER_FORMAT "%0.7f"
-#define CALCULATED_NUMBER_FORMAT_ZERO "%0.0f"
-#define CALCULATED_NUMBER_FORMAT_AUTO "%f"
-
-#define LONG_DOUBLE_MODIFIER "f"
-typedef double LONG_DOUBLE;
-
-#else
-
-typedef long double calculated_number;
-#define CALCULATED_NUMBER_FORMAT "%0.7Lf"
-#define CALCULATED_NUMBER_FORMAT_ZERO "%0.0Lf"
-#define CALCULATED_NUMBER_FORMAT_AUTO "%Lf"
-
-#define LONG_DOUBLE_MODIFIER "Lf"
-typedef long double LONG_DOUBLE;
-
-#endif
-
-//typedef long long calculated_number;
-//#define CALCULATED_NUMBER_FORMAT "%lld"
-
-typedef long long collected_number;
-#define COLLECTED_NUMBER_FORMAT "%lld"
-
-/*
-typedef long double collected_number;
-#define COLLECTED_NUMBER_FORMAT "%0.7Lf"
-*/
-
-#define calculated_number_modf(x, y) modfl(x, y)
-#define calculated_number_llrint(x) llrintl(x)
-#define calculated_number_round(x) roundl(x)
-#define calculated_number_fabs(x) fabsl(x)
-#define calculated_number_epsilon (calculated_number)0.0000001
-
-#define calculated_number_equal(a, b) (calculated_number_fabs((a) - (b)) < calculated_number_epsilon)
-
-typedef uint32_t storage_number;
-#define STORAGE_NUMBER_FORMAT "%u"
-
-#define SN_NOT_EXISTS (0x0 << 24)
-#define SN_EXISTS (0x1 << 24)
-#define SN_EXISTS_RESET (0x2 << 24)
-#define SN_EXISTS_UNDEF1 (0x3 << 24)
-#define SN_EXISTS_UNDEF2 (0x4 << 24)
-#define SN_EXISTS_UNDEF3 (0x5 << 24)
-#define SN_EXISTS_UNDEF4 (0x6 << 24)
-
-#define SN_FLAGS_MASK (~(0x6 << 24))
-
-// extract the flags
-#define get_storage_number_flags(value) ((((storage_number)(value)) & (1 << 24)) | (((storage_number)(value)) & (2 << 24)) | (((storage_number)(value)) & (4 << 24)))
-#define SN_EMPTY_SLOT 0x00000000
-
-// checks
-#define does_storage_number_exist(value) ((get_storage_number_flags(value) != 0)?1:0)
-#define did_storage_number_reset(value) ((get_storage_number_flags(value) == SN_EXISTS_RESET)?1:0)
-
-storage_number pack_storage_number(calculated_number value, uint32_t flags);
-calculated_number unpack_storage_number(storage_number value);
-
-int print_calculated_number(char *str, calculated_number value);
-
-#define STORAGE_NUMBER_POSITIVE_MAX (167772150000000.0)
-#define STORAGE_NUMBER_POSITIVE_MIN (0.0000001)
-#define STORAGE_NUMBER_NEGATIVE_MAX (-0.0000001)
-#define STORAGE_NUMBER_NEGATIVE_MIN (-167772150000000.0)
-
-// accepted accuracy loss
-#define ACCURACY_LOSS 0.0001
-#define accuracy_loss(t1, t2) (((t1) == (t2) || (t1) == 0.0 || (t2) == 0.0) ? 0.0 : (100.0 - (((t1) > (t2)) ? ((t2) * 100.0 / (t1) ) : ((t1) * 100.0 / (t2)))))
-
-#endif /* NETDATA_STORAGE_NUMBER_H */
diff --git a/src/sys_devices_system_edac_mc.c b/src/sys_devices_system_edac_mc.c
deleted file mode 100644
index caa16192e..000000000
--- a/src/sys_devices_system_edac_mc.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#include "common.h"
-
-struct mc {
- char *name;
- char ce_updated;
- char ue_updated;
-
- char *ce_count_filename;
- char *ue_count_filename;
-
- procfile *ce_ff;
- procfile *ue_ff;
-
- collected_number ce_count;
- collected_number ue_count;
-
- RRDDIM *ce_rd;
- RRDDIM *ue_rd;
-
- struct mc *next;
-};
-static struct mc *mc_root = NULL;
-
-static void find_all_mc() {
- char name[FILENAME_MAX + 1];
- snprintfz(name, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/edac/mc");
- char *dirname = config_get("plugin:proc:/sys/devices/system/edac/mc", "directory to monitor", name);
-
- DIR *dir = opendir(dirname);
- if(unlikely(!dir)) {
- error("Cannot read ECC memory errors directory '%s'", dirname);
- return;
- }
-
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type == DT_DIR && de->d_name[0] == 'm' && de->d_name[1] == 'c' && isdigit(de->d_name[2])) {
- struct mc *m = callocz(1, sizeof(struct mc));
- m->name = strdupz(de->d_name);
-
- struct stat st;
-
- snprintfz(name, FILENAME_MAX, "%s/%s/ce_count", dirname, de->d_name);
- if(stat(name, &st) != -1)
- m->ce_count_filename = strdupz(name);
-
- snprintfz(name, FILENAME_MAX, "%s/%s/ue_count", dirname, de->d_name);
- if(stat(name, &st) != -1)
- m->ue_count_filename = strdupz(name);
-
- if(!m->ce_count_filename && !m->ue_count_filename) {
- freez(m->name);
- freez(m);
- }
- else {
- m->next = mc_root;
- mc_root = m;
- }
- }
- }
-
- closedir(dir);
-}
-
-int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) {
- (void)dt;
-
- if(unlikely(mc_root == NULL)) {
- find_all_mc();
- if(unlikely(mc_root == NULL))
- return 1;
- }
-
- static int do_ce = -1, do_ue = -1;
- calculated_number ce_sum = 0, ue_sum = 0;
- struct mc *m;
-
- if(unlikely(do_ce == -1)) {
- do_ce = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory correctable errors", CONFIG_BOOLEAN_AUTO);
- do_ue = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory uncorrectable errors", CONFIG_BOOLEAN_AUTO);
- }
-
- if(do_ce != CONFIG_BOOLEAN_NO) {
- for(m = mc_root; m; m = m->next) {
- if(m->ce_count_filename) {
- m->ce_updated = 0;
-
- if(unlikely(!m->ce_ff)) {
- m->ce_ff = procfile_open(m->ce_count_filename, " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!m->ce_ff))
- continue;
- }
-
- m->ce_ff = procfile_readall(m->ce_ff);
- if(unlikely(!m->ce_ff || procfile_lines(m->ce_ff) < 1 || procfile_linewords(m->ce_ff, 0) < 1))
- continue;
-
- m->ce_count = str2ull(procfile_lineword(m->ce_ff, 0, 0));
- ce_sum += m->ce_count;
- m->ce_updated = 1;
- }
- }
- }
-
- if(do_ue != CONFIG_BOOLEAN_NO) {
- for(m = mc_root; m; m = m->next) {
- if(m->ue_count_filename) {
- m->ue_updated = 0;
-
- if(unlikely(!m->ue_ff)) {
- m->ue_ff = procfile_open(m->ue_count_filename, " \t", PROCFILE_FLAG_DEFAULT);
- if(unlikely(!m->ue_ff))
- continue;
- }
-
- m->ue_ff = procfile_readall(m->ue_ff);
- if(unlikely(!m->ue_ff || procfile_lines(m->ue_ff) < 1 || procfile_linewords(m->ue_ff, 0) < 1))
- continue;
-
- m->ue_count = str2ull(procfile_lineword(m->ue_ff, 0, 0));
- ue_sum += m->ue_count;
- m->ue_updated = 1;
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- if(do_ce == CONFIG_BOOLEAN_YES || (do_ce == CONFIG_BOOLEAN_AUTO && ce_sum > 0)) {
- do_ce = CONFIG_BOOLEAN_YES;
-
- static RRDSET *ce_st = NULL;
-
- if(unlikely(!ce_st)) {
- ce_st = rrdset_create_localhost(
- "mem"
- , "ecc_ce"
- , NULL
- , "ecc"
- , NULL
- , "ECC Memory Correctable Errors"
- , "errors"
- , "proc"
- , "/sys/devices/system/edac/mc"
- , NETDATA_CHART_PRIO_MEM_HW + 50
- , update_every
- , RRDSET_TYPE_LINE
- );
- }
- else
- rrdset_next(ce_st);
-
- for(m = mc_root; m; m = m->next) {
- if (m->ce_count_filename && m->ce_updated) {
- if(unlikely(!m->ce_rd))
- m->ce_rd = rrddim_add(ce_st, m->name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(ce_st, m->ce_rd, m->ce_count);
- }
- }
-
- rrdset_done(ce_st);
- }
-
- // --------------------------------------------------------------------
-
- if(do_ue == CONFIG_BOOLEAN_YES || (do_ue == CONFIG_BOOLEAN_AUTO && ue_sum > 0)) {
- do_ue = CONFIG_BOOLEAN_YES;
-
- static RRDSET *ue_st = NULL;
-
- if(unlikely(!ue_st)) {
- ue_st = rrdset_create_localhost(
- "mem"
- , "ecc_ue"
- , NULL
- , "ecc"
- , NULL
- , "ECC Memory Uncorrectable Errors"
- , "errors"
- , "proc"
- , "/sys/devices/system/edac/mc"
- , NETDATA_CHART_PRIO_MEM_HW + 60
- , update_every
- , RRDSET_TYPE_LINE
- );
- }
- else
- rrdset_next(ue_st);
-
- for(m = mc_root; m; m = m->next) {
- if (m->ue_count_filename && m->ue_updated) {
- if(unlikely(!m->ue_rd))
- m->ue_rd = rrddim_add(ue_st, m->name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(ue_st, m->ue_rd, m->ue_count);
- }
- }
-
- rrdset_done(ue_st);
- }
-
- return 0;
-}
diff --git a/src/sys_devices_system_node.c b/src/sys_devices_system_node.c
deleted file mode 100644
index d04c8dc30..000000000
--- a/src/sys_devices_system_node.c
+++ /dev/null
@@ -1,161 +0,0 @@
-#include "common.h"
-
-struct node {
- char *name;
- char *numastat_filename;
- procfile *numastat_ff;
- RRDSET *numastat_st;
- struct node *next;
-};
-static struct node *numa_root = NULL;
-
-static int find_all_nodes() {
- int numa_node_count = 0;
- char name[FILENAME_MAX + 1];
- snprintfz(name, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/node");
- char *dirname = config_get("plugin:proc:/sys/devices/system/node", "directory to monitor", name);
-
- DIR *dir = opendir(dirname);
- if(!dir) {
- error("Cannot read NUMA node directory '%s'", dirname);
- return 0;
- }
-
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type != DT_DIR)
- continue;
-
- if(strncmp(de->d_name, "node", 4) != 0)
- continue;
-
- if(!isdigit(de->d_name[4]))
- continue;
-
- numa_node_count++;
-
- struct node *m = callocz(1, sizeof(struct node));
- m->name = strdupz(de->d_name);
-
- struct stat st;
-
- snprintfz(name, FILENAME_MAX, "%s/%s/numastat", dirname, de->d_name);
- if(stat(name, &st) == -1) {
- freez(m->name);
- freez(m);
- continue;
- }
-
- m->numastat_filename = strdupz(name);
-
- m->next = numa_root;
- numa_root = m;
- }
-
- closedir(dir);
-
- return numa_node_count;
-}
-
-int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
- (void)dt;
-
- static uint32_t hash_local_node = 0, hash_numa_foreign = 0, hash_interleave_hit = 0, hash_other_node = 0, hash_numa_hit = 0, hash_numa_miss = 0;
- static int do_numastat = -1, numa_node_count = 0;
- struct node *m;
-
- if(unlikely(numa_root == NULL)) {
- numa_node_count = find_all_nodes();
- if(unlikely(numa_root == NULL))
- return 1;
- }
-
- if(unlikely(do_numastat == -1)) {
- do_numastat = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO);
-
- hash_local_node = simple_hash("local_node");
- hash_numa_foreign = simple_hash("numa_foreign");
- hash_interleave_hit = simple_hash("interleave_hit");
- hash_other_node = simple_hash("other_node");
- hash_numa_hit = simple_hash("numa_hit");
- hash_numa_miss = simple_hash("numa_miss");
- }
-
- if(do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) {
- for(m = numa_root; m; m = m->next) {
- if(m->numastat_filename) {
-
- if(unlikely(!m->numastat_ff)) {
- m->numastat_ff = procfile_open(m->numastat_filename, " ", PROCFILE_FLAG_DEFAULT);
-
- if(unlikely(!m->numastat_ff))
- continue;
- }
-
- m->numastat_ff = procfile_readall(m->numastat_ff);
- if(unlikely(!m->numastat_ff || procfile_lines(m->numastat_ff) < 1 || procfile_linewords(m->numastat_ff, 0) < 1))
- continue;
-
- if(unlikely(!m->numastat_st)) {
- m->numastat_st = rrdset_create_localhost(
- "mem"
- , m->name
- , NULL
- , "numa"
- , NULL
- , "NUMA events"
- , "events/s"
- , "proc"
- , "/sys/devices/system/node"
- , NETDATA_CHART_PRIO_MEM_NUMA + 10
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrdset_flag_set(m->numastat_st, RRDSET_FLAG_DETAIL);
-
- rrddim_add(m->numastat_st, "numa_hit", "hit", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(m->numastat_st, "numa_miss", "miss", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(m->numastat_st, "local_node", "local", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(m->numastat_st, "numa_foreign", "foreign", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(m->numastat_st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(m->numastat_st, "other_node", "other", 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- }
- else rrdset_next(m->numastat_st);
-
- size_t lines = procfile_lines(m->numastat_ff), l;
- for(l = 0; l < lines; l++) {
- size_t words = procfile_linewords(m->numastat_ff, l);
-
- if(unlikely(words < 2)) {
- if(unlikely(words))
- error("Cannot read %s numastat line %zu. Expected 2 params, read %zu.", m->name, l, words);
- continue;
- }
-
- char *name = procfile_lineword(m->numastat_ff, l, 0);
- char *value = procfile_lineword(m->numastat_ff, l, 1);
-
- if (unlikely(!name || !*name || !value || !*value))
- continue;
-
- uint32_t hash = simple_hash(name);
- if(likely(
- (hash == hash_numa_hit && !strcmp(name, "numa_hit"))
- || (hash == hash_numa_miss && !strcmp(name, "numa_miss"))
- || (hash == hash_local_node && !strcmp(name, "local_node"))
- || (hash == hash_numa_foreign && !strcmp(name, "numa_foreign"))
- || (hash == hash_interleave_hit && !strcmp(name, "interleave_hit"))
- || (hash == hash_other_node && !strcmp(name, "other_node"))
- ))
- rrddim_set(m->numastat_st, name, (collected_number)str2kernel_uint_t(value));
- }
-
- rrdset_done(m->numastat_st);
- }
- }
- }
-
- return 0;
-}
diff --git a/src/sys_fs_btrfs.c b/src/sys_fs_btrfs.c
deleted file mode 100644
index a8dfb5c91..000000000
--- a/src/sys_fs_btrfs.c
+++ /dev/null
@@ -1,714 +0,0 @@
-#include "common.h"
-
-typedef struct btrfs_disk {
- char *name;
- uint32_t hash;
- int exists;
-
- char *size_filename;
- char *hw_sector_size_filename;
- unsigned long long size;
- unsigned long long hw_sector_size;
-
- struct btrfs_disk *next;
-} BTRFS_DISK;
-
-typedef struct btrfs_node {
- int exists;
- int logged_error;
-
- char *id;
- uint32_t hash;
-
- char *label;
-
- // unsigned long long int sectorsize;
- // unsigned long long int nodesize;
- // unsigned long long int quota_override;
-
- #define declare_btrfs_allocation_section_field(SECTION, FIELD) \
- char *allocation_ ## SECTION ## _ ## FIELD ## _filename; \
- unsigned long long int allocation_ ## SECTION ## _ ## FIELD;
-
- #define declare_btrfs_allocation_field(FIELD) \
- char *allocation_ ## FIELD ## _filename; \
- unsigned long long int allocation_ ## FIELD;
-
- RRDSET *st_allocation_disks;
- RRDDIM *rd_allocation_disks_unallocated;
- RRDDIM *rd_allocation_disks_data_used;
- RRDDIM *rd_allocation_disks_data_free;
- RRDDIM *rd_allocation_disks_metadata_used;
- RRDDIM *rd_allocation_disks_metadata_free;
- RRDDIM *rd_allocation_disks_system_used;
- RRDDIM *rd_allocation_disks_system_free;
- unsigned long long all_disks_total;
-
- RRDSET *st_allocation_data;
- RRDDIM *rd_allocation_data_free;
- RRDDIM *rd_allocation_data_used;
- declare_btrfs_allocation_section_field(data, total_bytes)
- declare_btrfs_allocation_section_field(data, bytes_used)
- declare_btrfs_allocation_section_field(data, disk_total)
- declare_btrfs_allocation_section_field(data, disk_used)
-
- RRDSET *st_allocation_metadata;
- RRDDIM *rd_allocation_metadata_free;
- RRDDIM *rd_allocation_metadata_used;
- RRDDIM *rd_allocation_metadata_reserved;
- declare_btrfs_allocation_section_field(metadata, total_bytes)
- declare_btrfs_allocation_section_field(metadata, bytes_used)
- declare_btrfs_allocation_section_field(metadata, disk_total)
- declare_btrfs_allocation_section_field(metadata, disk_used)
- //declare_btrfs_allocation_field(global_rsv_reserved)
- declare_btrfs_allocation_field(global_rsv_size)
-
- RRDSET *st_allocation_system;
- RRDDIM *rd_allocation_system_free;
- RRDDIM *rd_allocation_system_used;
- declare_btrfs_allocation_section_field(system, total_bytes)
- declare_btrfs_allocation_section_field(system, bytes_used)
- declare_btrfs_allocation_section_field(system, disk_total)
- declare_btrfs_allocation_section_field(system, disk_used)
-
- BTRFS_DISK *disks;
-
- struct btrfs_node *next;
-} BTRFS_NODE;
-
-static BTRFS_NODE *nodes = NULL;
-
-static inline void btrfs_free_disk(BTRFS_DISK *d) {
- freez(d->name);
- freez(d->size_filename);
- freez(d->hw_sector_size_filename);
- freez(d);
-}
-
-static inline void btrfs_free_node(BTRFS_NODE *node) {
- // info("BTRFS: destroying '%s'", node->id);
-
- if(node->st_allocation_disks)
- rrdset_is_obsolete(node->st_allocation_disks);
-
- if(node->st_allocation_data)
- rrdset_is_obsolete(node->st_allocation_data);
-
- if(node->st_allocation_metadata)
- rrdset_is_obsolete(node->st_allocation_metadata);
-
- if(node->st_allocation_system)
- rrdset_is_obsolete(node->st_allocation_system);
-
- freez(node->allocation_data_bytes_used_filename);
- freez(node->allocation_data_total_bytes_filename);
-
- freez(node->allocation_metadata_bytes_used_filename);
- freez(node->allocation_metadata_total_bytes_filename);
-
- freez(node->allocation_system_bytes_used_filename);
- freez(node->allocation_system_total_bytes_filename);
-
- while(node->disks) {
- BTRFS_DISK *d = node->disks;
- node->disks = node->disks->next;
- btrfs_free_disk(d);
- }
-
- freez(node->label);
- freez(node->id);
- freez(node);
-}
-
-static inline int find_btrfs_disks(BTRFS_NODE *node, const char *path) {
- char filename[FILENAME_MAX + 1];
-
- node->all_disks_total = 0;
-
- BTRFS_DISK *d;
- for(d = node->disks ; d ; d = d->next)
- d->exists = 0;
-
- DIR *dir = opendir(path);
- if (!dir) {
- if(!node->logged_error) {
- error("BTRFS: Cannot open directory '%s'.", path);
- node->logged_error = 1;
- }
- return 1;
- }
- node->logged_error = 0;
-
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- if (de->d_type != DT_LNK
- || !strcmp(de->d_name, ".")
- || !strcmp(de->d_name, "..")
- ) {
- // info("BTRFS: ignoring '%s'", de->d_name);
- continue;
- }
-
- uint32_t hash = simple_hash(de->d_name);
-
- // --------------------------------------------------------------------
- // search for it
-
- for(d = node->disks ; d ; d = d->next) {
- if(hash == d->hash && !strcmp(de->d_name, d->name))
- break;
- }
-
- // --------------------------------------------------------------------
- // did we find it?
-
- if(!d) {
- d = callocz(sizeof(BTRFS_DISK), 1);
-
- d->name = strdupz(de->d_name);
- d->hash = simple_hash(d->name);
-
- snprintfz(filename, FILENAME_MAX, "%s/%s/size", path, de->d_name);
- d->size_filename = strdupz(filename);
-
- // for disks
- snprintfz(filename, FILENAME_MAX, "%s/%s/queue/hw_sector_size", path, de->d_name);
- struct stat sb;
- if(stat(filename, &sb) == -1)
- // for partitions
- snprintfz(filename, FILENAME_MAX, "%s/%s/../queue/hw_sector_size", path, de->d_name);
-
- d->hw_sector_size_filename = strdupz(filename);
-
- // link it
- d->next = node->disks;
- node->disks = d;
- }
-
- d->exists = 1;
-
-
- // --------------------------------------------------------------------
- // update the values
-
- if(read_single_number_file(d->size_filename, &d->size) != 0) {
- error("BTRFS: failed to read '%s'", d->size_filename);
- d->exists = 0;
- continue;
- }
-
- if(read_single_number_file(d->hw_sector_size_filename, &d->hw_sector_size) != 0) {
- error("BTRFS: failed to read '%s'", d->hw_sector_size_filename);
- d->exists = 0;
- continue;
- }
-
- node->all_disks_total += d->size * d->hw_sector_size;
- }
- closedir(dir);
-
- // ------------------------------------------------------------------------
- // cleanup
-
- BTRFS_DISK *last = NULL;
- d = node->disks;
-
- while(d) {
- if(unlikely(!d->exists)) {
- if(unlikely(node->disks == d)) {
- node->disks = d->next;
- btrfs_free_disk(d);
- d = node->disks;
- last = NULL;
- }
- else {
- last->next = d->next;
- btrfs_free_disk(d);
- d = last->next;
- }
-
- continue;
- }
-
- last = d;
- d = d->next;
- }
-
- return 0;
-}
-
-
-static inline int find_all_btrfs_pools(const char *path) {
- static int logged_error = 0;
- char filename[FILENAME_MAX + 1];
-
- BTRFS_NODE *node;
- for(node = nodes ; node ; node = node->next)
- node->exists = 0;
-
- DIR *dir = opendir(path);
- if (!dir) {
- if(!logged_error) {
- error("BTRFS: Cannot open directory '%s'.", path);
- logged_error = 1;
- }
- return 1;
- }
- logged_error = 0;
-
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- if(de->d_type != DT_DIR
- || !strcmp(de->d_name, ".")
- || !strcmp(de->d_name, "..")
- || !strcmp(de->d_name, "features")
- ) {
- // info("BTRFS: ignoring '%s'", de->d_name);
- continue;
- }
-
- uint32_t hash = simple_hash(de->d_name);
-
- // search for it
- for(node = nodes ; node ; node = node->next) {
- if(hash == node->hash && !strcmp(de->d_name, node->id))
- break;
- }
-
- // did we find it?
- if(node) {
- // info("BTRFS: already exists '%s'", de->d_name);
- node->exists = 1;
-
- // update the disk sizes
- snprintfz(filename, FILENAME_MAX, "%s/%s/devices", path, de->d_name);
- find_btrfs_disks(node, filename);
-
- continue;
- }
-
- // info("BTRFS: adding '%s'", de->d_name);
-
- // not found, create it
- node = callocz(sizeof(BTRFS_NODE), 1);
-
- node->id = strdupz(de->d_name);
- node->hash = simple_hash(node->id);
- node->exists = 1;
-
- {
- char label[FILENAME_MAX + 1] = "";
-
- snprintfz(filename, FILENAME_MAX, "%s/%s/label", path, de->d_name);
- read_file(filename, label, FILENAME_MAX);
-
- char *s = label;
- if (s[0])
- s = trim(label);
-
- if(s && s[0])
- node->label = strdupz(s);
- else
- node->label = strdupz(node->id);
- }
-
- //snprintfz(filename, FILENAME_MAX, "%s/%s/sectorsize", path, de->d_name);
- //if(read_single_number_file(filename, &node->sectorsize) != 0) {
- // error("BTRFS: failed to read '%s'", filename);
- // btrfs_free_node(node);
- // continue;
- //}
-
- //snprintfz(filename, FILENAME_MAX, "%s/%s/nodesize", path, de->d_name);
- //if(read_single_number_file(filename, &node->nodesize) != 0) {
- // error("BTRFS: failed to read '%s'", filename);
- // btrfs_free_node(node);
- // continue;
- //}
-
- //snprintfz(filename, FILENAME_MAX, "%s/%s/quota_override", path, de->d_name);
- //if(read_single_number_file(filename, &node->quota_override) != 0) {
- // error("BTRFS: failed to read '%s'", filename);
- // btrfs_free_node(node);
- // continue;
- //}
-
- // --------------------------------------------------------------------
- // macros to simplify our life
-
- #define init_btrfs_allocation_field(FIELD) {\
- snprintfz(filename, FILENAME_MAX, "%s/%s/allocation/" #FIELD, path, de->d_name); \
- if(read_single_number_file(filename, &node->allocation_ ## FIELD) != 0) {\
- error("BTRFS: failed to read '%s'", filename);\
- btrfs_free_node(node);\
- continue;\
- }\
- if(!node->allocation_ ## FIELD ## _filename)\
- node->allocation_ ## FIELD ## _filename = strdupz(filename);\
- }
-
- #define init_btrfs_allocation_section_field(SECTION, FIELD) {\
- snprintfz(filename, FILENAME_MAX, "%s/%s/allocation/" #SECTION "/" #FIELD, path, de->d_name); \
- if(read_single_number_file(filename, &node->allocation_ ## SECTION ## _ ## FIELD) != 0) {\
- error("BTRFS: failed to read '%s'", filename);\
- btrfs_free_node(node);\
- continue;\
- }\
- if(!node->allocation_ ## SECTION ## _ ## FIELD ## _filename)\
- node->allocation_ ## SECTION ## _ ## FIELD ## _filename = strdupz(filename);\
- }
-
- // --------------------------------------------------------------------
- // allocation/data
-
- init_btrfs_allocation_section_field(data, total_bytes);
- init_btrfs_allocation_section_field(data, bytes_used);
- init_btrfs_allocation_section_field(data, disk_total);
- init_btrfs_allocation_section_field(data, disk_used);
-
-
- // --------------------------------------------------------------------
- // allocation/metadata
-
- init_btrfs_allocation_section_field(metadata, total_bytes);
- init_btrfs_allocation_section_field(metadata, bytes_used);
- init_btrfs_allocation_section_field(metadata, disk_total);
- init_btrfs_allocation_section_field(metadata, disk_used);
-
- init_btrfs_allocation_field(global_rsv_size);
- // init_btrfs_allocation_field(global_rsv_reserved);
-
-
- // --------------------------------------------------------------------
- // allocation/system
-
- init_btrfs_allocation_section_field(system, total_bytes);
- init_btrfs_allocation_section_field(system, bytes_used);
- init_btrfs_allocation_section_field(system, disk_total);
- init_btrfs_allocation_section_field(system, disk_used);
-
-
- // --------------------------------------------------------------------
- // find all disks related to this node
- // and collect their sizes
-
- snprintfz(filename, FILENAME_MAX, "%s/%s/devices", path, de->d_name);
- find_btrfs_disks(node, filename);
-
-
- // --------------------------------------------------------------------
- // link it
-
- // info("BTRFS: linking '%s'", node->id);
- node->next = nodes;
- nodes = node;
- }
- closedir(dir);
-
-
- // ------------------------------------------------------------------------
- // cleanup
-
- BTRFS_NODE *last = NULL;
- node = nodes;
-
- while(node) {
- if(unlikely(!node->exists)) {
- if(unlikely(nodes == node)) {
- nodes = node->next;
- btrfs_free_node(node);
- node = nodes;
- last = NULL;
- }
- else {
- last->next = node->next;
- btrfs_free_node(node);
- node = last->next;
- }
-
- continue;
- }
-
- last = node;
- node = node->next;
- }
-
- return 0;
-}
-
-int do_sys_fs_btrfs(int update_every, usec_t dt) {
- static int initialized = 0
- , do_allocation_disks = CONFIG_BOOLEAN_AUTO
- , do_allocation_system = CONFIG_BOOLEAN_AUTO
- , do_allocation_data = CONFIG_BOOLEAN_AUTO
- , do_allocation_metadata = CONFIG_BOOLEAN_AUTO;
-
- static usec_t refresh_delta = 0, refresh_every = 60 * USEC_PER_SEC;
- static char *btrfs_path = NULL;
-
- (void)dt;
-
- if(unlikely(!initialized)) {
- initialized = 1;
-
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/fs/btrfs");
- btrfs_path = config_get("plugin:proc:/sys/fs/btrfs", "path to monitor", filename);
-
- refresh_every = config_get_number("plugin:proc:/sys/fs/btrfs", "check for btrfs changes every", refresh_every / USEC_PER_SEC) * USEC_PER_SEC;
- refresh_delta = refresh_every;
-
- do_allocation_disks = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "physical disks allocation", do_allocation_disks);
- do_allocation_data = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "data allocation", do_allocation_data);
- do_allocation_metadata = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "metadata allocation", do_allocation_metadata);
- do_allocation_system = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "system allocation", do_allocation_system);
- }
-
- refresh_delta += dt;
- if(refresh_delta >= refresh_every) {
- refresh_delta = 0;
- find_all_btrfs_pools(btrfs_path);
- }
-
- BTRFS_NODE *node;
- for(node = nodes; node ; node = node->next) {
- // --------------------------------------------------------------------
- // allocation/system
-
- #define collect_btrfs_allocation_field(FIELD) \
- read_single_number_file(node->allocation_ ## FIELD ## _filename, &node->allocation_ ## FIELD)
-
- #define collect_btrfs_allocation_section_field(SECTION, FIELD) \
- read_single_number_file(node->allocation_ ## SECTION ## _ ## FIELD ## _filename, &node->allocation_ ## SECTION ## _ ## FIELD)
-
- if(do_allocation_disks != CONFIG_BOOLEAN_NO) {
- if( collect_btrfs_allocation_section_field(data, disk_total) != 0
- || collect_btrfs_allocation_section_field(data, disk_used) != 0
- || collect_btrfs_allocation_section_field(metadata, disk_total) != 0
- || collect_btrfs_allocation_section_field(metadata, disk_used) != 0
- || collect_btrfs_allocation_section_field(system, disk_total) != 0
- || collect_btrfs_allocation_section_field(system, disk_used) != 0) {
- error("BTRFS: failed to collect physical disks allocation for '%s'", node->id);
- // make it refresh btrfs at the next iteration
- refresh_delta = refresh_every;
- continue;
- }
- }
-
- if(do_allocation_data != CONFIG_BOOLEAN_NO) {
- if (collect_btrfs_allocation_section_field(data, total_bytes) != 0
- || collect_btrfs_allocation_section_field(data, bytes_used) != 0) {
- error("BTRFS: failed to collect allocation/data for '%s'", node->id);
- // make it refresh btrfs at the next iteration
- refresh_delta = refresh_every;
- continue;
- }
- }
-
- if(do_allocation_metadata != CONFIG_BOOLEAN_NO) {
- if (collect_btrfs_allocation_section_field(metadata, total_bytes) != 0
- || collect_btrfs_allocation_section_field(metadata, bytes_used) != 0
- || collect_btrfs_allocation_field(global_rsv_size) != 0
- ) {
- error("BTRFS: failed to collect allocation/metadata for '%s'", node->id);
- // make it refresh btrfs at the next iteration
- refresh_delta = refresh_every;
- continue;
- }
- }
-
- if(do_allocation_system != CONFIG_BOOLEAN_NO) {
- if (collect_btrfs_allocation_section_field(system, total_bytes) != 0
- || collect_btrfs_allocation_section_field(system, bytes_used) != 0) {
- error("BTRFS: failed to collect allocation/system for '%s'", node->id);
- // make it refresh btrfs at the next iteration
- refresh_delta = refresh_every;
- continue;
- }
- }
-
- // --------------------------------------------------------------------
- // allocation/disks
-
- if(do_allocation_disks == CONFIG_BOOLEAN_YES || (do_allocation_disks == CONFIG_BOOLEAN_AUTO && node->all_disks_total && node->allocation_data_disk_total)) {
- do_allocation_disks = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!node->st_allocation_disks)) {
- char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
-
- snprintf(id, RRD_ID_LENGTH_MAX, "disk_%s", node->id);
- snprintf(name, RRD_ID_LENGTH_MAX, "disk_%s", node->label);
- snprintf(title, 200, "BTRFS Disk Allocation for %s", node->label);
-
- netdata_fix_chart_id(id);
- netdata_fix_chart_name(name);
-
- node->st_allocation_disks = rrdset_create_localhost(
- "btrfs"
- , id
- , name
- , node->label
- , "btrfs.disk"
- , title
- , "MB"
- , "proc"
- , "sys/fs/btrfs"
- , 2300
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- node->rd_allocation_disks_unallocated = rrddim_add(node->st_allocation_disks, "unallocated", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_disks_data_used = rrddim_add(node->st_allocation_disks, "data_used", "data used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_disks_data_free = rrddim_add(node->st_allocation_disks, "data_free", "data free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_disks_metadata_used = rrddim_add(node->st_allocation_disks, "meta_used", "meta used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_disks_metadata_free = rrddim_add(node->st_allocation_disks, "meta_free", "meta free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_disks_system_used = rrddim_add(node->st_allocation_disks, "sys_used", "sys used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_disks_system_free = rrddim_add(node->st_allocation_disks, "sys_free", "sys free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(node->st_allocation_disks);
-
- // unsigned long long disk_used = node->allocation_data_disk_used + node->allocation_metadata_disk_used + node->allocation_system_disk_used;
- unsigned long long disk_total = node->allocation_data_disk_total + node->allocation_metadata_disk_total + node->allocation_system_disk_total;
- unsigned long long disk_unallocated = node->all_disks_total - disk_total;
-
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_unallocated, disk_unallocated);
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_data_used, node->allocation_data_disk_used);
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_data_free, node->allocation_data_disk_total - node->allocation_data_disk_used);
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_metadata_used, node->allocation_metadata_disk_used);
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_metadata_free, node->allocation_metadata_disk_total - node->allocation_metadata_disk_used);
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_system_used, node->allocation_system_disk_used);
- rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_system_free, node->allocation_system_disk_total - node->allocation_system_disk_used);
- rrdset_done(node->st_allocation_disks);
- }
-
-
- // --------------------------------------------------------------------
- // allocation/data
-
- if(do_allocation_data == CONFIG_BOOLEAN_YES || (do_allocation_data == CONFIG_BOOLEAN_AUTO && node->allocation_data_total_bytes)) {
- do_allocation_data = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!node->st_allocation_data)) {
- char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
-
- snprintf(id, RRD_ID_LENGTH_MAX, "data_%s", node->id);
- snprintf(name, RRD_ID_LENGTH_MAX, "data_%s", node->label);
- snprintf(title, 200, "BTRFS Data Allocation for %s", node->label);
-
- netdata_fix_chart_id(id);
- netdata_fix_chart_name(name);
-
- node->st_allocation_data = rrdset_create_localhost(
- "btrfs"
- , id
- , name
- , node->label
- , "btrfs.data"
- , title
- , "MB"
- , "proc"
- , "sys/fs/btrfs"
- , 2301
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- node->rd_allocation_data_free = rrddim_add(node->st_allocation_data, "free", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_data_used = rrddim_add(node->st_allocation_data, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(node->st_allocation_data);
-
- rrddim_set_by_pointer(node->st_allocation_data, node->rd_allocation_data_free, node->allocation_data_total_bytes - node->allocation_data_bytes_used);
- rrddim_set_by_pointer(node->st_allocation_data, node->rd_allocation_data_used, node->allocation_data_bytes_used);
- rrdset_done(node->st_allocation_data);
- }
-
- // --------------------------------------------------------------------
- // allocation/metadata
-
- if(do_allocation_metadata == CONFIG_BOOLEAN_YES || (do_allocation_metadata == CONFIG_BOOLEAN_AUTO && node->allocation_metadata_total_bytes)) {
- do_allocation_metadata = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!node->st_allocation_metadata)) {
- char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
-
- snprintf(id, RRD_ID_LENGTH_MAX, "metadata_%s", node->id);
- snprintf(name, RRD_ID_LENGTH_MAX, "metadata_%s", node->label);
- snprintf(title, 200, "BTRFS Metadata Allocation for %s", node->label);
-
- netdata_fix_chart_id(id);
- netdata_fix_chart_name(name);
-
- node->st_allocation_metadata = rrdset_create_localhost(
- "btrfs"
- , id
- , name
- , node->label
- , "btrfs.metadata"
- , title
- , "MB"
- , "proc"
- , "sys/fs/btrfs"
- , 2302
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- node->rd_allocation_metadata_free = rrddim_add(node->st_allocation_metadata, "free", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_metadata_used = rrddim_add(node->st_allocation_metadata, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_metadata_reserved = rrddim_add(node->st_allocation_metadata, "reserved", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(node->st_allocation_metadata);
-
- rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_free, node->allocation_metadata_total_bytes - node->allocation_metadata_bytes_used - node->allocation_global_rsv_size);
- rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_used, node->allocation_metadata_bytes_used);
- rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_reserved, node->allocation_global_rsv_size);
- rrdset_done(node->st_allocation_metadata);
- }
-
- // --------------------------------------------------------------------
- // allocation/system
-
- if(do_allocation_system == CONFIG_BOOLEAN_YES || (do_allocation_system == CONFIG_BOOLEAN_AUTO && node->allocation_system_total_bytes)) {
- do_allocation_system = CONFIG_BOOLEAN_YES;
-
- if(unlikely(!node->st_allocation_system)) {
- char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
-
- snprintf(id, RRD_ID_LENGTH_MAX, "system_%s", node->id);
- snprintf(name, RRD_ID_LENGTH_MAX, "system_%s", node->label);
- snprintf(title, 200, "BTRFS System Allocation for %s", node->label);
-
- netdata_fix_chart_id(id);
- netdata_fix_chart_name(name);
-
- node->st_allocation_system = rrdset_create_localhost(
- "btrfs"
- , id
- , name
- , node->label
- , "btrfs.system"
- , title
- , "MB"
- , "proc"
- , "sys/fs/btrfs"
- , 2303
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- node->rd_allocation_system_free = rrddim_add(node->st_allocation_system, "free", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- node->rd_allocation_system_used = rrddim_add(node->st_allocation_system, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else rrdset_next(node->st_allocation_system);
-
- rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_free, node->allocation_system_total_bytes - node->allocation_system_bytes_used);
- rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_used, node->allocation_system_bytes_used);
- rrdset_done(node->st_allocation_system);
- }
- }
-
- return 0;
-}
-
diff --git a/src/sys_fs_cgroup.c b/src/sys_fs_cgroup.c
deleted file mode 100644
index f6e613c4b..000000000
--- a/src/sys_fs_cgroup.c
+++ /dev/null
@@ -1,2765 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// cgroup globals
-
-#define CHART_PRIORITY_SYSTEMD_SERVICES 19000
-#define CHART_PRIORITY_CONTAINERS 40000
-
-static long system_page_size = 4096; // system will be queried via sysconf() in configuration()
-
-static int cgroup_enable_cpuacct_stat = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_cpuacct_usage = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_memory = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_detailed_memory = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_memory_failcnt = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_swap = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_blkio_io = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_blkio_ops = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_blkio_throttle_io = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_blkio_throttle_ops = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_blkio_merged_ops = CONFIG_BOOLEAN_AUTO;
-static int cgroup_enable_blkio_queued_ops = CONFIG_BOOLEAN_AUTO;
-
-static int cgroup_enable_systemd_services = CONFIG_BOOLEAN_YES;
-static int cgroup_enable_systemd_services_detailed_memory = CONFIG_BOOLEAN_NO;
-static int cgroup_used_memory_without_cache = CONFIG_BOOLEAN_YES;
-
-static int cgroup_search_in_devices = 1;
-
-static int cgroup_enable_new_cgroups_detected_at_runtime = 1;
-static int cgroup_check_for_new_every = 10;
-static int cgroup_update_every = 1;
-
-static int cgroup_recheck_zero_blkio_every_iterations = 10;
-static int cgroup_recheck_zero_mem_failcnt_every_iterations = 10;
-static int cgroup_recheck_zero_mem_detailed_every_iterations = 10;
-
-static char *cgroup_cpuacct_base = NULL;
-static char *cgroup_blkio_base = NULL;
-static char *cgroup_memory_base = NULL;
-static char *cgroup_devices_base = NULL;
-
-static int cgroup_root_count = 0;
-static int cgroup_root_max = 1000;
-static int cgroup_max_depth = 0;
-
-static SIMPLE_PATTERN *enabled_cgroup_patterns = NULL;
-static SIMPLE_PATTERN *enabled_cgroup_paths = NULL;
-static SIMPLE_PATTERN *enabled_cgroup_renames = NULL;
-static SIMPLE_PATTERN *systemd_services_cgroups = NULL;
-
-static char *cgroups_rename_script = NULL;
-static char *cgroups_network_interface_script = NULL;
-
-static int cgroups_check = 0;
-
-static uint32_t Read_hash = 0;
-static uint32_t Write_hash = 0;
-static uint32_t user_hash = 0;
-static uint32_t system_hash = 0;
-
-void read_cgroup_plugin_configuration() {
- system_page_size = sysconf(_SC_PAGESIZE);
-
- Read_hash = simple_hash("Read");
- Write_hash = simple_hash("Write");
- user_hash = simple_hash("user");
- system_hash = simple_hash("system");
-
- cgroup_update_every = (int)config_get_number("plugin:cgroups", "update every", localhost->rrd_update_every);
- if(cgroup_update_every < localhost->rrd_update_every)
- cgroup_update_every = localhost->rrd_update_every;
-
- cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every * cgroup_update_every);
- if(cgroup_check_for_new_every < cgroup_update_every)
- cgroup_check_for_new_every = cgroup_update_every;
-
- cgroup_enable_cpuacct_stat = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct stat (total CPU)", cgroup_enable_cpuacct_stat);
- cgroup_enable_cpuacct_usage = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct usage (per core CPU)", cgroup_enable_cpuacct_usage);
-
- cgroup_enable_memory = config_get_boolean_ondemand("plugin:cgroups", "enable memory (used mem including cache)", cgroup_enable_memory);
- cgroup_enable_detailed_memory = config_get_boolean_ondemand("plugin:cgroups", "enable detailed memory", cgroup_enable_detailed_memory);
- cgroup_enable_memory_failcnt = config_get_boolean_ondemand("plugin:cgroups", "enable memory limits fail count", cgroup_enable_memory_failcnt);
- cgroup_enable_swap = config_get_boolean_ondemand("plugin:cgroups", "enable swap memory", cgroup_enable_swap);
-
- cgroup_enable_blkio_io = config_get_boolean_ondemand("plugin:cgroups", "enable blkio bandwidth", cgroup_enable_blkio_io);
- cgroup_enable_blkio_ops = config_get_boolean_ondemand("plugin:cgroups", "enable blkio operations", cgroup_enable_blkio_ops);
- cgroup_enable_blkio_throttle_io = config_get_boolean_ondemand("plugin:cgroups", "enable blkio throttle bandwidth", cgroup_enable_blkio_throttle_io);
- cgroup_enable_blkio_throttle_ops = config_get_boolean_ondemand("plugin:cgroups", "enable blkio throttle operations", cgroup_enable_blkio_throttle_ops);
- cgroup_enable_blkio_queued_ops = config_get_boolean_ondemand("plugin:cgroups", "enable blkio queued operations", cgroup_enable_blkio_queued_ops);
- cgroup_enable_blkio_merged_ops = config_get_boolean_ondemand("plugin:cgroups", "enable blkio merged operations", cgroup_enable_blkio_merged_ops);
-
- cgroup_recheck_zero_blkio_every_iterations = (int)config_get_number("plugin:cgroups", "recheck zero blkio every iterations", cgroup_recheck_zero_blkio_every_iterations);
- cgroup_recheck_zero_mem_failcnt_every_iterations = (int)config_get_number("plugin:cgroups", "recheck zero memory failcnt every iterations", cgroup_recheck_zero_mem_failcnt_every_iterations);
- cgroup_recheck_zero_mem_detailed_every_iterations = (int)config_get_number("plugin:cgroups", "recheck zero detailed memory every iterations", cgroup_recheck_zero_mem_detailed_every_iterations);
-
- cgroup_enable_systemd_services = config_get_boolean("plugin:cgroups", "enable systemd services", cgroup_enable_systemd_services);
- cgroup_enable_systemd_services_detailed_memory = config_get_boolean("plugin:cgroups", "enable systemd services detailed memory", cgroup_enable_systemd_services_detailed_memory);
- cgroup_used_memory_without_cache = config_get_boolean("plugin:cgroups", "report used memory without cache", cgroup_used_memory_without_cache);
-
- char filename[FILENAME_MAX + 1], *s;
- struct mountinfo *mi, *root = mountinfo_read(0);
-
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuacct");
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuacct");
- if(!mi) {
- error("CGROUP: cannot find cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct");
- s = "/sys/fs/cgroup/cpuacct";
- }
- else s = mi->mount_point;
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, s);
- cgroup_cpuacct_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/cpuacct", filename);
-
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "blkio");
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "blkio");
- if(!mi) {
- error("CGROUP: cannot find blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio");
- s = "/sys/fs/cgroup/blkio";
- }
- else s = mi->mount_point;
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, s);
- cgroup_blkio_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/blkio", filename);
-
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "memory");
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "memory");
- if(!mi) {
- error("CGROUP: cannot find memory mountinfo. Assuming default: /sys/fs/cgroup/memory");
- s = "/sys/fs/cgroup/memory";
- }
- else s = mi->mount_point;
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, s);
- cgroup_memory_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/memory", filename);
-
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "devices");
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "devices");
- if(!mi) {
- error("CGROUP: cannot find devices mountinfo. Assuming default: /sys/fs/cgroup/devices");
- s = "/sys/fs/cgroup/devices";
- }
- else s = mi->mount_point;
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, s);
- cgroup_devices_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/devices", filename);
-
- cgroup_root_max = (int)config_get_number("plugin:cgroups", "max cgroups to allow", cgroup_root_max);
- cgroup_max_depth = (int)config_get_number("plugin:cgroups", "max cgroups depth to monitor", cgroup_max_depth);
-
- cgroup_enable_new_cgroups_detected_at_runtime = config_get_boolean("plugin:cgroups", "enable new cgroups detected at run time", cgroup_enable_new_cgroups_detected_at_runtime);
-
- enabled_cgroup_patterns = simple_pattern_create(
- config_get("plugin:cgroups", "enable by default cgroups matching",
- // ----------------------------------------------------------------
-
- " !*/init.scope " // ignore init.scope
- " !/system.slice/run-*.scope " // ignore system.slice/run-XXXX.scope
- " *.scope " // we need all other *.scope for sure
-
- // ----------------------------------------------------------------
-
- " /machine.slice/*.service " // #3367 systemd-nspawn
-
- // ----------------------------------------------------------------
-
- " !*/vcpu* " // libvirtd adds these sub-cgroups
- " !*/emulator " // libvirtd adds these sub-cgroups
- " !*.mount "
- " !*.partition "
- " !*.service "
- " !*.socket "
- " !*.slice "
- " !*.swap "
- " !*.user "
- " !/ "
- " !/docker "
- " !/libvirt "
- " !/lxc "
- " !/lxc/*/* " // #1397 #2649
- " !/machine "
- " !/qemu "
- " !/system "
- " !/systemd "
- " !/user "
- " * " // enable anything else
- ), NULL, SIMPLE_PATTERN_EXACT);
-
- enabled_cgroup_paths = simple_pattern_create(
- config_get("plugin:cgroups", "search for cgroups in subpaths matching",
- " !*/init.scope " // ignore init.scope
- " !*-qemu " // #345
- " !*.libvirt-qemu " // #3010
- " !/init.scope "
- " !/system "
- " !/systemd "
- " !/user "
- " !/user.slice "
- " !/lxc/*/* " // #2161 #2649
- " * "
- ), NULL, SIMPLE_PATTERN_EXACT);
-
- snprintfz(filename, FILENAME_MAX, "%s/cgroup-name.sh", netdata_configured_plugins_dir);
- cgroups_rename_script = config_get("plugin:cgroups", "script to get cgroup names", filename);
-
- snprintfz(filename, FILENAME_MAX, "%s/cgroup-network", netdata_configured_plugins_dir);
- cgroups_network_interface_script = config_get("plugin:cgroups", "script to get cgroup network interfaces", filename);
-
- enabled_cgroup_renames = simple_pattern_create(
- config_get("plugin:cgroups", "run script to rename cgroups matching",
- " !/ "
- " !*.mount "
- " !*.socket "
- " !*.partition "
- " /machine.slice/*.service " // #3367 systemd-nspawn
- " !*.service "
- " !*.slice "
- " !*.swap "
- " !*.user "
- " !init.scope "
- " !*.scope/vcpu* " // libvirtd adds these sub-cgroups
- " !*.scope/emulator " // libvirtd adds these sub-cgroups
- " *.scope "
- " *docker* "
- " *lxc* "
- " *qemu* "
- " *kubepods* " // #3396 kubernetes
- " *.libvirt-qemu " // #3010
- " * "
- ), NULL, SIMPLE_PATTERN_EXACT);
-
- if(cgroup_enable_systemd_services) {
- systemd_services_cgroups = simple_pattern_create(
- config_get("plugin:cgroups", "cgroups to match as systemd services",
- " !/system.slice/*/*.service "
- " /system.slice/*.service "
- ), NULL, SIMPLE_PATTERN_EXACT);
- }
-
- mountinfo_free_all(root);
-}
-
-// ----------------------------------------------------------------------------
-// cgroup objects
-
-struct blkio {
- int updated;
- int enabled; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
- int delay_counter;
-
- char *filename;
-
- unsigned long long Read;
- unsigned long long Write;
-/*
- unsigned long long Sync;
- unsigned long long Async;
- unsigned long long Total;
-*/
-};
-
-// https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
-struct memory {
- ARL_BASE *arl_base;
- ARL_ENTRY *arl_dirty;
- ARL_ENTRY *arl_swap;
-
- int updated_detailed;
- int updated_usage_in_bytes;
- int updated_msw_usage_in_bytes;
- int updated_failcnt;
-
- int enabled_detailed; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
- int enabled_usage_in_bytes; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
- int enabled_msw_usage_in_bytes; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
- int enabled_failcnt; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
-
- int delay_counter_detailed;
- int delay_counter_failcnt;
-
- char *filename_detailed;
- char *filename_usage_in_bytes;
- char *filename_msw_usage_in_bytes;
- char *filename_failcnt;
-
- int detailed_has_dirty;
- int detailed_has_swap;
-
- // detailed metrics
- unsigned long long cache;
- unsigned long long rss;
- unsigned long long rss_huge;
- unsigned long long mapped_file;
- unsigned long long writeback;
- unsigned long long dirty;
- unsigned long long swap;
- unsigned long long pgpgin;
- unsigned long long pgpgout;
- unsigned long long pgfault;
- unsigned long long pgmajfault;
-/*
- unsigned long long inactive_anon;
- unsigned long long active_anon;
- unsigned long long inactive_file;
- unsigned long long active_file;
- unsigned long long unevictable;
- unsigned long long hierarchical_memory_limit;
- unsigned long long total_cache;
- unsigned long long total_rss;
- unsigned long long total_rss_huge;
- unsigned long long total_mapped_file;
- unsigned long long total_writeback;
- unsigned long long total_dirty;
- unsigned long long total_swap;
- unsigned long long total_pgpgin;
- unsigned long long total_pgpgout;
- unsigned long long total_pgfault;
- unsigned long long total_pgmajfault;
- unsigned long long total_inactive_anon;
- unsigned long long total_active_anon;
- unsigned long long total_inactive_file;
- unsigned long long total_active_file;
- unsigned long long total_unevictable;
-*/
-
- // single file metrics
- unsigned long long usage_in_bytes;
- unsigned long long msw_usage_in_bytes;
- unsigned long long failcnt;
-};
-
-// https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt
-struct cpuacct_stat {
- int updated;
- int enabled; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
-
- char *filename;
-
- unsigned long long user;
- unsigned long long system;
-};
-
-// https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt
-struct cpuacct_usage {
- int updated;
- int enabled; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO
-
- char *filename;
-
- unsigned int cpus;
- unsigned long long *cpu_percpu;
-};
-
-struct cgroup_network_interface {
- const char *host_device;
- const char *container_device;
- struct cgroup_network_interface *next;
-};
-
-#define CGROUP_OPTIONS_DISABLED_DUPLICATE 0x00000001
-#define CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE 0x00000002
-
-struct cgroup {
- uint32_t options;
-
- char available; // found in the filesystem
- char enabled; // enabled in the config
-
- char *id;
- uint32_t hash;
-
- char *chart_id;
- uint32_t hash_chart;
-
- char *chart_title;
-
- struct cpuacct_stat cpuacct_stat;
- struct cpuacct_usage cpuacct_usage;
-
- struct memory memory;
-
- struct blkio io_service_bytes; // bytes
- struct blkio io_serviced; // operations
-
- struct blkio throttle_io_service_bytes; // bytes
- struct blkio throttle_io_serviced; // operations
-
- struct blkio io_merged; // operations
- struct blkio io_queued; // operations
-
- struct cgroup_network_interface *interfaces;
-
- // per cgroup charts
- RRDSET *st_cpu;
- RRDSET *st_cpu_per_core;
- RRDSET *st_mem;
- RRDSET *st_writeback;
- RRDSET *st_mem_activity;
- RRDSET *st_pgfaults;
- RRDSET *st_mem_usage;
- RRDSET *st_mem_failcnt;
- RRDSET *st_io;
- RRDSET *st_serviced_ops;
- RRDSET *st_throttle_io;
- RRDSET *st_throttle_serviced_ops;
- RRDSET *st_queued_ops;
- RRDSET *st_merged_ops;
-
- // services
- RRDDIM *rd_cpu;
- RRDDIM *rd_mem_usage;
- RRDDIM *rd_mem_failcnt;
- RRDDIM *rd_swap_usage;
-
- RRDDIM *rd_mem_detailed_cache;
- RRDDIM *rd_mem_detailed_rss;
- RRDDIM *rd_mem_detailed_mapped;
- RRDDIM *rd_mem_detailed_writeback;
- RRDDIM *rd_mem_detailed_pgpgin;
- RRDDIM *rd_mem_detailed_pgpgout;
- RRDDIM *rd_mem_detailed_pgfault;
- RRDDIM *rd_mem_detailed_pgmajfault;
-
- RRDDIM *rd_io_service_bytes_read;
- RRDDIM *rd_io_serviced_read;
- RRDDIM *rd_throttle_io_read;
- RRDDIM *rd_throttle_io_serviced_read;
- RRDDIM *rd_io_queued_read;
- RRDDIM *rd_io_merged_read;
-
- RRDDIM *rd_io_service_bytes_write;
- RRDDIM *rd_io_serviced_write;
- RRDDIM *rd_throttle_io_write;
- RRDDIM *rd_throttle_io_serviced_write;
- RRDDIM *rd_io_queued_write;
- RRDDIM *rd_io_merged_write;
-
- struct cgroup *next;
-
-} *cgroup_root = NULL;
-
-// ----------------------------------------------------------------------------
-// read values from /sys
-
-static inline void cgroup_read_cpuacct_stat(struct cpuacct_stat *cp) {
- static procfile *ff = NULL;
-
- if(likely(cp->filename)) {
- ff = procfile_reopen(ff, cp->filename, NULL, PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- cp->updated = 0;
- cgroups_check = 1;
- return;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) {
- cp->updated = 0;
- cgroups_check = 1;
- return;
- }
-
- unsigned long i, lines = procfile_lines(ff);
-
- if(unlikely(lines < 1)) {
- error("CGROUP: file '%s' should have 1+ lines.", cp->filename);
- cp->updated = 0;
- return;
- }
-
- for(i = 0; i < lines ; i++) {
- char *s = procfile_lineword(ff, i, 0);
- uint32_t hash = simple_hash(s);
-
- if(unlikely(hash == user_hash && !strcmp(s, "user")))
- cp->user = str2ull(procfile_lineword(ff, i, 1));
-
- else if(unlikely(hash == system_hash && !strcmp(s, "system")))
- cp->system = str2ull(procfile_lineword(ff, i, 1));
- }
-
- cp->updated = 1;
-
- if(unlikely(cp->enabled == CONFIG_BOOLEAN_AUTO && (cp->user || cp->system)))
- cp->enabled = CONFIG_BOOLEAN_YES;
- }
-}
-
-static inline void cgroup_read_cpuacct_usage(struct cpuacct_usage *ca) {
- static procfile *ff = NULL;
-
- if(likely(ca->filename)) {
- ff = procfile_reopen(ff, ca->filename, NULL, PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- ca->updated = 0;
- cgroups_check = 1;
- return;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) {
- ca->updated = 0;
- cgroups_check = 1;
- return;
- }
-
- if(unlikely(procfile_lines(ff) < 1)) {
- error("CGROUP: file '%s' should have 1+ lines but has %zu.", ca->filename, procfile_lines(ff));
- ca->updated = 0;
- return;
- }
-
- unsigned long i = procfile_linewords(ff, 0);
- if(unlikely(i == 0)) {
- ca->updated = 0;
- return;
- }
-
- // we may have 1 more CPU reported
- while(i > 0) {
- char *s = procfile_lineword(ff, 0, i - 1);
- if(!*s) i--;
- else break;
- }
-
- if(unlikely(i != ca->cpus)) {
- freez(ca->cpu_percpu);
- ca->cpu_percpu = mallocz(sizeof(unsigned long long) * i);
- ca->cpus = (unsigned int)i;
- }
-
- unsigned long long total = 0;
- for(i = 0; i < ca->cpus ;i++) {
- unsigned long long n = str2ull(procfile_lineword(ff, 0, i));
- ca->cpu_percpu[i] = n;
- total += n;
- }
-
- ca->updated = 1;
-
- if(unlikely(ca->enabled == CONFIG_BOOLEAN_AUTO && total))
- ca->enabled = CONFIG_BOOLEAN_YES;
- }
-}
-
-static inline void cgroup_read_blkio(struct blkio *io) {
- if(unlikely(io->enabled == CONFIG_BOOLEAN_AUTO && io->delay_counter > 0)) {
- io->delay_counter--;
- return;
- }
-
- if(likely(io->filename)) {
- static procfile *ff = NULL;
-
- ff = procfile_reopen(ff, io->filename, NULL, PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- io->updated = 0;
- cgroups_check = 1;
- return;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) {
- io->updated = 0;
- cgroups_check = 1;
- return;
- }
-
- unsigned long i, lines = procfile_lines(ff);
-
- if(unlikely(lines < 1)) {
- error("CGROUP: file '%s' should have 1+ lines.", io->filename);
- io->updated = 0;
- return;
- }
-
- io->Read = 0;
- io->Write = 0;
-/*
- io->Sync = 0;
- io->Async = 0;
- io->Total = 0;
-*/
-
- for(i = 0; i < lines ; i++) {
- char *s = procfile_lineword(ff, i, 1);
- uint32_t hash = simple_hash(s);
-
- if(unlikely(hash == Read_hash && !strcmp(s, "Read")))
- io->Read += str2ull(procfile_lineword(ff, i, 2));
-
- else if(unlikely(hash == Write_hash && !strcmp(s, "Write")))
- io->Write += str2ull(procfile_lineword(ff, i, 2));
-
-/*
- else if(unlikely(hash == Sync_hash && !strcmp(s, "Sync")))
- io->Sync += str2ull(procfile_lineword(ff, i, 2));
-
- else if(unlikely(hash == Async_hash && !strcmp(s, "Async")))
- io->Async += str2ull(procfile_lineword(ff, i, 2));
-
- else if(unlikely(hash == Total_hash && !strcmp(s, "Total")))
- io->Total += str2ull(procfile_lineword(ff, i, 2));
-*/
- }
-
- io->updated = 1;
-
- if(unlikely(io->enabled == CONFIG_BOOLEAN_AUTO)) {
- if(unlikely(io->Read || io->Write))
- io->enabled = CONFIG_BOOLEAN_YES;
- else
- io->delay_counter = cgroup_recheck_zero_blkio_every_iterations;
- }
- }
-}
-
-static inline void cgroup_read_memory(struct memory *mem) {
- static procfile *ff = NULL;
-
- // read detailed ram usage
- if(likely(mem->filename_detailed)) {
- if(unlikely(mem->enabled_detailed == CONFIG_BOOLEAN_AUTO && mem->delay_counter_detailed > 0)) {
- mem->delay_counter_detailed--;
- goto memory_next;
- }
-
- ff = procfile_reopen(ff, mem->filename_detailed, NULL, PROCFILE_FLAG_DEFAULT);
- if(unlikely(!ff)) {
- mem->updated_detailed = 0;
- cgroups_check = 1;
- goto memory_next;
- }
-
- ff = procfile_readall(ff);
- if(unlikely(!ff)) {
- mem->updated_detailed = 0;
- cgroups_check = 1;
- goto memory_next;
- }
-
- unsigned long i, lines = procfile_lines(ff);
-
- if(unlikely(lines < 1)) {
- error("CGROUP: file '%s' should have 1+ lines.", mem->filename_detailed);
- mem->updated_detailed = 0;
- goto memory_next;
- }
-
- if(unlikely(!mem->arl_base)) {
- mem->arl_base = arl_create("cgroup/memory", NULL, 60);
-
- arl_expect(mem->arl_base, "cache", &mem->cache);
- arl_expect(mem->arl_base, "rss", &mem->rss);
- arl_expect(mem->arl_base, "rss_huge", &mem->rss_huge);
- arl_expect(mem->arl_base, "mapped_file", &mem->mapped_file);
- arl_expect(mem->arl_base, "writeback", &mem->writeback);
- mem->arl_dirty = arl_expect(mem->arl_base, "dirty", &mem->dirty);
- mem->arl_swap = arl_expect(mem->arl_base, "swap", &mem->swap);
- arl_expect(mem->arl_base, "pgpgin", &mem->pgpgin);
- arl_expect(mem->arl_base, "pgpgout", &mem->pgpgout);
- arl_expect(mem->arl_base, "pgfault", &mem->pgfault);
- arl_expect(mem->arl_base, "pgmajfault", &mem->pgmajfault);
- }
-
- arl_begin(mem->arl_base);
-
- for(i = 0; i < lines ; i++) {
- if(arl_check(mem->arl_base,
- procfile_lineword(ff, i, 0),
- procfile_lineword(ff, i, 1))) break;
- }
-
- if(unlikely(mem->arl_dirty->flags & ARL_ENTRY_FLAG_FOUND))
- mem->detailed_has_dirty = 1;
-
- if(unlikely(mem->arl_swap->flags & ARL_ENTRY_FLAG_FOUND))
- mem->detailed_has_swap = 1;
-
- // fprintf(stderr, "READ: '%s', cache: %llu, rss: %llu, rss_huge: %llu, mapped_file: %llu, writeback: %llu, dirty: %llu, swap: %llu, pgpgin: %llu, pgpgout: %llu, pgfault: %llu, pgmajfault: %llu, inactive_anon: %llu, active_anon: %llu, inactive_file: %llu, active_file: %llu, unevictable: %llu, hierarchical_memory_limit: %llu, total_cache: %llu, total_rss: %llu, total_rss_huge: %llu, total_mapped_file: %llu, total_writeback: %llu, total_dirty: %llu, total_swap: %llu, total_pgpgin: %llu, total_pgpgout: %llu, total_pgfault: %llu, total_pgmajfault: %llu, total_inactive_anon: %llu, total_active_anon: %llu, total_inactive_file: %llu, total_active_file: %llu, total_unevictable: %llu\n", mem->filename, mem->cache, mem->rss, mem->rss_huge, mem->mapped_file, mem->writeback, mem->dirty, mem->swap, mem->pgpgin, mem->pgpgout, mem->pgfault, mem->pgmajfault, mem->inactive_anon, mem->active_anon, mem->inactive_file, mem->active_file, mem->unevictable, mem->hierarchical_memory_limit, mem->total_cache, mem->total_rss, mem->total_rss_huge, mem->total_mapped_file, mem->total_writeback, mem->total_dirty, mem->total_swap, mem->total_pgpgin, mem->total_pgpgout, mem->total_pgfault, mem->total_pgmajfault, mem->total_inactive_anon, mem->total_active_anon, mem->total_inactive_file, mem->total_active_file, mem->total_unevictable);
-
- mem->updated_detailed = 1;
-
- if(unlikely(mem->enabled_detailed == CONFIG_BOOLEAN_AUTO)) {
- if(mem->cache || mem->dirty || mem->rss || mem->rss_huge || mem->mapped_file || mem->writeback || mem->swap || mem->pgpgin || mem->pgpgout || mem->pgfault || mem->pgmajfault)
- mem->enabled_detailed = CONFIG_BOOLEAN_YES;
- else
- mem->delay_counter_detailed = cgroup_recheck_zero_mem_detailed_every_iterations;
- }
- }
-
-memory_next:
-
- // read usage_in_bytes
- if(likely(mem->filename_usage_in_bytes)) {
- mem->updated_usage_in_bytes = !read_single_number_file(mem->filename_usage_in_bytes, &mem->usage_in_bytes);
- if(unlikely(mem->updated_usage_in_bytes && mem->enabled_usage_in_bytes == CONFIG_BOOLEAN_AUTO && mem->usage_in_bytes))
- mem->enabled_usage_in_bytes = CONFIG_BOOLEAN_YES;
- }
-
- // read msw_usage_in_bytes
- if(likely(mem->filename_msw_usage_in_bytes)) {
- mem->updated_msw_usage_in_bytes = !read_single_number_file(mem->filename_msw_usage_in_bytes, &mem->msw_usage_in_bytes);
- if(unlikely(mem->updated_msw_usage_in_bytes && mem->enabled_msw_usage_in_bytes == CONFIG_BOOLEAN_AUTO && mem->msw_usage_in_bytes))
- mem->enabled_msw_usage_in_bytes = CONFIG_BOOLEAN_YES;
- }
-
- // read failcnt
- if(likely(mem->filename_failcnt)) {
- if(unlikely(mem->enabled_failcnt == CONFIG_BOOLEAN_AUTO && mem->delay_counter_failcnt > 0)) {
- mem->updated_failcnt = 0;
- mem->delay_counter_failcnt--;
- }
- else {
- mem->updated_failcnt = !read_single_number_file(mem->filename_failcnt, &mem->failcnt);
- if(unlikely(mem->updated_failcnt && mem->enabled_failcnt == CONFIG_BOOLEAN_AUTO)) {
- if(unlikely(!mem->failcnt))
- mem->delay_counter_failcnt = cgroup_recheck_zero_mem_failcnt_every_iterations;
- else
- mem->enabled_failcnt = CONFIG_BOOLEAN_YES;
- }
- }
- }
-}
-
-static inline void cgroup_read(struct cgroup *cg) {
- debug(D_CGROUP, "reading metrics for cgroups '%s'", cg->id);
-
- cgroup_read_cpuacct_stat(&cg->cpuacct_stat);
- cgroup_read_cpuacct_usage(&cg->cpuacct_usage);
- cgroup_read_memory(&cg->memory);
- cgroup_read_blkio(&cg->io_service_bytes);
- cgroup_read_blkio(&cg->io_serviced);
- cgroup_read_blkio(&cg->throttle_io_service_bytes);
- cgroup_read_blkio(&cg->throttle_io_serviced);
- cgroup_read_blkio(&cg->io_merged);
- cgroup_read_blkio(&cg->io_queued);
-}
-
-static inline void read_all_cgroups(struct cgroup *root) {
- debug(D_CGROUP, "reading metrics for all cgroups");
-
- struct cgroup *cg;
-
- for(cg = root; cg ; cg = cg->next)
- if(cg->enabled && cg->available)
- cgroup_read(cg);
-}
-
-// ----------------------------------------------------------------------------
-// cgroup network interfaces
-
-#define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048
-static inline void read_cgroup_network_interfaces(struct cgroup *cg) {
- debug(D_CGROUP, "looking for the network interfaces of cgroup '%s' with chart id '%s' and title '%s'", cg->id, cg->chart_id, cg->chart_title);
-
- pid_t cgroup_pid;
- char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
-
- snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s --cgroup '%s%s'", cgroups_network_interface_script, cgroup_cpuacct_base, cg->id);
-
- debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
- FILE *fp = mypopen(buffer, &cgroup_pid);
- if(fp) {
- char *s;
- while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) {
- trim(s);
-
- if(*s && *s != '\n') {
- char *t = s;
- while(*t && *t != ' ') t++;
- if(*t == ' ') {
- *t = '\0';
- t++;
- }
-
- if(!*s) {
- error("CGROUP: empty host interface returned by script");
- continue;
- }
-
- if(!*t) {
- error("CGROUP: empty guest interface returned by script");
- continue;
- }
-
- struct cgroup_network_interface *i = callocz(1, sizeof(struct cgroup_network_interface));
- i->host_device = strdupz(s);
- i->container_device = strdupz(t);
- i->next = cg->interfaces;
- cg->interfaces = i;
-
- info("CGROUP: cgroup '%s' has network interface '%s' as '%s'", cg->id, i->host_device, i->container_device);
-
- // register a device rename to proc_net_dev.c
- netdev_rename_device_add(i->host_device, i->container_device, cg->chart_id);
- }
- }
-
- mypclose(fp, cgroup_pid);
- // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
- }
- else
- error("CGROUP: cannot popen(\"%s\", \"r\").", buffer);
-}
-
-static inline void free_cgroup_network_interfaces(struct cgroup *cg) {
- while(cg->interfaces) {
- struct cgroup_network_interface *i = cg->interfaces;
- cg->interfaces = i->next;
-
- // delete the registration of proc_net_dev rename
- netdev_rename_device_del(i->host_device);
-
- freez((void *)i->host_device);
- freez((void *)i->container_device);
- freez((void *)i);
- }
-}
-
-// ----------------------------------------------------------------------------
-// add/remove/find cgroup objects
-
-#define CGROUP_CHARTID_LINE_MAX 1024
-
-static inline char *cgroup_title_strdupz(const char *s) {
- if(!s || !*s) s = "/";
-
- if(*s == '/' && s[1] != '\0') s++;
-
- char *r = strdupz(s);
- netdata_fix_chart_name(r);
-
- return r;
-}
-
-static inline char *cgroup_chart_id_strdupz(const char *s) {
- if(!s || !*s) s = "/";
-
- if(*s == '/' && s[1] != '\0') s++;
-
- char *r = strdupz(s);
- netdata_fix_chart_id(r);
-
- return r;
-}
-
-static inline void cgroup_get_chart_name(struct cgroup *cg) {
- debug(D_CGROUP, "looking for the name of cgroup '%s' with chart id '%s' and title '%s'", cg->id, cg->chart_id, cg->chart_title);
-
- pid_t cgroup_pid;
- char buffer[CGROUP_CHARTID_LINE_MAX + 1];
-
- snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s' '%s'", cgroups_rename_script, cg->chart_id, cg->id);
-
- debug(D_CGROUP, "executing command \"%s\" for cgroup '%s'", buffer, cg->id);
- FILE *fp = mypopen(buffer, &cgroup_pid);
- if(fp) {
- // debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
- char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
- // debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
- mypclose(fp, cgroup_pid);
- // debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
-
- if(s && *s && *s != '\n') {
- debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
-
- trim(s);
-
- freez(cg->chart_title);
- cg->chart_title = cgroup_title_strdupz(s);
-
- freez(cg->chart_id);
- cg->chart_id = cgroup_chart_id_strdupz(s);
- cg->hash_chart = simple_hash(cg->chart_id);
- }
- }
- else
- error("CGROUP: cannot popen(\"%s\", \"r\").", buffer);
-}
-
-static inline struct cgroup *cgroup_add(const char *id) {
- if(!id || !*id) id = "/";
- debug(D_CGROUP, "adding to list, cgroup with id '%s'", id);
-
- if(cgroup_root_count >= cgroup_root_max) {
- info("CGROUP: maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, id);
- return NULL;
- }
-
- int def = simple_pattern_matches(enabled_cgroup_patterns, id)?cgroup_enable_new_cgroups_detected_at_runtime:0;
- struct cgroup *cg = callocz(1, sizeof(struct cgroup));
-
- cg->id = strdupz(id);
- cg->hash = simple_hash(cg->id);
-
- cg->chart_title = cgroup_title_strdupz(id);
-
- cg->chart_id = cgroup_chart_id_strdupz(id);
- cg->hash_chart = simple_hash(cg->chart_id);
-
- if(!cgroup_root)
- cgroup_root = cg;
- else {
- // append it
- struct cgroup *e;
- for(e = cgroup_root; e->next ;e = e->next) ;
- e->next = cg;
- }
-
- cgroup_root_count++;
-
- // fix the chart_id and title by calling the external script
- if(simple_pattern_matches(enabled_cgroup_renames, cg->id)) {
-
- cgroup_get_chart_name(cg);
-
- debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
- }
- else
- debug(D_CGROUP, "cgroup '%s' will not be renamed - it matches the list of disabled cgroup renames (will be shown as '%s')", cg->id, cg->chart_id);
-
- int user_configurable = 1;
-
- // check if this cgroup should be a systemd service
- if(cgroup_enable_systemd_services) {
- if(simple_pattern_matches(systemd_services_cgroups, cg->id) ||
- simple_pattern_matches(systemd_services_cgroups, cg->chart_id)) {
- debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
-
- char buffer[CGROUP_CHARTID_LINE_MAX + 1];
- cg->options |= CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
-
- strncpy(buffer, cg->id, CGROUP_CHARTID_LINE_MAX);
- char *s = buffer;
-
- //freez(cg->chart_id);
- //cg->chart_id = cgroup_chart_id_strdupz(s);
- //cg->hash_chart = simple_hash(cg->chart_id);
-
- // skip to the last slash
- size_t len = strlen(s);
- while(len--) if(unlikely(s[len] == '/')) break;
- if(len) s = &s[len + 1];
-
- // remove extension
- len = strlen(s);
- while(len--) if(unlikely(s[len] == '.')) break;
- if(len) s[len] = '\0';
-
- freez(cg->chart_title);
- cg->chart_title = cgroup_title_strdupz(s);
-
- cg->enabled = 1;
- user_configurable = 0;
-
- debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
- }
- else
- debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') does not match systemd services groups", cg->id, cg->chart_id, cg->chart_title);
- }
-
- if(user_configurable) {
- // allow the user to enable/disable this individualy
- char option[FILENAME_MAX + 1];
- snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title);
- cg->enabled = (char) config_get_boolean("plugin:cgroups", option, def);
- }
-
- // detect duplicate cgroups
- if(cg->enabled) {
- struct cgroup *t;
- for (t = cgroup_root; t; t = t->next) {
- if (t != cg && t->enabled && t->hash_chart == cg->hash_chart && !strcmp(t->chart_id, cg->chart_id)) {
- if (!strncmp(t->chart_id, "/system.slice/", 14) && !strncmp(cg->chart_id, "/init.scope/system.slice/", 25)) {
- error("CGROUP: chart id '%s' already exists with id '%s' and is enabled. Swapping them by enabling cgroup with id '%s' and disabling cgroup with id '%s'.",
- cg->chart_id, t->id, cg->id, t->id);
- debug(D_CGROUP, "Control group with chart id '%s' already exists with id '%s' and is enabled. Swapping them by enabling cgroup with id '%s' and disabling cgroup with id '%s'.",
- cg->chart_id, t->id, cg->id, t->id);
- t->enabled = 0;
- t->options |= CGROUP_OPTIONS_DISABLED_DUPLICATE;
- }
- else {
- error("CGROUP: chart id '%s' already exists with id '%s' and is enabled and available. Disabling cgroup with id '%s'.",
- cg->chart_id, t->id, cg->id);
- debug(D_CGROUP, "Control group with chart id '%s' already exists with id '%s' and is enabled and available. Disabling cgroup with id '%s'.",
- cg->chart_id, t->id, cg->id);
- cg->enabled = 0;
- cg->options |= CGROUP_OPTIONS_DISABLED_DUPLICATE;
- }
-
- break;
- }
- }
- }
-
- if(cg->enabled && !(cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE))
- read_cgroup_network_interfaces(cg);
-
- debug(D_CGROUP, "ADDED CGROUP: '%s' with chart id '%s' and title '%s' as %s (default was %s)", cg->id, cg->chart_id, cg->chart_title, (cg->enabled)?"enabled":"disabled", (def)?"enabled":"disabled");
-
- return cg;
-}
-
-static inline void cgroup_free(struct cgroup *cg) {
- debug(D_CGROUP, "Removing cgroup '%s' with chart id '%s' (was %s and %s)", cg->id, cg->chart_id, (cg->enabled)?"enabled":"disabled", (cg->available)?"available":"not available");
-
- if(cg->st_cpu) rrdset_is_obsolete(cg->st_cpu);
- if(cg->st_cpu_per_core) rrdset_is_obsolete(cg->st_cpu_per_core);
- if(cg->st_mem) rrdset_is_obsolete(cg->st_mem);
- if(cg->st_writeback) rrdset_is_obsolete(cg->st_writeback);
- if(cg->st_mem_activity) rrdset_is_obsolete(cg->st_mem_activity);
- if(cg->st_pgfaults) rrdset_is_obsolete(cg->st_pgfaults);
- if(cg->st_mem_usage) rrdset_is_obsolete(cg->st_mem_usage);
- if(cg->st_mem_failcnt) rrdset_is_obsolete(cg->st_mem_failcnt);
- if(cg->st_io) rrdset_is_obsolete(cg->st_io);
- if(cg->st_serviced_ops) rrdset_is_obsolete(cg->st_serviced_ops);
- if(cg->st_throttle_io) rrdset_is_obsolete(cg->st_throttle_io);
- if(cg->st_throttle_serviced_ops) rrdset_is_obsolete(cg->st_throttle_serviced_ops);
- if(cg->st_queued_ops) rrdset_is_obsolete(cg->st_queued_ops);
- if(cg->st_merged_ops) rrdset_is_obsolete(cg->st_merged_ops);
-
- free_cgroup_network_interfaces(cg);
-
- freez(cg->cpuacct_usage.cpu_percpu);
-
- freez(cg->cpuacct_stat.filename);
- freez(cg->cpuacct_usage.filename);
-
- arl_free(cg->memory.arl_base);
- freez(cg->memory.filename_detailed);
- freez(cg->memory.filename_failcnt);
- freez(cg->memory.filename_usage_in_bytes);
- freez(cg->memory.filename_msw_usage_in_bytes);
-
- freez(cg->io_service_bytes.filename);
- freez(cg->io_serviced.filename);
-
- freez(cg->throttle_io_service_bytes.filename);
- freez(cg->throttle_io_serviced.filename);
-
- freez(cg->io_merged.filename);
- freez(cg->io_queued.filename);
-
- freez(cg->id);
- freez(cg->chart_id);
- freez(cg->chart_title);
-
- freez(cg);
-
- cgroup_root_count--;
-}
-
-// find if a given cgroup exists
-static inline struct cgroup *cgroup_find(const char *id) {
- debug(D_CGROUP, "searching for cgroup '%s'", id);
-
- uint32_t hash = simple_hash(id);
-
- struct cgroup *cg;
- for(cg = cgroup_root; cg ; cg = cg->next) {
- if(hash == cg->hash && strcmp(id, cg->id) == 0)
- break;
- }
-
- debug(D_CGROUP, "cgroup '%s' %s in memory", id, (cg)?"found":"not found");
- return cg;
-}
-
-// ----------------------------------------------------------------------------
-// detect running cgroups
-
-// callback for find_file_in_subdirs()
-static inline void found_subdir_in_dir(const char *dir) {
- debug(D_CGROUP, "examining cgroup dir '%s'", dir);
-
- struct cgroup *cg = cgroup_find(dir);
- if(!cg) {
- if(*dir && cgroup_max_depth > 0) {
- int depth = 0;
- const char *s;
-
- for(s = dir; *s ;s++)
- if(unlikely(*s == '/'))
- depth++;
-
- if(depth > cgroup_max_depth) {
- info("CGROUP: '%s' is too deep (%d, while max is %d)", dir, depth, cgroup_max_depth);
- return;
- }
- }
- // debug(D_CGROUP, "will add dir '%s' as cgroup", dir);
- cg = cgroup_add(dir);
- }
-
- if(cg) cg->available = 1;
-}
-
-static inline int find_dir_in_subdirs(const char *base, const char *this, void (*callback)(const char *)) {
- if(!this) this = base;
- debug(D_CGROUP, "searching for directories in '%s' (base '%s')", this?this:"", base);
-
- size_t dirlen = strlen(this), baselen = strlen(base);
-
- int ret = -1;
- int enabled = -1;
-
- const char *relative_path = &this[baselen];
- if(!*relative_path) relative_path = "/";
-
- DIR *dir = opendir(this);
- if(!dir) {
- error("CGROUP: cannot read directory '%s'", base);
- return ret;
- }
- ret = 1;
-
- callback(relative_path);
-
- struct dirent *de = NULL;
- while((de = readdir(dir))) {
- if(de->d_type == DT_DIR
- && (
- (de->d_name[0] == '.' && de->d_name[1] == '\0')
- || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
- ))
- continue;
-
- if(de->d_type == DT_DIR) {
- if(enabled == -1) {
- const char *r = relative_path;
- if(*r == '\0') r = "/";
-
- // do not decent in directories we are not interested
- int def = simple_pattern_matches(enabled_cgroup_paths, r);
-
- // we check for this option here
- // so that the config will not have settings
- // for leaf directories
- char option[FILENAME_MAX + 1];
- snprintfz(option, FILENAME_MAX, "search for cgroups under %s", r);
- option[FILENAME_MAX] = '\0';
- enabled = config_get_boolean("plugin:cgroups", option, def);
- }
-
- if(enabled) {
- char *s = mallocz(dirlen + strlen(de->d_name) + 2);
- strcpy(s, this);
- strcat(s, "/");
- strcat(s, de->d_name);
- int ret2 = find_dir_in_subdirs(base, s, callback);
- if(ret2 > 0) ret += ret2;
- freez(s);
- }
- }
- }
-
- closedir(dir);
- return ret;
-}
-
-static inline void mark_all_cgroups_as_not_available() {
- debug(D_CGROUP, "marking all cgroups as not available");
-
- struct cgroup *cg;
-
- // mark all as not available
- for(cg = cgroup_root; cg ; cg = cg->next) {
- cg->available = 0;
- }
-}
-
-static inline void cleanup_all_cgroups() {
- struct cgroup *cg = cgroup_root, *last = NULL;
-
- for(; cg ;) {
- if(!cg->available) {
- // enable the first duplicate cgroup
- {
- struct cgroup *t;
- for(t = cgroup_root; t ; t = t->next) {
- if(t != cg && t->available && !t->enabled && t->options & CGROUP_OPTIONS_DISABLED_DUPLICATE && t->hash_chart == cg->hash_chart && !strcmp(t->chart_id, cg->chart_id)) {
- debug(D_CGROUP, "Enabling duplicate of cgroup '%s' with id '%s', because the original with id '%s' stopped.", t->chart_id, t->id, cg->id);
- t->enabled = 1;
- t->options &= ~CGROUP_OPTIONS_DISABLED_DUPLICATE;
- break;
- }
- }
- }
-
- if(!last)
- cgroup_root = cg->next;
- else
- last->next = cg->next;
-
- cgroup_free(cg);
-
- if(!last)
- cg = cgroup_root;
- else
- cg = last->next;
- }
- else {
- last = cg;
- cg = cg->next;
- }
- }
-}
-
-static inline void find_all_cgroups() {
- debug(D_CGROUP, "searching for cgroups");
-
- mark_all_cgroups_as_not_available();
-
- if(cgroup_enable_cpuacct_stat || cgroup_enable_cpuacct_usage) {
- if(find_dir_in_subdirs(cgroup_cpuacct_base, NULL, found_subdir_in_dir) == -1) {
- cgroup_enable_cpuacct_stat =
- cgroup_enable_cpuacct_usage = CONFIG_BOOLEAN_NO;
- error("CGROUP: disabled cpu statistics.");
- }
- }
-
- if(cgroup_enable_blkio_io || cgroup_enable_blkio_ops || cgroup_enable_blkio_throttle_io || cgroup_enable_blkio_throttle_ops || cgroup_enable_blkio_merged_ops || cgroup_enable_blkio_queued_ops) {
- if(find_dir_in_subdirs(cgroup_blkio_base, NULL, found_subdir_in_dir) == -1) {
- cgroup_enable_blkio_io =
- cgroup_enable_blkio_ops =
- cgroup_enable_blkio_throttle_io =
- cgroup_enable_blkio_throttle_ops =
- cgroup_enable_blkio_merged_ops =
- cgroup_enable_blkio_queued_ops = CONFIG_BOOLEAN_NO;
- error("CGROUP: disabled blkio statistics.");
- }
- }
-
- if(cgroup_enable_memory || cgroup_enable_detailed_memory || cgroup_enable_swap || cgroup_enable_memory_failcnt) {
- if(find_dir_in_subdirs(cgroup_memory_base, NULL, found_subdir_in_dir) == -1) {
- cgroup_enable_memory =
- cgroup_enable_detailed_memory =
- cgroup_enable_swap =
- cgroup_enable_memory_failcnt = CONFIG_BOOLEAN_NO;
- error("CGROUP: disabled memory statistics.");
- }
- }
-
- if(cgroup_search_in_devices) {
- if(find_dir_in_subdirs(cgroup_devices_base, NULL, found_subdir_in_dir) == -1) {
- cgroup_search_in_devices = 0;
- error("CGROUP: disabled devices statistics.");
- }
- }
-
- // remove any non-existing cgroups
- cleanup_all_cgroups();
-
- struct cgroup *cg;
- struct stat buf;
- for(cg = cgroup_root; cg ; cg = cg->next) {
- // fprintf(stderr, " >>> CGROUP '%s' (%u - %s) with name '%s'\n", cg->id, cg->hash, cg->available?"available":"stopped", cg->name);
-
- if(unlikely(!cg->available))
- continue;
-
- debug(D_CGROUP, "checking paths for cgroup '%s'", cg->id);
-
- // check for newly added cgroups
- // and update the filenames they read
- char filename[FILENAME_MAX + 1];
- if(unlikely(cgroup_enable_cpuacct_stat && !cg->cpuacct_stat.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/cpuacct.stat", cgroup_cpuacct_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->cpuacct_stat.filename = strdupz(filename);
- cg->cpuacct_stat.enabled = cgroup_enable_cpuacct_stat;
- debug(D_CGROUP, "cpuacct.stat filename for cgroup '%s': '%s'", cg->id, cg->cpuacct_stat.filename);
- }
- else
- debug(D_CGROUP, "cpuacct.stat file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_cpuacct_usage && !cg->cpuacct_usage.filename && !(cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE))) {
- snprintfz(filename, FILENAME_MAX, "%s%s/cpuacct.usage_percpu", cgroup_cpuacct_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->cpuacct_usage.filename = strdupz(filename);
- cg->cpuacct_usage.enabled = cgroup_enable_cpuacct_usage;
- debug(D_CGROUP, "cpuacct.usage_percpu filename for cgroup '%s': '%s'", cg->id, cg->cpuacct_usage.filename);
- }
- else
- debug(D_CGROUP, "cpuacct.usage_percpu file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely((cgroup_enable_detailed_memory || cgroup_used_memory_without_cache) && !cg->memory.filename_detailed && (cgroup_used_memory_without_cache || cgroup_enable_systemd_services_detailed_memory || !(cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)))) {
- snprintfz(filename, FILENAME_MAX, "%s%s/memory.stat", cgroup_memory_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->memory.filename_detailed = strdupz(filename);
- cg->memory.enabled_detailed = (cgroup_enable_detailed_memory == CONFIG_BOOLEAN_YES)?CONFIG_BOOLEAN_YES:CONFIG_BOOLEAN_AUTO;
- debug(D_CGROUP, "memory.stat filename for cgroup '%s': '%s'", cg->id, cg->memory.filename_detailed);
- }
- else
- debug(D_CGROUP, "memory.stat file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_memory && !cg->memory.filename_usage_in_bytes)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/memory.usage_in_bytes", cgroup_memory_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->memory.filename_usage_in_bytes = strdupz(filename);
- cg->memory.enabled_usage_in_bytes = cgroup_enable_memory;
- debug(D_CGROUP, "memory.usage_in_bytes filename for cgroup '%s': '%s'", cg->id, cg->memory.filename_usage_in_bytes);
- }
- else
- debug(D_CGROUP, "memory.usage_in_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_swap && !cg->memory.filename_msw_usage_in_bytes)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/memory.msw_usage_in_bytes", cgroup_memory_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->memory.filename_msw_usage_in_bytes = strdupz(filename);
- cg->memory.enabled_msw_usage_in_bytes = cgroup_enable_swap;
- debug(D_CGROUP, "memory.msw_usage_in_bytes filename for cgroup '%s': '%s'", cg->id, cg->memory.filename_msw_usage_in_bytes);
- }
- else
- debug(D_CGROUP, "memory.msw_usage_in_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_memory_failcnt && !cg->memory.filename_failcnt)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/memory.failcnt", cgroup_memory_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->memory.filename_failcnt = strdupz(filename);
- cg->memory.enabled_failcnt = cgroup_enable_memory_failcnt;
- debug(D_CGROUP, "memory.failcnt filename for cgroup '%s': '%s'", cg->id, cg->memory.filename_failcnt);
- }
- else
- debug(D_CGROUP, "memory.failcnt file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_blkio_io && !cg->io_service_bytes.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_service_bytes", cgroup_blkio_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->io_service_bytes.filename = strdupz(filename);
- cg->io_service_bytes.enabled = cgroup_enable_blkio_io;
- debug(D_CGROUP, "io_service_bytes filename for cgroup '%s': '%s'", cg->id, cg->io_service_bytes.filename);
- }
- else
- debug(D_CGROUP, "io_service_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_blkio_ops && !cg->io_serviced.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_serviced", cgroup_blkio_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->io_serviced.filename = strdupz(filename);
- cg->io_serviced.enabled = cgroup_enable_blkio_ops;
- debug(D_CGROUP, "io_serviced filename for cgroup '%s': '%s'", cg->id, cg->io_serviced.filename);
- }
- else
- debug(D_CGROUP, "io_serviced file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_blkio_throttle_io && !cg->throttle_io_service_bytes.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.throttle.io_service_bytes", cgroup_blkio_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->throttle_io_service_bytes.filename = strdupz(filename);
- cg->throttle_io_service_bytes.enabled = cgroup_enable_blkio_throttle_io;
- debug(D_CGROUP, "throttle_io_service_bytes filename for cgroup '%s': '%s'", cg->id, cg->throttle_io_service_bytes.filename);
- }
- else
- debug(D_CGROUP, "throttle_io_service_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_blkio_throttle_ops && !cg->throttle_io_serviced.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.throttle.io_serviced", cgroup_blkio_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->throttle_io_serviced.filename = strdupz(filename);
- cg->throttle_io_serviced.enabled = cgroup_enable_blkio_throttle_ops;
- debug(D_CGROUP, "throttle_io_serviced filename for cgroup '%s': '%s'", cg->id, cg->throttle_io_serviced.filename);
- }
- else
- debug(D_CGROUP, "throttle_io_serviced file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_blkio_merged_ops && !cg->io_merged.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_merged", cgroup_blkio_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->io_merged.filename = strdupz(filename);
- cg->io_merged.enabled = cgroup_enable_blkio_merged_ops;
- debug(D_CGROUP, "io_merged filename for cgroup '%s': '%s'", cg->id, cg->io_merged.filename);
- }
- else
- debug(D_CGROUP, "io_merged file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
-
- if(unlikely(cgroup_enable_blkio_queued_ops && !cg->io_queued.filename)) {
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_queued", cgroup_blkio_base, cg->id);
- if(likely(stat(filename, &buf) != -1)) {
- cg->io_queued.filename = strdupz(filename);
- cg->io_queued.enabled = cgroup_enable_blkio_queued_ops;
- debug(D_CGROUP, "io_queued filename for cgroup '%s': '%s'", cg->id, cg->io_queued.filename);
- }
- else
- debug(D_CGROUP, "io_queued file for cgroup '%s': '%s' does not exist.", cg->id, filename);
- }
- }
-
- debug(D_CGROUP, "done searching for cgroups");
-}
-
-// ----------------------------------------------------------------------------
-// generate charts
-
-#define CHART_TITLE_MAX 300
-
-void update_systemd_services_charts(
- int update_every
- , int do_cpu
- , int do_mem_usage
- , int do_mem_detailed
- , int do_mem_failcnt
- , int do_swap_usage
- , int do_io
- , int do_io_ops
- , int do_throttle_io
- , int do_throttle_ops
- , int do_queued_ops
- , int do_merged_ops
-) {
- static RRDSET
- *st_cpu = NULL,
- *st_mem_usage = NULL,
- *st_mem_failcnt = NULL,
- *st_swap_usage = NULL,
-
- *st_mem_detailed_cache = NULL,
- *st_mem_detailed_rss = NULL,
- *st_mem_detailed_mapped = NULL,
- *st_mem_detailed_writeback = NULL,
- *st_mem_detailed_pgfault = NULL,
- *st_mem_detailed_pgmajfault = NULL,
- *st_mem_detailed_pgpgin = NULL,
- *st_mem_detailed_pgpgout = NULL,
-
- *st_io_read = NULL,
- *st_io_serviced_read = NULL,
- *st_throttle_io_read = NULL,
- *st_throttle_ops_read = NULL,
- *st_queued_ops_read = NULL,
- *st_merged_ops_read = NULL,
-
- *st_io_write = NULL,
- *st_io_serviced_write = NULL,
- *st_throttle_io_write = NULL,
- *st_throttle_ops_write = NULL,
- *st_queued_ops_write = NULL,
- *st_merged_ops_write = NULL;
-
- // create the charts
-
- if(likely(do_cpu)) {
- if(unlikely(!st_cpu)) {
- char title[CHART_TITLE_MAX + 1];
- snprintfz(title, CHART_TITLE_MAX, "Systemd Services CPU utilization (%d%% = %d core%s)", (processors * 100), processors, (processors > 1) ? "s" : "");
-
- st_cpu = rrdset_create_localhost(
- "services"
- , "cpu"
- , NULL
- , "cpu"
- , "services.cpu"
- , title
- , "%"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_cpu);
- }
-
- if(likely(do_mem_usage)) {
- if(unlikely(!st_mem_usage)) {
-
- st_mem_usage = rrdset_create_localhost(
- "services"
- , "mem_usage"
- , NULL
- , "mem"
- , "services.mem_usage"
- , (cgroup_used_memory_without_cache) ? "Systemd Services Used Memory without Cache"
- : "Systemd Services Used Memory"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 10
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_usage);
- }
-
- if(likely(do_mem_detailed)) {
- if(unlikely(!st_mem_detailed_rss)) {
-
- st_mem_detailed_rss = rrdset_create_localhost(
- "services"
- , "mem_rss"
- , NULL
- , "mem"
- , "services.mem_rss"
- , "Systemd Services RSS Memory"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 20
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_rss);
-
- if(unlikely(!st_mem_detailed_mapped)) {
-
- st_mem_detailed_mapped = rrdset_create_localhost(
- "services"
- , "mem_mapped"
- , NULL
- , "mem"
- , "services.mem_mapped"
- , "Systemd Services Mapped Memory"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 30
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_mapped);
-
- if(unlikely(!st_mem_detailed_cache)) {
-
- st_mem_detailed_cache = rrdset_create_localhost(
- "services"
- , "mem_cache"
- , NULL
- , "mem"
- , "services.mem_cache"
- , "Systemd Services Cache Memory"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 40
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_cache);
-
- if(unlikely(!st_mem_detailed_writeback)) {
-
- st_mem_detailed_writeback = rrdset_create_localhost(
- "services"
- , "mem_writeback"
- , NULL
- , "mem"
- , "services.mem_writeback"
- , "Systemd Services Writeback Memory"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 50
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_writeback);
-
- if(unlikely(!st_mem_detailed_pgfault)) {
-
- st_mem_detailed_pgfault = rrdset_create_localhost(
- "services"
- , "mem_pgfault"
- , NULL
- , "mem"
- , "services.mem_pgfault"
- , "Systemd Services Memory Minor Page Faults"
- , "MB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 60
- , update_every
- , RRDSET_TYPE_STACKED
- );
- }
- else
- rrdset_next(st_mem_detailed_pgfault);
-
- if(unlikely(!st_mem_detailed_pgmajfault)) {
-
- st_mem_detailed_pgmajfault = rrdset_create_localhost(
- "services"
- , "mem_pgmajfault"
- , NULL
- , "mem"
- , "services.mem_pgmajfault"
- , "Systemd Services Memory Major Page Faults"
- , "MB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 70
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_pgmajfault);
-
- if(unlikely(!st_mem_detailed_pgpgin)) {
-
- st_mem_detailed_pgpgin = rrdset_create_localhost(
- "services"
- , "mem_pgpgin"
- , NULL
- , "mem"
- , "services.mem_pgpgin"
- , "Systemd Services Memory Charging Activity"
- , "MB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 80
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_pgpgin);
-
- if(unlikely(!st_mem_detailed_pgpgout)) {
-
- st_mem_detailed_pgpgout = rrdset_create_localhost(
- "services"
- , "mem_pgpgout"
- , NULL
- , "mem"
- , "services.mem_pgpgout"
- , "Systemd Services Memory Uncharging Activity"
- , "MB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 90
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_detailed_pgpgout);
- }
-
- if(likely(do_mem_failcnt)) {
- if(unlikely(!st_mem_failcnt)) {
-
- st_mem_failcnt = rrdset_create_localhost(
- "services"
- , "mem_failcnt"
- , NULL
- , "mem"
- , "services.mem_failcnt"
- , "Systemd Services Memory Limit Failures"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 110
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_mem_failcnt);
- }
-
- if(likely(do_swap_usage)) {
- if(unlikely(!st_swap_usage)) {
-
- st_swap_usage = rrdset_create_localhost(
- "services"
- , "swap_usage"
- , NULL
- , "swap"
- , "services.swap_usage"
- , "Systemd Services Swap Memory Used"
- , "MB"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 100
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_swap_usage);
- }
-
- if(likely(do_io)) {
- if(unlikely(!st_io_read)) {
-
- st_io_read = rrdset_create_localhost(
- "services"
- , "io_read"
- , NULL
- , "disk"
- , "services.io_read"
- , "Systemd Services Disk Read Bandwidth"
- , "KB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 120
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_io_read);
-
- if(unlikely(!st_io_write)) {
-
- st_io_write = rrdset_create_localhost(
- "services"
- , "io_write"
- , NULL
- , "disk"
- , "services.io_write"
- , "Systemd Services Disk Write Bandwidth"
- , "KB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 130
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_io_write);
- }
-
- if(likely(do_io_ops)) {
- if(unlikely(!st_io_serviced_read)) {
-
- st_io_serviced_read = rrdset_create_localhost(
- "services"
- , "io_ops_read"
- , NULL
- , "disk"
- , "services.io_ops_read"
- , "Systemd Services Disk Read Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 140
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_io_serviced_read);
-
- if(unlikely(!st_io_serviced_write)) {
-
- st_io_serviced_write = rrdset_create_localhost(
- "services"
- , "io_ops_write"
- , NULL
- , "disk"
- , "services.io_ops_write"
- , "Systemd Services Disk Write Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 150
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_io_serviced_write);
- }
-
- if(likely(do_throttle_io)) {
- if(unlikely(!st_throttle_io_read)) {
-
- st_throttle_io_read = rrdset_create_localhost(
- "services"
- , "throttle_io_read"
- , NULL
- , "disk"
- , "services.throttle_io_read"
- , "Systemd Services Throttle Disk Read Bandwidth"
- , "KB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 160
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_throttle_io_read);
-
- if(unlikely(!st_throttle_io_write)) {
-
- st_throttle_io_write = rrdset_create_localhost(
- "services"
- , "throttle_io_write"
- , NULL
- , "disk"
- , "services.throttle_io_write"
- , "Systemd Services Throttle Disk Write Bandwidth"
- , "KB/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 170
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_throttle_io_write);
- }
-
- if(likely(do_throttle_ops)) {
- if(unlikely(!st_throttle_ops_read)) {
-
- st_throttle_ops_read = rrdset_create_localhost(
- "services"
- , "throttle_io_ops_read"
- , NULL
- , "disk"
- , "services.throttle_io_ops_read"
- , "Systemd Services Throttle Disk Read Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 180
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_throttle_ops_read);
-
- if(unlikely(!st_throttle_ops_write)) {
-
- st_throttle_ops_write = rrdset_create_localhost(
- "services"
- , "throttle_io_ops_write"
- , NULL
- , "disk"
- , "services.throttle_io_ops_write"
- , "Systemd Services Throttle Disk Write Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 190
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_throttle_ops_write);
- }
-
- if(likely(do_queued_ops)) {
- if(unlikely(!st_queued_ops_read)) {
-
- st_queued_ops_read = rrdset_create_localhost(
- "services"
- , "queued_io_ops_read"
- , NULL
- , "disk"
- , "services.queued_io_ops_read"
- , "Systemd Services Queued Disk Read Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 200
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_queued_ops_read);
-
- if(unlikely(!st_queued_ops_write)) {
-
- st_queued_ops_write = rrdset_create_localhost(
- "services"
- , "queued_io_ops_write"
- , NULL
- , "disk"
- , "services.queued_io_ops_write"
- , "Systemd Services Queued Disk Write Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 210
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_queued_ops_write);
- }
-
- if(likely(do_merged_ops)) {
- if(unlikely(!st_merged_ops_read)) {
-
- st_merged_ops_read = rrdset_create_localhost(
- "services"
- , "merged_io_ops_read"
- , NULL
- , "disk"
- , "services.merged_io_ops_read"
- , "Systemd Services Merged Disk Read Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 220
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_merged_ops_read);
-
- if(unlikely(!st_merged_ops_write)) {
-
- st_merged_ops_write = rrdset_create_localhost(
- "services"
- , "merged_io_ops_write"
- , NULL
- , "disk"
- , "services.merged_io_ops_write"
- , "Systemd Services Merged Disk Write Operations"
- , "operations/s"
- , "cgroup"
- , "systemd"
- , CHART_PRIORITY_SYSTEMD_SERVICES + 230
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- }
- else
- rrdset_next(st_merged_ops_write);
- }
-
- // update the values
- struct cgroup *cg;
- for(cg = cgroup_root; cg ; cg = cg->next) {
- if(unlikely(!cg->available || !cg->enabled || !(cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)))
- continue;
-
- if(likely(do_cpu && cg->cpuacct_stat.updated)) {
- if(unlikely(!cg->rd_cpu))
- cg->rd_cpu = rrddim_add(st_cpu, cg->chart_id, cg->chart_title, 100, hz, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_cpu, cg->rd_cpu, cg->cpuacct_stat.user + cg->cpuacct_stat.system);
- }
-
- if(likely(do_mem_usage && cg->memory.updated_usage_in_bytes)) {
- if(unlikely(!cg->rd_mem_usage))
- cg->rd_mem_usage = rrddim_add(st_mem_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_set_by_pointer(st_mem_usage, cg->rd_mem_usage, cg->memory.usage_in_bytes - ((cgroup_used_memory_without_cache)?cg->memory.cache:0));
- }
-
- if(likely(do_mem_detailed && cg->memory.updated_detailed)) {
- if(unlikely(!cg->rd_mem_detailed_rss))
- cg->rd_mem_detailed_rss = rrddim_add(st_mem_detailed_rss, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_set_by_pointer(st_mem_detailed_rss, cg->rd_mem_detailed_rss, cg->memory.rss + cg->memory.rss_huge);
-
- if(unlikely(!cg->rd_mem_detailed_mapped))
- cg->rd_mem_detailed_mapped = rrddim_add(st_mem_detailed_mapped, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_set_by_pointer(st_mem_detailed_mapped, cg->rd_mem_detailed_mapped, cg->memory.mapped_file);
-
- if(unlikely(!cg->rd_mem_detailed_cache))
- cg->rd_mem_detailed_cache = rrddim_add(st_mem_detailed_cache, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_set_by_pointer(st_mem_detailed_cache, cg->rd_mem_detailed_cache, cg->memory.cache);
-
- if(unlikely(!cg->rd_mem_detailed_writeback))
- cg->rd_mem_detailed_writeback = rrddim_add(st_mem_detailed_writeback, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_set_by_pointer(st_mem_detailed_writeback, cg->rd_mem_detailed_writeback, cg->memory.writeback);
-
- if(unlikely(!cg->rd_mem_detailed_pgfault))
- cg->rd_mem_detailed_pgfault = rrddim_add(st_mem_detailed_pgfault, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_mem_detailed_pgfault, cg->rd_mem_detailed_pgfault, cg->memory.pgfault);
-
- if(unlikely(!cg->rd_mem_detailed_pgmajfault))
- cg->rd_mem_detailed_pgmajfault = rrddim_add(st_mem_detailed_pgmajfault, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_mem_detailed_pgmajfault, cg->rd_mem_detailed_pgmajfault, cg->memory.pgmajfault);
-
- if(unlikely(!cg->rd_mem_detailed_pgpgin))
- cg->rd_mem_detailed_pgpgin = rrddim_add(st_mem_detailed_pgpgin, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_mem_detailed_pgpgin, cg->rd_mem_detailed_pgpgin, cg->memory.pgpgin);
-
- if(unlikely(!cg->rd_mem_detailed_pgpgout))
- cg->rd_mem_detailed_pgpgout = rrddim_add(st_mem_detailed_pgpgout, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_mem_detailed_pgpgout, cg->rd_mem_detailed_pgpgout, cg->memory.pgpgout);
- }
-
- if(likely(do_mem_failcnt && cg->memory.updated_failcnt)) {
- if(unlikely(!cg->rd_mem_failcnt))
- cg->rd_mem_failcnt = rrddim_add(st_mem_failcnt, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_mem_failcnt, cg->rd_mem_failcnt, cg->memory.failcnt);
- }
-
- if(likely(do_swap_usage && cg->memory.updated_msw_usage_in_bytes)) {
- if(unlikely(!cg->rd_swap_usage))
- cg->rd_swap_usage = rrddim_add(st_swap_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_set_by_pointer(st_swap_usage, cg->rd_swap_usage, cg->memory.msw_usage_in_bytes);
- }
-
- if(likely(do_io && cg->io_service_bytes.updated)) {
- if(unlikely(!cg->rd_io_service_bytes_read))
- cg->rd_io_service_bytes_read = rrddim_add(st_io_read, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_io_read, cg->rd_io_service_bytes_read, cg->io_service_bytes.Read);
-
- if(unlikely(!cg->rd_io_service_bytes_write))
- cg->rd_io_service_bytes_write = rrddim_add(st_io_write, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_io_write, cg->rd_io_service_bytes_write, cg->io_service_bytes.Write);
- }
-
- if(likely(do_io_ops && cg->io_serviced.updated)) {
- if(unlikely(!cg->rd_io_serviced_read))
- cg->rd_io_serviced_read = rrddim_add(st_io_serviced_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_io_serviced_read, cg->rd_io_serviced_read, cg->io_serviced.Read);
-
- if(unlikely(!cg->rd_io_serviced_write))
- cg->rd_io_serviced_write = rrddim_add(st_io_serviced_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_io_serviced_write, cg->rd_io_serviced_write, cg->io_serviced.Write);
- }
-
- if(likely(do_throttle_io && cg->throttle_io_service_bytes.updated)) {
- if(unlikely(!cg->rd_throttle_io_read))
- cg->rd_throttle_io_read = rrddim_add(st_throttle_io_read, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_throttle_io_read, cg->rd_throttle_io_read, cg->throttle_io_service_bytes.Read);
-
- if(unlikely(!cg->rd_throttle_io_write))
- cg->rd_throttle_io_write = rrddim_add(st_throttle_io_write, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_throttle_io_write, cg->rd_throttle_io_write, cg->throttle_io_service_bytes.Write);
- }
-
- if(likely(do_throttle_ops && cg->throttle_io_serviced.updated)) {
- if(unlikely(!cg->rd_throttle_io_serviced_read))
- cg->rd_throttle_io_serviced_read = rrddim_add(st_throttle_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_throttle_ops_read, cg->rd_throttle_io_serviced_read, cg->throttle_io_serviced.Read);
-
- if(unlikely(!cg->rd_throttle_io_serviced_write))
- cg->rd_throttle_io_serviced_write = rrddim_add(st_throttle_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_throttle_ops_write, cg->rd_throttle_io_serviced_write, cg->throttle_io_serviced.Write);
- }
-
- if(likely(do_queued_ops && cg->io_queued.updated)) {
- if(unlikely(!cg->rd_io_queued_read))
- cg->rd_io_queued_read = rrddim_add(st_queued_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_queued_ops_read, cg->rd_io_queued_read, cg->io_queued.Read);
-
- if(unlikely(!cg->rd_io_queued_write))
- cg->rd_io_queued_write = rrddim_add(st_queued_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_queued_ops_write, cg->rd_io_queued_write, cg->io_queued.Write);
- }
-
- if(likely(do_merged_ops && cg->io_merged.updated)) {
- if(unlikely(!cg->rd_io_merged_read))
- cg->rd_io_merged_read = rrddim_add(st_merged_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_merged_ops_read, cg->rd_io_merged_read, cg->io_merged.Read);
-
- if(unlikely(!cg->rd_io_merged_write))
- cg->rd_io_merged_write = rrddim_add(st_merged_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- rrddim_set_by_pointer(st_merged_ops_write, cg->rd_io_merged_write, cg->io_merged.Write);
- }
- }
-
- // complete the iteration
- if(likely(do_cpu))
- rrdset_done(st_cpu);
-
- if(likely(do_mem_usage))
- rrdset_done(st_mem_usage);
-
- if(unlikely(do_mem_detailed)) {
- rrdset_done(st_mem_detailed_cache);
- rrdset_done(st_mem_detailed_rss);
- rrdset_done(st_mem_detailed_mapped);
- rrdset_done(st_mem_detailed_writeback);
- rrdset_done(st_mem_detailed_pgfault);
- rrdset_done(st_mem_detailed_pgmajfault);
- rrdset_done(st_mem_detailed_pgpgin);
- rrdset_done(st_mem_detailed_pgpgout);
- }
-
- if(likely(do_mem_failcnt))
- rrdset_done(st_mem_failcnt);
-
- if(likely(do_swap_usage))
- rrdset_done(st_swap_usage);
-
- if(likely(do_io)) {
- rrdset_done(st_io_read);
- rrdset_done(st_io_write);
- }
-
- if(likely(do_io_ops)) {
- rrdset_done(st_io_serviced_read);
- rrdset_done(st_io_serviced_write);
- }
-
- if(likely(do_throttle_io)) {
- rrdset_done(st_throttle_io_read);
- rrdset_done(st_throttle_io_write);
- }
-
- if(likely(do_throttle_ops)) {
- rrdset_done(st_throttle_ops_read);
- rrdset_done(st_throttle_ops_write);
- }
-
- if(likely(do_queued_ops)) {
- rrdset_done(st_queued_ops_read);
- rrdset_done(st_queued_ops_write);
- }
-
- if(likely(do_merged_ops)) {
- rrdset_done(st_merged_ops_read);
- rrdset_done(st_merged_ops_write);
- }
-}
-
-static inline char *cgroup_chart_type(char *buffer, const char *id, size_t len) {
- if(buffer[0]) return buffer;
-
- if(id[0] == '\0' || (id[0] == '/' && id[1] == '\0'))
- strncpy(buffer, "cgroup_root", len);
- else
- snprintfz(buffer, len, "cgroup_%s", id);
-
- netdata_fix_chart_id(buffer);
- return buffer;
-}
-
-void update_cgroup_charts(int update_every) {
- debug(D_CGROUP, "updating cgroups charts");
-
- char type[RRD_ID_LENGTH_MAX + 1];
- char title[CHART_TITLE_MAX + 1];
-
- int services_do_cpu = 0,
- services_do_mem_usage = 0,
- services_do_mem_detailed = 0,
- services_do_mem_failcnt = 0,
- services_do_swap_usage = 0,
- services_do_io = 0,
- services_do_io_ops = 0,
- services_do_throttle_io = 0,
- services_do_throttle_ops = 0,
- services_do_queued_ops = 0,
- services_do_merged_ops = 0;
-
- struct cgroup *cg;
- for(cg = cgroup_root; cg ; cg = cg->next) {
- if(unlikely(!cg->available || !cg->enabled))
- continue;
-
- if(likely(cgroup_enable_systemd_services && cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)) {
- if(cg->cpuacct_stat.updated && cg->cpuacct_stat.enabled == CONFIG_BOOLEAN_YES) services_do_cpu++;
-
- if(cgroup_enable_systemd_services_detailed_memory && cg->memory.updated_detailed && cg->memory.enabled_detailed) services_do_mem_detailed++;
- if(cg->memory.updated_usage_in_bytes && cg->memory.enabled_usage_in_bytes == CONFIG_BOOLEAN_YES) services_do_mem_usage++;
- if(cg->memory.updated_failcnt && cg->memory.enabled_failcnt == CONFIG_BOOLEAN_YES) services_do_mem_failcnt++;
- if(cg->memory.updated_msw_usage_in_bytes && cg->memory.enabled_msw_usage_in_bytes == CONFIG_BOOLEAN_YES) services_do_swap_usage++;
-
- if(cg->io_service_bytes.updated && cg->io_service_bytes.enabled == CONFIG_BOOLEAN_YES) services_do_io++;
- if(cg->io_serviced.updated && cg->io_serviced.enabled == CONFIG_BOOLEAN_YES) services_do_io_ops++;
- if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.enabled == CONFIG_BOOLEAN_YES) services_do_throttle_io++;
- if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.enabled == CONFIG_BOOLEAN_YES) services_do_throttle_ops++;
- if(cg->io_queued.updated && cg->io_queued.enabled == CONFIG_BOOLEAN_YES) services_do_queued_ops++;
- if(cg->io_merged.updated && cg->io_merged.enabled == CONFIG_BOOLEAN_YES) services_do_merged_ops++;
- continue;
- }
-
- type[0] = '\0';
-
- if(likely(cg->cpuacct_stat.updated && cg->cpuacct_stat.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_cpu)) {
- snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) for cgroup %s", (processors * 100), processors, (processors > 1) ? "s" : "", cg->chart_title);
-
- cg->st_cpu = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "cpu"
- , NULL
- , "cpu"
- , "cgroup.cpu"
- , title
- , "%"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(cg->st_cpu, "user", NULL, 100, hz, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_cpu, "system", NULL, 100, hz, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_cpu);
-
- rrddim_set(cg->st_cpu, "user", cg->cpuacct_stat.user);
- rrddim_set(cg->st_cpu, "system", cg->cpuacct_stat.system);
- rrdset_done(cg->st_cpu);
- }
-
- if(likely(cg->cpuacct_usage.updated && cg->cpuacct_usage.enabled == CONFIG_BOOLEAN_YES)) {
- char id[RRD_ID_LENGTH_MAX + 1];
- unsigned int i;
-
- if(unlikely(!cg->st_cpu_per_core)) {
- snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) Per Core for cgroup %s", (processors * 100), processors, (processors > 1) ? "s" : "", cg->chart_title);
-
- cg->st_cpu_per_core = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "cpu_per_core"
- , NULL
- , "cpu"
- , "cgroup.cpu_per_core"
- , title
- , "%"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 100
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- for(i = 0; i < cg->cpuacct_usage.cpus; i++) {
- snprintfz(id, RRD_ID_LENGTH_MAX, "cpu%u", i);
- rrddim_add(cg->st_cpu_per_core, id, NULL, 100, 1000000000, RRD_ALGORITHM_INCREMENTAL);
- }
- }
- else
- rrdset_next(cg->st_cpu_per_core);
-
- for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
- snprintfz(id, RRD_ID_LENGTH_MAX, "cpu%u", i);
- rrddim_set(cg->st_cpu_per_core, id, cg->cpuacct_usage.cpu_percpu[i]);
- }
- rrdset_done(cg->st_cpu_per_core);
- }
-
- if(likely(cg->memory.updated_detailed && cg->memory.enabled_detailed == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_mem)) {
- snprintfz(title, CHART_TITLE_MAX, "Memory Usage for cgroup %s", cg->chart_title);
-
- cg->st_mem = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "mem"
- , NULL
- , "mem"
- , "cgroup.mem"
- , title
- , "MB"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 210
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(cg->st_mem, "cache", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(cg->st_mem, "rss", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- if(cg->memory.detailed_has_swap)
- rrddim_add(cg->st_mem, "swap", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_add(cg->st_mem, "rss_huge", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(cg->st_mem, "mapped_file", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(cg->st_mem);
-
- rrddim_set(cg->st_mem, "cache", cg->memory.cache);
- rrddim_set(cg->st_mem, "rss", cg->memory.rss);
-
- if(cg->memory.detailed_has_swap)
- rrddim_set(cg->st_mem, "swap", cg->memory.swap);
-
- rrddim_set(cg->st_mem, "rss_huge", cg->memory.rss_huge);
- rrddim_set(cg->st_mem, "mapped_file", cg->memory.mapped_file);
- rrdset_done(cg->st_mem);
-
- if(unlikely(!cg->st_writeback)) {
- snprintfz(title, CHART_TITLE_MAX, "Writeback Memory for cgroup %s", cg->chart_title);
-
- cg->st_writeback = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "writeback"
- , NULL
- , "mem"
- , "cgroup.writeback"
- , title
- , "MB"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 300
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- if(cg->memory.detailed_has_dirty)
- rrddim_add(cg->st_writeback, "dirty", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
-
- rrddim_add(cg->st_writeback, "writeback", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(cg->st_writeback);
-
- if(cg->memory.detailed_has_dirty)
- rrddim_set(cg->st_writeback, "dirty", cg->memory.dirty);
-
- rrddim_set(cg->st_writeback, "writeback", cg->memory.writeback);
- rrdset_done(cg->st_writeback);
-
- if(unlikely(!cg->st_mem_activity)) {
- snprintfz(title, CHART_TITLE_MAX, "Memory Activity for cgroup %s", cg->chart_title);
-
- cg->st_mem_activity = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "mem_activity"
- , NULL
- , "mem"
- , "cgroup.mem_activity"
- , title
- , "MB/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 400
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_mem_activity, "pgpgin", "in", system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_mem_activity, "pgpgout", "out", -system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_mem_activity);
-
- rrddim_set(cg->st_mem_activity, "pgpgin", cg->memory.pgpgin);
- rrddim_set(cg->st_mem_activity, "pgpgout", cg->memory.pgpgout);
- rrdset_done(cg->st_mem_activity);
-
- if(unlikely(!cg->st_pgfaults)) {
- snprintfz(title, CHART_TITLE_MAX, "Memory Page Faults for cgroup %s", cg->chart_title);
-
- cg->st_pgfaults = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "pgfaults"
- , NULL
- , "mem"
- , "cgroup.pgfaults"
- , title
- , "MB/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 500
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_pgfaults, "pgfault", NULL, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_pgfaults, "pgmajfault", "swap", -system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_pgfaults);
-
- rrddim_set(cg->st_pgfaults, "pgfault", cg->memory.pgfault);
- rrddim_set(cg->st_pgfaults, "pgmajfault", cg->memory.pgmajfault);
- rrdset_done(cg->st_pgfaults);
- }
-
- if(likely(cg->memory.updated_usage_in_bytes && cg->memory.enabled_usage_in_bytes == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_mem_usage)) {
- snprintfz(title, CHART_TITLE_MAX, "Used Memory %sfor cgroup %s", (cgroup_used_memory_without_cache && cg->memory.updated_detailed)?"without Cache ":"", cg->chart_title);
-
- cg->st_mem_usage = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "mem_usage"
- , NULL
- , "mem"
- , "cgroup.mem_usage"
- , title
- , "MB"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 200
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(cg->st_mem_usage, "ram", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(cg->st_mem_usage, "swap", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(cg->st_mem_usage);
-
- rrddim_set(cg->st_mem_usage, "ram", cg->memory.usage_in_bytes - ((cgroup_used_memory_without_cache)?cg->memory.cache:0));
- rrddim_set(cg->st_mem_usage, "swap", (cg->memory.msw_usage_in_bytes > cg->memory.usage_in_bytes)?cg->memory.msw_usage_in_bytes - cg->memory.usage_in_bytes:0);
- rrdset_done(cg->st_mem_usage);
- }
-
- if(likely(cg->memory.updated_failcnt && cg->memory.enabled_failcnt == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_mem_failcnt)) {
- snprintfz(title, CHART_TITLE_MAX, "Memory Limit Failures for cgroup %s", cg->chart_title);
-
- cg->st_mem_failcnt = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "mem_failcnt"
- , NULL
- , "mem"
- , "cgroup.mem_failcnt"
- , title
- , "count"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 250
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_mem_failcnt, "failures", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_mem_failcnt);
-
- rrddim_set(cg->st_mem_failcnt, "failures", cg->memory.failcnt);
- rrdset_done(cg->st_mem_failcnt);
- }
-
- if(likely(cg->io_service_bytes.updated && cg->io_service_bytes.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_io)) {
- snprintfz(title, CHART_TITLE_MAX, "I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
-
- cg->st_io = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "io"
- , NULL
- , "disk"
- , "cgroup.io"
- , title
- , "KB/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 1200
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(cg->st_io, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_io, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_io);
-
- rrddim_set(cg->st_io, "read", cg->io_service_bytes.Read);
- rrddim_set(cg->st_io, "write", cg->io_service_bytes.Write);
- rrdset_done(cg->st_io);
- }
-
- if(likely(cg->io_serviced.updated && cg->io_serviced.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_serviced_ops)) {
- snprintfz(title, CHART_TITLE_MAX, "Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
-
- cg->st_serviced_ops = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "serviced_ops"
- , NULL
- , "disk"
- , "cgroup.serviced_ops"
- , title
- , "operations/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 1200
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_serviced_ops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_serviced_ops, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_serviced_ops);
-
- rrddim_set(cg->st_serviced_ops, "read", cg->io_serviced.Read);
- rrddim_set(cg->st_serviced_ops, "write", cg->io_serviced.Write);
- rrdset_done(cg->st_serviced_ops);
- }
-
- if(likely(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_throttle_io)) {
- snprintfz(title, CHART_TITLE_MAX, "Throttle I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
-
- cg->st_throttle_io = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "throttle_io"
- , NULL
- , "disk"
- , "cgroup.throttle_io"
- , title
- , "KB/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 1200
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rrddim_add(cg->st_throttle_io, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_throttle_io, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_throttle_io);
-
- rrddim_set(cg->st_throttle_io, "read", cg->throttle_io_service_bytes.Read);
- rrddim_set(cg->st_throttle_io, "write", cg->throttle_io_service_bytes.Write);
- rrdset_done(cg->st_throttle_io);
- }
-
- if(likely(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_throttle_serviced_ops)) {
- snprintfz(title, CHART_TITLE_MAX, "Throttle Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
-
- cg->st_throttle_serviced_ops = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "throttle_serviced_ops"
- , NULL
- , "disk"
- , "cgroup.throttle_serviced_ops"
- , title
- , "operations/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 1200
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_throttle_serviced_ops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_throttle_serviced_ops, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_throttle_serviced_ops);
-
- rrddim_set(cg->st_throttle_serviced_ops, "read", cg->throttle_io_serviced.Read);
- rrddim_set(cg->st_throttle_serviced_ops, "write", cg->throttle_io_serviced.Write);
- rrdset_done(cg->st_throttle_serviced_ops);
- }
-
- if(likely(cg->io_queued.updated && cg->io_queued.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_queued_ops)) {
- snprintfz(title, CHART_TITLE_MAX, "Queued I/O Operations (all disks) for cgroup %s", cg->chart_title);
-
- cg->st_queued_ops = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "queued_ops"
- , NULL
- , "disk"
- , "cgroup.queued_ops"
- , title
- , "operations"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 2000
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_queued_ops, "read", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rrddim_add(cg->st_queued_ops, "write", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(cg->st_queued_ops);
-
- rrddim_set(cg->st_queued_ops, "read", cg->io_queued.Read);
- rrddim_set(cg->st_queued_ops, "write", cg->io_queued.Write);
- rrdset_done(cg->st_queued_ops);
- }
-
- if(likely(cg->io_merged.updated && cg->io_merged.enabled == CONFIG_BOOLEAN_YES)) {
- if(unlikely(!cg->st_merged_ops)) {
- snprintfz(title, CHART_TITLE_MAX, "Merged I/O Operations (all disks) for cgroup %s", cg->chart_title);
-
- cg->st_merged_ops = rrdset_create_localhost(
- cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX)
- , "merged_ops"
- , NULL
- , "disk"
- , "cgroup.merged_ops"
- , title
- , "operations/s"
- , "cgroup"
- , "default"
- , CHART_PRIORITY_CONTAINERS + 2100
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rrddim_add(cg->st_merged_ops, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(cg->st_merged_ops, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(cg->st_merged_ops);
-
- rrddim_set(cg->st_merged_ops, "read", cg->io_merged.Read);
- rrddim_set(cg->st_merged_ops, "write", cg->io_merged.Write);
- rrdset_done(cg->st_merged_ops);
- }
- }
-
- if(likely(cgroup_enable_systemd_services))
- update_systemd_services_charts(update_every, services_do_cpu, services_do_mem_usage, services_do_mem_detailed
- , services_do_mem_failcnt, services_do_swap_usage, services_do_io
- , services_do_io_ops, services_do_throttle_io, services_do_throttle_ops
- , services_do_queued_ops, services_do_merged_ops
- );
-
- debug(D_CGROUP, "done updating cgroups charts");
-}
-
-// ----------------------------------------------------------------------------
-// cgroups main
-
-static void cgroup_main_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *cgroups_main(void *ptr) {
- netdata_thread_cleanup_push(cgroup_main_cleanup, ptr);
-
- struct rusage thread;
-
- // when ZERO, attempt to do it
- int vdo_cpu_netdata = config_get_boolean("plugin:cgroups", "cgroups plugin resource charts", 1);
-
- read_cgroup_plugin_configuration();
-
- RRDSET *stcpu_thread = NULL;
-
- heartbeat_t hb;
- heartbeat_init(&hb);
- usec_t step = cgroup_update_every * USEC_PER_SEC;
- usec_t find_every = cgroup_check_for_new_every * USEC_PER_SEC, find_dt = 0;
-
- while(!netdata_exit) {
- usec_t hb_dt = heartbeat_next(&hb, step);
- if(unlikely(netdata_exit)) break;
-
- // BEGIN -- the job to be done
-
- find_dt += hb_dt;
- if(unlikely(find_dt >= find_every || cgroups_check)) {
- find_all_cgroups();
- find_dt = 0;
- cgroups_check = 0;
- }
-
- read_all_cgroups(cgroup_root);
- update_cgroup_charts(cgroup_update_every);
-
- // END -- the job is done
-
- // --------------------------------------------------------------------
-
- if(vdo_cpu_netdata) {
- getrusage(RUSAGE_THREAD, &thread);
-
- if(unlikely(!stcpu_thread)) {
-
- stcpu_thread = rrdset_create_localhost(
- "netdata"
- , "plugin_cgroups_cpu"
- , NULL
- , "cgroups"
- , NULL
- , "NetData CGroups Plugin CPU usage"
- , "milliseconds/s"
- , "cgroup"
- , "stats"
- , 132000
- , cgroup_update_every
- , RRDSET_TYPE_STACKED
- );
-
- rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(stcpu_thread);
-
- rrddim_set(stcpu_thread, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
- rrddim_set(stcpu_thread, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
- rrdset_done(stcpu_thread);
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/sys_kernel_mm_ksm.c b/src/sys_kernel_mm_ksm.c
deleted file mode 100644
index 7ca1366b4..000000000
--- a/src/sys_kernel_mm_ksm.c
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "common.h"
-
-typedef struct ksm_name_value {
- char filename[FILENAME_MAX + 1];
- unsigned long long value;
-} KSM_NAME_VALUE;
-
-#define PAGES_SHARED 0
-#define PAGES_SHARING 1
-#define PAGES_UNSHARED 2
-#define PAGES_VOLATILE 3
-#define PAGES_TO_SCAN 4
-
-KSM_NAME_VALUE values[] = {
- [PAGES_SHARED] = { "/sys/kernel/mm/ksm/pages_shared", 0ULL },
- [PAGES_SHARING] = { "/sys/kernel/mm/ksm/pages_sharing", 0ULL },
- [PAGES_UNSHARED] = { "/sys/kernel/mm/ksm/pages_unshared", 0ULL },
- [PAGES_VOLATILE] = { "/sys/kernel/mm/ksm/pages_volatile", 0ULL },
- // [PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
-};
-
-int do_sys_kernel_mm_ksm(int update_every, usec_t dt) {
- (void)dt;
- static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL/*, *ff_pages_to_scan = NULL*/;
- static unsigned long page_size = 0;
-
- if(unlikely(page_size == 0))
- page_size = (unsigned long)sysconf(_SC_PAGESIZE);
-
- if(unlikely(!ff_pages_shared)) {
- snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_shared");
- snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_shared", values[PAGES_SHARED].filename));
- ff_pages_shared = procfile_open(values[PAGES_SHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
- }
-
- if(unlikely(!ff_pages_sharing)) {
- snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_sharing");
- snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_sharing", values[PAGES_SHARING].filename));
- ff_pages_sharing = procfile_open(values[PAGES_SHARING].filename, " \t:", PROCFILE_FLAG_DEFAULT);
- }
-
- if(unlikely(!ff_pages_unshared)) {
- snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_unshared");
- snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_unshared", values[PAGES_UNSHARED].filename));
- ff_pages_unshared = procfile_open(values[PAGES_UNSHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
- }
-
- if(unlikely(!ff_pages_volatile)) {
- snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_volatile");
- snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_volatile", values[PAGES_VOLATILE].filename));
- ff_pages_volatile = procfile_open(values[PAGES_VOLATILE].filename, " \t:", PROCFILE_FLAG_DEFAULT);
- }
-
- //if(unlikely(!ff_pages_to_scan)) {
- // snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/kernel/mm/ksm/pages_to_scan");
- // snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_to_scan", values[PAGES_TO_SCAN].filename));
- // ff_pages_to_scan = procfile_open(values[PAGES_TO_SCAN].filename, " \t:", PROCFILE_FLAG_DEFAULT);
- //}
-
- if(unlikely(!ff_pages_shared || !ff_pages_sharing || !ff_pages_unshared || !ff_pages_volatile /*|| !ff_pages_to_scan */))
- return 1;
-
- unsigned long long pages_shared = 0, pages_sharing = 0, pages_unshared = 0, pages_volatile = 0, /*pages_to_scan = 0,*/ offered = 0, saved = 0;
-
- ff_pages_shared = procfile_readall(ff_pages_shared);
- if(unlikely(!ff_pages_shared)) return 0; // we return 0, so that we will retry to open it next time
- pages_shared = str2ull(procfile_lineword(ff_pages_shared, 0, 0));
-
- ff_pages_sharing = procfile_readall(ff_pages_sharing);
- if(unlikely(!ff_pages_sharing)) return 0; // we return 0, so that we will retry to open it next time
- pages_sharing = str2ull(procfile_lineword(ff_pages_sharing, 0, 0));
-
- ff_pages_unshared = procfile_readall(ff_pages_unshared);
- if(unlikely(!ff_pages_unshared)) return 0; // we return 0, so that we will retry to open it next time
- pages_unshared = str2ull(procfile_lineword(ff_pages_unshared, 0, 0));
-
- ff_pages_volatile = procfile_readall(ff_pages_volatile);
- if(unlikely(!ff_pages_volatile)) return 0; // we return 0, so that we will retry to open it next time
- pages_volatile = str2ull(procfile_lineword(ff_pages_volatile, 0, 0));
-
- //ff_pages_to_scan = procfile_readall(ff_pages_to_scan);
- //if(unlikely(!ff_pages_to_scan)) return 0; // we return 0, so that we will retry to open it next time
- //pages_to_scan = str2ull(procfile_lineword(ff_pages_to_scan, 0, 0));
-
- offered = pages_sharing + pages_shared + pages_unshared + pages_volatile;
- saved = pages_sharing;
-
- if(unlikely(!offered /*|| !pages_to_scan*/)) return 0;
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_mem_ksm = NULL;
- static RRDDIM *rd_shared = NULL, *rd_unshared = NULL, *rd_sharing = NULL, *rd_volatile = NULL/*, *rd_to_scan = NULL*/;
-
- if (unlikely(!st_mem_ksm)) {
- st_mem_ksm = rrdset_create_localhost(
- "mem"
- , "ksm"
- , NULL
- , "ksm"
- , NULL
- , "Kernel Same Page Merging"
- , "MB"
- , "proc"
- , "/sys/kernel/mm/ksm"
- , NETDATA_CHART_PRIO_MEM_KSM
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_shared = rrddim_add(st_mem_ksm, "shared", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_unshared = rrddim_add(st_mem_ksm, "unshared", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_sharing = rrddim_add(st_mem_ksm, "sharing", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_volatile = rrddim_add(st_mem_ksm, "volatile", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- //rd_to_scan = rrddim_add(st_mem_ksm, "to_scan", "to scan", -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_mem_ksm);
-
- rrddim_set_by_pointer(st_mem_ksm, rd_shared, pages_shared * page_size);
- rrddim_set_by_pointer(st_mem_ksm, rd_unshared, pages_unshared * page_size);
- rrddim_set_by_pointer(st_mem_ksm, rd_sharing, pages_sharing * page_size);
- rrddim_set_by_pointer(st_mem_ksm, rd_volatile, pages_volatile * page_size);
- //rrddim_set_by_pointer(st_mem_ksm, rd_to_scan, pages_to_scan * page_size);
-
- rrdset_done(st_mem_ksm);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_mem_ksm_savings = NULL;
- static RRDDIM *rd_savings = NULL, *rd_offered = NULL;
-
- if (unlikely(!st_mem_ksm_savings)) {
- st_mem_ksm_savings = rrdset_create_localhost(
- "mem"
- , "ksm_savings"
- , NULL
- , "ksm"
- , NULL
- , "Kernel Same Page Merging Savings"
- , "MB"
- , "proc"
- , "/sys/kernel/mm/ksm"
- , NETDATA_CHART_PRIO_MEM_KSM + 1
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_savings = rrddim_add(st_mem_ksm_savings, "savings", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_offered = rrddim_add(st_mem_ksm_savings, "offered", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_mem_ksm_savings);
-
- rrddim_set_by_pointer(st_mem_ksm_savings, rd_savings, saved * page_size);
- rrddim_set_by_pointer(st_mem_ksm_savings, rd_offered, offered * page_size);
-
- rrdset_done(st_mem_ksm_savings);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_mem_ksm_ratios = NULL;
- static RRDDIM *rd_savings = NULL;
-
- if (unlikely(!st_mem_ksm_ratios)) {
- st_mem_ksm_ratios = rrdset_create_localhost(
- "mem"
- , "ksm_ratios"
- , NULL
- , "ksm"
- , NULL
- , "Kernel Same Page Merging Effectiveness"
- , "percentage"
- , "proc"
- , "/sys/kernel/mm/ksm"
- , NETDATA_CHART_PRIO_MEM_KSM + 2
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_savings = rrddim_add(st_mem_ksm_ratios, "savings", NULL, 1, 10000, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_mem_ksm_ratios);
-
- rrddim_set_by_pointer(st_mem_ksm_ratios, rd_savings, (saved * 1000000) / offered);
-
- rrdset_done(st_mem_ksm_ratios);
- }
-
- return 0;
-}
diff --git a/src/threads.c b/src/threads.c
deleted file mode 100644
index b9ca3c085..000000000
--- a/src/threads.c
+++ /dev/null
@@ -1,181 +0,0 @@
-#include "common.h"
-
-static size_t default_stacksize = 0, wanted_stacksize = 0;
-static pthread_attr_t *attr = NULL;
-
-// ----------------------------------------------------------------------------
-// per thread data
-
-typedef struct {
- void *arg;
- pthread_t *thread;
- const char *tag;
- void *(*start_routine) (void *);
- NETDATA_THREAD_OPTIONS options;
-} NETDATA_THREAD;
-
-static __thread NETDATA_THREAD *netdata_thread = NULL;
-
-const char *netdata_thread_tag(void) {
- return ((netdata_thread && netdata_thread->tag && *netdata_thread->tag)?netdata_thread->tag:"MAIN");
-}
-
-// ----------------------------------------------------------------------------
-// compatibility library functions
-
-pid_t gettid(void) {
-#ifdef __FreeBSD__
-
- return (pid_t)pthread_getthreadid_np();
-
-#elif defined(__APPLE__)
-
- #if (defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
- uint64_t curthreadid;
- pthread_threadid_np(NULL, &curthreadid);
- return (pid_t)curthreadid;
- #else /* __MAC_OS_X_VERSION_MIN_REQUIRED */
- return (pid_t)pthread_self;
- #endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */
-
-#else /* __APPLE__*/
-
- return (pid_t)syscall(SYS_gettid);
-
-#endif /* __FreeBSD__, __APPLE__*/
-}
-
-// ----------------------------------------------------------------------------
-// early initialization
-
-size_t netdata_threads_init(void) {
- int i;
-
- // --------------------------------------------------------------------
- // get the required stack size of the threads of netdata
-
- attr = callocz(1, sizeof(pthread_attr_t));
- i = pthread_attr_init(attr);
- if(i != 0)
- fatal("pthread_attr_init() failed with code %d.", i);
-
- i = pthread_attr_getstacksize(attr, &default_stacksize);
- if(i != 0)
- fatal("pthread_attr_getstacksize() failed with code %d.", i);
- else
- debug(D_OPTIONS, "initial pthread stack size is %zu bytes", default_stacksize);
-
- return default_stacksize;
-}
-
-// ----------------------------------------------------------------------------
-// late initialization
-
-void netdata_threads_init_after_fork(size_t stacksize) {
- wanted_stacksize = stacksize;
- int i;
-
- // ------------------------------------------------------------------------
- // set default pthread stack size
-
- if(attr && default_stacksize < wanted_stacksize && wanted_stacksize > 0) {
- i = pthread_attr_setstacksize(attr, wanted_stacksize);
- if(i != 0)
- fatal("pthread_attr_setstacksize() to %zu bytes, failed with code %d.", wanted_stacksize, i);
- else
- debug(D_SYSTEM, "Successfully set pthread stacksize to %zu bytes", wanted_stacksize);
- }
-}
-
-
-// ----------------------------------------------------------------------------
-// netdata_thread_create
-
-static void thread_cleanup(void *ptr) {
- if(netdata_thread != ptr) {
- NETDATA_THREAD *info = (NETDATA_THREAD *)ptr;
- error("THREADS: internal error - thread local variable does not match the one passed to this function. Expected thread '%s', passed thread '%s'", netdata_thread->tag, info->tag);
- }
-
- if(!(netdata_thread->options & NETDATA_THREAD_OPTION_DONT_LOG_CLEANUP))
- info("thread with task id %d finished", gettid());
-
- freez((void *)netdata_thread->tag);
- netdata_thread->tag = NULL;
-
- freez(netdata_thread);
- netdata_thread = NULL;
-}
-
-static void *thread_start(void *ptr) {
- netdata_thread = (NETDATA_THREAD *)ptr;
-
- if(!(netdata_thread->options & NETDATA_THREAD_OPTION_DONT_LOG_STARTUP))
- info("thread created with task id %d", gettid());
-
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
- error("cannot set pthread cancel type to DEFERRED.");
-
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
- error("cannot set pthread cancel state to ENABLE.");
-
- void *ret = NULL;
- pthread_cleanup_push(thread_cleanup, ptr);
- ret = netdata_thread->start_routine(netdata_thread->arg);
- pthread_cleanup_pop(1);
-
- return ret;
-}
-
-int netdata_thread_create(netdata_thread_t *thread, const char *tag, NETDATA_THREAD_OPTIONS options, void *(*start_routine) (void *), void *arg) {
- NETDATA_THREAD *info = mallocz(sizeof(NETDATA_THREAD));
- info->arg = arg;
- info->thread = thread;
- info->tag = strdupz(tag);
- info->start_routine = start_routine;
- info->options = options;
-
- int ret = pthread_create(thread, attr, thread_start, info);
- if(ret != 0)
- error("failed to create new thread for %s. pthread_create() failed with code %d", tag, ret);
-
- else {
- if (!(options & NETDATA_THREAD_OPTION_JOINABLE)) {
- int ret2 = pthread_detach(*thread);
- if (ret2 != 0)
- error("cannot request detach of newly created %s thread. pthread_detach() failed with code %d", tag, ret2);
- }
- }
-
- return ret;
-}
-
-// ----------------------------------------------------------------------------
-// netdata_thread_cancel
-
-int netdata_thread_cancel(netdata_thread_t thread) {
- int ret = pthread_cancel(thread);
- if(ret != 0)
- error("cannot cancel thread. pthread_cancel() failed with code %d.", ret);
-
- return ret;
-}
-
-// ----------------------------------------------------------------------------
-// netdata_thread_join
-
-int netdata_thread_join(netdata_thread_t thread, void **retval) {
- int ret = pthread_join(thread, retval);
- if(ret != 0)
- error("cannot join thread. pthread_join() failed with code %d.", ret);
-
- return ret;
-}
-
-int netdata_thread_detach(pthread_t thread) {
- int ret = pthread_detach(thread);
- if(ret != 0)
- error("cannot detach thread. pthread_detach() failed with code %d.", ret);
-
- return ret;
-}
diff --git a/src/threads.h b/src/threads.h
deleted file mode 100644
index e2ed6a4ff..000000000
--- a/src/threads.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef NETDATA_THREADS_H
-#define NETDATA_THREADS_H
-
-extern pid_t gettid(void);
-
-typedef enum {
- NETDATA_THREAD_OPTION_DEFAULT = 0 << 0,
- NETDATA_THREAD_OPTION_JOINABLE = 1 << 0,
- NETDATA_THREAD_OPTION_DONT_LOG_STARTUP = 1 << 1,
- NETDATA_THREAD_OPTION_DONT_LOG_CLEANUP = 1 << 2,
- NETDATA_THREAD_OPTION_DONT_LOG = NETDATA_THREAD_OPTION_DONT_LOG_STARTUP|NETDATA_THREAD_OPTION_DONT_LOG_CLEANUP,
-} NETDATA_THREAD_OPTIONS;
-
-#define netdata_thread_cleanup_push(func, arg) pthread_cleanup_push(func, arg)
-#define netdata_thread_cleanup_pop(execute) pthread_cleanup_pop(execute)
-
-typedef pthread_t netdata_thread_t;
-
-#define NETDATA_THREAD_TAG_MAX 100
-extern const char *netdata_thread_tag(void);
-
-extern size_t netdata_threads_init(void);
-extern void netdata_threads_init_after_fork(size_t stacksize);
-
-extern int netdata_thread_create(netdata_thread_t *thread, const char *tag, NETDATA_THREAD_OPTIONS options, void *(*start_routine) (void *), void *arg);
-extern int netdata_thread_cancel(netdata_thread_t thread);
-extern int netdata_thread_join(netdata_thread_t thread, void **retval);
-extern int netdata_thread_detach(pthread_t thread);
-
-#define netdata_thread_self pthread_self
-#define netdata_thread_testcancel pthread_testcancel
-
-#endif //NETDATA_THREADS_H
diff --git a/src/unit_test.c b/src/unit_test.c
deleted file mode 100644
index e3eb146ad..000000000
--- a/src/unit_test.c
+++ /dev/null
@@ -1,1368 +0,0 @@
-#include "common.h"
-
-static int check_number_printing(void) {
- struct {
- calculated_number n;
- const char *correct;
- } values[] = {
- { .n = 0, .correct = "0" },
- { .n = 0.0000001, .correct = "0.0000001" },
- { .n = 0.00000009, .correct = "0.0000001" },
- { .n = 0.000000001, .correct = "0" },
- { .n = 99.99999999999999999, .correct = "100" },
- { .n = -99.99999999999999999, .correct = "-100" },
- { .n = 123.4567890123456789, .correct = "123.456789" },
- { .n = 9999.9999999, .correct = "9999.9999999" },
- { .n = -9999.9999999, .correct = "-9999.9999999" },
- { .n = 0, .correct = NULL },
- };
-
- char netdata[50], system[50];
- int i, failed = 0;
- for(i = 0; values[i].correct ; i++) {
- print_calculated_number(netdata, values[i].n);
- snprintfz(system, 49, "%0.12" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE)values[i].n);
-
- int ok = 1;
- if(strcmp(netdata, values[i].correct) != 0) {
- ok = 0;
- failed++;
- }
-
- fprintf(stderr, "'%s' (system) printed as '%s' (netdata): %s\n", system, netdata, ok?"OK":"FAILED");
- }
-
- if(failed) return 1;
- return 0;
-}
-
-static int check_rrdcalc_comparisons(void) {
- RRDCALC_STATUS a, b;
-
- // make sure calloc() sets the status to UNINITIALIZED
- memset(&a, 0, sizeof(RRDCALC_STATUS));
- if(a != RRDCALC_STATUS_UNINITIALIZED) {
- fprintf(stderr, "%s is not zero.\n", rrdcalc_status2string(RRDCALC_STATUS_UNINITIALIZED));
- return 1;
- }
-
- a = RRDCALC_STATUS_REMOVED;
- b = RRDCALC_STATUS_UNDEFINED;
- if(!(a < b)) {
- fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
- return 1;
- }
-
- a = RRDCALC_STATUS_UNDEFINED;
- b = RRDCALC_STATUS_UNINITIALIZED;
- if(!(a < b)) {
- fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
- return 1;
- }
-
- a = RRDCALC_STATUS_UNINITIALIZED;
- b = RRDCALC_STATUS_CLEAR;
- if(!(a < b)) {
- fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
- return 1;
- }
-
- a = RRDCALC_STATUS_CLEAR;
- b = RRDCALC_STATUS_RAISED;
- if(!(a < b)) {
- fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
- return 1;
- }
-
- a = RRDCALC_STATUS_RAISED;
- b = RRDCALC_STATUS_WARNING;
- if(!(a < b)) {
- fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
- return 1;
- }
-
- a = RRDCALC_STATUS_WARNING;
- b = RRDCALC_STATUS_CRITICAL;
- if(!(a < b)) {
- fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
- return 1;
- }
-
- fprintf(stderr, "RRDCALC_STATUSes are sortable.\n");
-
- return 0;
-}
-
-int check_storage_number(calculated_number n, int debug) {
- char buffer[100];
- uint32_t flags = SN_EXISTS;
-
- storage_number s = pack_storage_number(n, flags);
- calculated_number d = unpack_storage_number(s);
-
- if(!does_storage_number_exist(s)) {
- fprintf(stderr, "Exists flags missing for number " CALCULATED_NUMBER_FORMAT "!\n", n);
- return 5;
- }
-
- calculated_number ddiff = d - n;
- calculated_number dcdiff = ddiff * 100.0 / n;
-
- if(dcdiff < 0) dcdiff = -dcdiff;
-
- size_t len = (size_t)print_calculated_number(buffer, d);
- calculated_number p = str2ld(buffer, NULL);
- calculated_number pdiff = n - p;
- calculated_number pcdiff = pdiff * 100.0 / n;
- if(pcdiff < 0) pcdiff = -pcdiff;
-
- if(debug) {
- fprintf(stderr,
- CALCULATED_NUMBER_FORMAT " original\n"
- CALCULATED_NUMBER_FORMAT " packed and unpacked, (stored as 0x%08X, diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n"
- "%s printed after unpacked (%zu bytes)\n"
- CALCULATED_NUMBER_FORMAT " re-parsed from printed (diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n\n",
- n,
- d, s, ddiff, dcdiff,
- buffer, len,
- p, pdiff, pcdiff
- );
- if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %zu but it has %zu\n", buffer, len, strlen(buffer));
- if(dcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss " CALCULATED_NUMBER_FORMAT " %%\n", n, dcdiff);
- if(pcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " CALCULATED_NUMBER_FORMAT " has accuracy loss " CALCULATED_NUMBER_FORMAT " %%\n", n, pcdiff);
- }
-
- if(len != strlen(buffer)) return 1;
- if(dcdiff > ACCURACY_LOSS) return 3;
- if(pcdiff > ACCURACY_LOSS) return 4;
- return 0;
-}
-
-calculated_number storage_number_min(calculated_number n) {
- calculated_number r = 1, last;
-
- do {
- last = n;
- n /= 2.0;
- storage_number t = pack_storage_number(n, SN_EXISTS);
- r = unpack_storage_number(t);
- } while(r != 0.0 && r != last);
-
- return last;
-}
-
-void benchmark_storage_number(int loop, int multiplier) {
- int i, j;
- calculated_number n, d;
- storage_number s;
- unsigned long long user, system, total, mine, their;
-
- char buffer[100];
-
- struct rusage now, last;
-
- fprintf(stderr, "\n\nBenchmarking %d numbers, please wait...\n\n", loop);
-
- // ------------------------------------------------------------------------
-
- fprintf(stderr, "SYSTEM LONG DOUBLE SIZE: %zu bytes\n", sizeof(calculated_number));
- fprintf(stderr, "NETDATA FLOATING POINT SIZE: %zu bytes\n", sizeof(storage_number));
-
- mine = (calculated_number)sizeof(storage_number) * (calculated_number)loop;
- their = (calculated_number)sizeof(calculated_number) * (calculated_number)loop;
-
- if(mine > their) {
- fprintf(stderr, "\nNETDATA NEEDS %0.2" LONG_DOUBLE_MODIFIER " TIMES MORE MEMORY. Sorry!\n", (LONG_DOUBLE)(mine / their));
- }
- else {
- fprintf(stderr, "\nNETDATA INTERNAL FLOATING POINT ARITHMETICS NEEDS %0.2" LONG_DOUBLE_MODIFIER " TIMES LESS MEMORY.\n", (LONG_DOUBLE)(their / mine));
- }
-
- fprintf(stderr, "\nNETDATA FLOATING POINT\n");
- fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", storage_number_min(1));
- fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MAX);
- fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MIN);
- fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", -storage_number_min(1));
- fprintf(stderr, "Maximum accuracy loss: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS);
-
- // ------------------------------------------------------------------------
-
- fprintf(stderr, "INTERNAL LONG DOUBLE PRINTING: ");
- getrusage(RUSAGE_SELF, &last);
-
- // do the job
- for(j = 1; j < 11 ;j++) {
- n = STORAGE_NUMBER_POSITIVE_MIN * j;
-
- for(i = 0; i < loop ;i++) {
- n *= multiplier;
- if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
-
- print_calculated_number(buffer, n);
- }
- }
-
- getrusage(RUSAGE_SELF, &now);
- user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
- system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
- total = user + system;
- mine = total;
-
- fprintf(stderr, "user %0.5" LONG_DOUBLE_MODIFIER", system %0.5" LONG_DOUBLE_MODIFIER ", total %0.5" LONG_DOUBLE_MODIFIER "\n", (LONG_DOUBLE)(user / 1000000.0), (LONG_DOUBLE)(system / 1000000.0), (LONG_DOUBLE)(total / 1000000.0));
-
- // ------------------------------------------------------------------------
-
- fprintf(stderr, "SYSTEM LONG DOUBLE PRINTING: ");
- getrusage(RUSAGE_SELF, &last);
-
- // do the job
- for(j = 1; j < 11 ;j++) {
- n = STORAGE_NUMBER_POSITIVE_MIN * j;
-
- for(i = 0; i < loop ;i++) {
- n *= multiplier;
- if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
- snprintfz(buffer, 100, CALCULATED_NUMBER_FORMAT, n);
- }
- }
-
- getrusage(RUSAGE_SELF, &now);
- user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
- system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
- total = user + system;
- their = total;
-
- fprintf(stderr, "user %0.5" LONG_DOUBLE_MODIFIER ", system %0.5" LONG_DOUBLE_MODIFIER ", total %0.5" LONG_DOUBLE_MODIFIER "\n", (LONG_DOUBLE)(user / 1000000.0), (LONG_DOUBLE)(system / 1000000.0), (LONG_DOUBLE)(total / 1000000.0));
-
- if(mine > total) {
- fprintf(stderr, "NETDATA CODE IS SLOWER %0.2" LONG_DOUBLE_MODIFIER " %%\n", (LONG_DOUBLE)(mine * 100.0 / their - 100.0));
- }
- else {
- fprintf(stderr, "NETDATA CODE IS F A S T E R %0.2" LONG_DOUBLE_MODIFIER " %%\n", (LONG_DOUBLE)(their * 100.0 / mine - 100.0));
- }
-
- // ------------------------------------------------------------------------
-
- fprintf(stderr, "\nINTERNAL LONG DOUBLE PRINTING WITH PACK / UNPACK: ");
- getrusage(RUSAGE_SELF, &last);
-
- // do the job
- for(j = 1; j < 11 ;j++) {
- n = STORAGE_NUMBER_POSITIVE_MIN * j;
-
- for(i = 0; i < loop ;i++) {
- n *= multiplier;
- if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
-
- s = pack_storage_number(n, 1);
- d = unpack_storage_number(s);
- print_calculated_number(buffer, d);
- }
- }
-
- getrusage(RUSAGE_SELF, &now);
- user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
- system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
- total = user + system;
- mine = total;
-
- fprintf(stderr, "user %0.5" LONG_DOUBLE_MODIFIER ", system %0.5" LONG_DOUBLE_MODIFIER ", total %0.5" LONG_DOUBLE_MODIFIER "\n", (LONG_DOUBLE)(user / 1000000.0), (LONG_DOUBLE)(system / 1000000.0), (LONG_DOUBLE)(total / 1000000.0));
-
- if(mine > their) {
- fprintf(stderr, "WITH PACKING UNPACKING NETDATA CODE IS SLOWER %0.2" LONG_DOUBLE_MODIFIER " %%\n", (LONG_DOUBLE)(mine * 100.0 / their - 100.0));
- }
- else {
- fprintf(stderr, "EVEN WITH PACKING AND UNPACKING, NETDATA CODE IS F A S T E R %0.2" LONG_DOUBLE_MODIFIER " %%\n", (LONG_DOUBLE)(their * 100.0 / mine - 100.0));
- }
-
- // ------------------------------------------------------------------------
-
-}
-
-static int check_storage_number_exists() {
- uint32_t flags = SN_EXISTS;
-
-
- for(flags = 0; flags < 7 ; flags++) {
- if(get_storage_number_flags(flags << 24) != flags << 24) {
- fprintf(stderr, "Flag 0x%08x is not checked correctly. It became 0x%08x\n", flags << 24, get_storage_number_flags(flags << 24));
- return 1;
- }
- }
-
- flags = SN_EXISTS;
- calculated_number n = 0.0;
-
- storage_number s = pack_storage_number(n, flags);
- calculated_number d = unpack_storage_number(s);
- if(get_storage_number_flags(s) != flags) {
- fprintf(stderr, "Wrong flags. Given %08x, Got %08x!\n", flags, get_storage_number_flags(s));
- return 1;
- }
- if(n != d) {
- fprintf(stderr, "Wrong number returned. Expected " CALCULATED_NUMBER_FORMAT ", returned " CALCULATED_NUMBER_FORMAT "!\n", n, d);
- return 1;
- }
-
- return 0;
-}
-
-int unit_test_storage()
-{
- if(check_storage_number_exists()) return 0;
-
- calculated_number c, a = 0;
- int i, j, g, r = 0;
-
- for(g = -1; g <= 1 ; g++) {
- a = 0;
-
- if(!g) continue;
-
- for(j = 0; j < 9 ;j++) {
- a += 0.0000001;
- c = a * g;
- for(i = 0; i < 21 ;i++, c *= 10) {
- if(c > 0 && c < STORAGE_NUMBER_POSITIVE_MIN) continue;
- if(c < 0 && c > STORAGE_NUMBER_NEGATIVE_MAX) continue;
-
- if(check_storage_number(c, 1)) return 1;
- }
- }
- }
-
- benchmark_storage_number(1000000, 2);
- return r;
-}
-
-int unit_test_str2ld() {
- char *values[] = {
- "1.2345678", "-35.6", "0.00123", "23842384234234.2", ".1", "1.2e-10",
- "hello", "1wrong", "nan", "inf", NULL
- };
-
- int i;
- for(i = 0; values[i] ; i++) {
- char *e_mine = "hello", *e_sys = "world";
- LONG_DOUBLE mine = str2ld(values[i], &e_mine);
- LONG_DOUBLE sys = strtold(values[i], &e_sys);
-
- if(isnan(mine)) {
- if(!isnan(sys)) {
- fprintf(stderr, "Value '%s' is parsed as %" LONG_DOUBLE_MODIFIER ", but system believes it is %" LONG_DOUBLE_MODIFIER ".\n", values[i], mine, sys);
- return -1;
- }
- }
- else if(isinf(mine)) {
- if(!isinf(sys)) {
- fprintf(stderr, "Value '%s' is parsed as %" LONG_DOUBLE_MODIFIER ", but system believes it is %" LONG_DOUBLE_MODIFIER ".\n", values[i], mine, sys);
- return -1;
- }
- }
- else if(mine != sys && abs(mine-sys) > 0.000001) {
- fprintf(stderr, "Value '%s' is parsed as %" LONG_DOUBLE_MODIFIER ", but system believes it is %" LONG_DOUBLE_MODIFIER ", delta %" LONG_DOUBLE_MODIFIER ".\n", values[i], mine, sys, sys-mine);
- return -1;
- }
-
- if(e_mine != e_sys) {
- fprintf(stderr, "Value '%s' is parsed correctly, but endptr is not right\n", values[i]);
- return -1;
- }
-
- fprintf(stderr, "str2ld() parsed value '%s' exactly the same way with strtold(), returned %" LONG_DOUBLE_MODIFIER " vs %" LONG_DOUBLE_MODIFIER "\n", values[i], mine, sys);
- }
-
- return 0;
-}
-
-int unit_test_buffer() {
- BUFFER *wb = buffer_create(1);
- char string[2048 + 1];
- char final[9000 + 1];
- int i;
-
- for(i = 0; i < 2048; i++)
- string[i] = (char)((i % 24) + 'a');
- string[2048] = '\0';
-
- const char *fmt = "string1: %s\nstring2: %s\nstring3: %s\nstring4: %s";
- buffer_sprintf(wb, fmt, string, string, string, string);
- snprintfz(final, 9000, fmt, string, string, string, string);
-
- const char *s = buffer_tostring(wb);
-
- if(buffer_strlen(wb) != strlen(final) || strcmp(s, final) != 0) {
- fprintf(stderr, "\nbuffer_sprintf() is faulty.\n");
- fprintf(stderr, "\nstring : %s (length %zu)\n", string, strlen(string));
- fprintf(stderr, "\nbuffer : %s (length %zu)\n", s, buffer_strlen(wb));
- fprintf(stderr, "\nexpected: %s (length %zu)\n", final, strlen(final));
- buffer_free(wb);
- return -1;
- }
-
- fprintf(stderr, "buffer_sprintf() works as expected.\n");
- buffer_free(wb);
- return 0;
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-struct feed_values {
- unsigned long long microseconds;
- collected_number value;
-};
-
-struct test {
- char name[100];
- char description[1024];
-
- int update_every;
- unsigned long long multiplier;
- unsigned long long divisor;
- RRD_ALGORITHM algorithm;
-
- unsigned long feed_entries;
- unsigned long result_entries;
- struct feed_values *feed;
- calculated_number *results;
-
- collected_number *feed2;
- calculated_number *results2;
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test1
-// test absolute values stored
-
-struct feed_values test1_feed[] = {
- { 0, 10 },
- { 1000000, 20 },
- { 1000000, 30 },
- { 1000000, 40 },
- { 1000000, 50 },
- { 1000000, 60 },
- { 1000000, 70 },
- { 1000000, 80 },
- { 1000000, 90 },
- { 1000000, 100 },
-};
-
-calculated_number test1_results[] = {
- 20, 30, 40, 50, 60, 70, 80, 90, 100
-};
-
-struct test test1 = {
- "test1", // name
- "test absolute values stored at exactly second boundaries",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_ABSOLUTE, // algorithm
- 10, // feed entries
- 9, // result entries
- test1_feed, // feed
- test1_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test2
-// test absolute values stored in the middle of second boundaries
-
-struct feed_values test2_feed[] = {
- { 500000, 10 },
- { 1000000, 20 },
- { 1000000, 30 },
- { 1000000, 40 },
- { 1000000, 50 },
- { 1000000, 60 },
- { 1000000, 70 },
- { 1000000, 80 },
- { 1000000, 90 },
- { 1000000, 100 },
-};
-
-calculated_number test2_results[] = {
- 20, 30, 40, 50, 60, 70, 80, 90, 100
-};
-
-struct test test2 = {
- "test2", // name
- "test absolute values stored in the middle of second boundaries",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_ABSOLUTE, // algorithm
- 10, // feed entries
- 9, // result entries
- test2_feed, // feed
- test2_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test3
-
-struct feed_values test3_feed[] = {
- { 0, 10 },
- { 1000000, 20 },
- { 1000000, 30 },
- { 1000000, 40 },
- { 1000000, 50 },
- { 1000000, 60 },
- { 1000000, 70 },
- { 1000000, 80 },
- { 1000000, 90 },
- { 1000000, 100 },
-};
-
-calculated_number test3_results[] = {
- 10, 10, 10, 10, 10, 10, 10, 10, 10
-};
-
-struct test test3 = {
- "test3", // name
- "test incremental values stored at exactly second boundaries",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test3_feed, // feed
- test3_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test4
-
-struct feed_values test4_feed[] = {
- { 500000, 10 },
- { 1000000, 20 },
- { 1000000, 30 },
- { 1000000, 40 },
- { 1000000, 50 },
- { 1000000, 60 },
- { 1000000, 70 },
- { 1000000, 80 },
- { 1000000, 90 },
- { 1000000, 100 },
-};
-
-calculated_number test4_results[] = {
- 10, 10, 10, 10, 10, 10, 10, 10, 10
-};
-
-struct test test4 = {
- "test4", // name
- "test incremental values stored in the middle of second boundaries",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test4_feed, // feed
- test4_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test5
-
-struct feed_values test5_feed[] = {
- { 500000, 1000 },
- { 1000000, 2000 },
- { 1000000, 2000 },
- { 1000000, 2000 },
- { 1000000, 3000 },
- { 1000000, 2000 },
- { 1000000, 2000 },
- { 1000000, 2000 },
- { 1000000, 2000 },
- { 1000000, 2000 },
-};
-
-calculated_number test5_results[] = {
- 1000, 500, 0, 500, 500, 0, 0, 0, 0
-};
-
-struct test test5 = {
- "test5", // name
- "test incremental values ups and downs",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test5_feed, // feed
- test5_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test6
-
-struct feed_values test6_feed[] = {
- { 250000, 1000 },
- { 250000, 2000 },
- { 250000, 3000 },
- { 250000, 4000 },
- { 250000, 5000 },
- { 250000, 6000 },
- { 250000, 7000 },
- { 250000, 8000 },
- { 250000, 9000 },
- { 250000, 10000 },
- { 250000, 11000 },
- { 250000, 12000 },
- { 250000, 13000 },
- { 250000, 14000 },
- { 250000, 15000 },
- { 250000, 16000 },
-};
-
-calculated_number test6_results[] = {
- 4000, 4000, 4000, 4000
-};
-
-struct test test6 = {
- "test6", // name
- "test incremental values updated within the same second",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 16, // feed entries
- 4, // result entries
- test6_feed, // feed
- test6_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test7
-
-struct feed_values test7_feed[] = {
- { 500000, 1000 },
- { 2000000, 2000 },
- { 2000000, 3000 },
- { 2000000, 4000 },
- { 2000000, 5000 },
- { 2000000, 6000 },
- { 2000000, 7000 },
- { 2000000, 8000 },
- { 2000000, 9000 },
- { 2000000, 10000 },
-};
-
-calculated_number test7_results[] = {
- 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500
-};
-
-struct test test7 = {
- "test7", // name
- "test incremental values updated in long durations",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 18, // result entries
- test7_feed, // feed
- test7_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test8
-
-struct feed_values test8_feed[] = {
- { 500000, 1000 },
- { 2000000, 2000 },
- { 2000000, 3000 },
- { 2000000, 4000 },
- { 2000000, 5000 },
- { 2000000, 6000 },
-};
-
-calculated_number test8_results[] = {
- 1250, 2000, 2250, 3000, 3250, 4000, 4250, 5000, 5250, 6000
-};
-
-struct test test8 = {
- "test8", // name
- "test absolute values updated in long durations",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_ABSOLUTE, // algorithm
- 6, // feed entries
- 10, // result entries
- test8_feed, // feed
- test8_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test9
-
-struct feed_values test9_feed[] = {
- { 250000, 1000 },
- { 250000, 2000 },
- { 250000, 3000 },
- { 250000, 4000 },
- { 250000, 5000 },
- { 250000, 6000 },
- { 250000, 7000 },
- { 250000, 8000 },
- { 250000, 9000 },
- { 250000, 10000 },
- { 250000, 11000 },
- { 250000, 12000 },
- { 250000, 13000 },
- { 250000, 14000 },
- { 250000, 15000 },
- { 250000, 16000 },
-};
-
-calculated_number test9_results[] = {
- 4000, 8000, 12000, 16000
-};
-
-struct test test9 = {
- "test9", // name
- "test absolute values updated within the same second",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_ABSOLUTE, // algorithm
- 16, // feed entries
- 4, // result entries
- test9_feed, // feed
- test9_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test10
-
-struct feed_values test10_feed[] = {
- { 500000, 1000 },
- { 600000, 1000 + 600 },
- { 200000, 1600 + 200 },
- { 1000000, 1800 + 1000 },
- { 200000, 2800 + 200 },
- { 2000000, 3000 + 2000 },
- { 600000, 5000 + 600 },
- { 400000, 5600 + 400 },
- { 900000, 6000 + 900 },
- { 1000000, 6900 + 1000 },
-};
-
-calculated_number test10_results[] = {
- 1000, 1000, 1000, 1000, 1000, 1000, 1000
-};
-
-struct test test10 = {
- "test10", // name
- "test incremental values updated in short and long durations",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 7, // result entries
- test10_feed, // feed
- test10_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test11
-
-struct feed_values test11_feed[] = {
- { 0, 10 },
- { 1000000, 20 },
- { 1000000, 30 },
- { 1000000, 40 },
- { 1000000, 50 },
- { 1000000, 60 },
- { 1000000, 70 },
- { 1000000, 80 },
- { 1000000, 90 },
- { 1000000, 100 },
-};
-
-collected_number test11_feed2[] = {
- 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
-};
-
-calculated_number test11_results[] = {
- 50, 50, 50, 50, 50, 50, 50, 50, 50
-};
-
-calculated_number test11_results2[] = {
- 50, 50, 50, 50, 50, 50, 50, 50, 50
-};
-
-struct test test11 = {
- "test11", // name
- "test percentage-of-incremental-row with equal values",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test11_feed, // feed
- test11_results, // results
- test11_feed2, // feed2
- test11_results2 // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test12
-
-struct feed_values test12_feed[] = {
- { 0, 10 },
- { 1000000, 20 },
- { 1000000, 30 },
- { 1000000, 40 },
- { 1000000, 50 },
- { 1000000, 60 },
- { 1000000, 70 },
- { 1000000, 80 },
- { 1000000, 90 },
- { 1000000, 100 },
-};
-
-collected_number test12_feed2[] = {
- 10*3, 20*3, 30*3, 40*3, 50*3, 60*3, 70*3, 80*3, 90*3, 100*3
-};
-
-calculated_number test12_results[] = {
- 25, 25, 25, 25, 25, 25, 25, 25, 25
-};
-
-calculated_number test12_results2[] = {
- 75, 75, 75, 75, 75, 75, 75, 75, 75
-};
-
-struct test test12 = {
- "test12", // name
- "test percentage-of-incremental-row with equal values",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test12_feed, // feed
- test12_results, // results
- test12_feed2, // feed2
- test12_results2 // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test13
-
-struct feed_values test13_feed[] = {
- { 500000, 1000 },
- { 600000, 1000 + 600 },
- { 200000, 1600 + 200 },
- { 1000000, 1800 + 1000 },
- { 200000, 2800 + 200 },
- { 2000000, 3000 + 2000 },
- { 600000, 5000 + 600 },
- { 400000, 5600 + 400 },
- { 900000, 6000 + 900 },
- { 1000000, 6900 + 1000 },
-};
-
-calculated_number test13_results[] = {
- 83.3333300, 100, 100, 100, 100, 100, 100
-};
-
-struct test test13 = {
- "test13", // name
- "test incremental values updated in short and long durations",
- 1, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm
- 10, // feed entries
- 7, // result entries
- test13_feed, // feed
- test13_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test14
-
-struct feed_values test14_feed[] = {
- { 0, 0x015397dc42151c41ULL },
- { 13573000, 0x015397e612e3ff5dULL },
- { 29969000, 0x015397f905ecdaa8ULL },
- { 29958000, 0x0153980c2a6cb5e4ULL },
- { 30054000, 0x0153981f4032fb83ULL },
- { 34952000, 0x015398355efadaccULL },
- { 25046000, 0x01539845ba4b09f8ULL },
- { 29947000, 0x0153985948bf381dULL },
- { 30054000, 0x0153986c5b9c27e2ULL },
- { 29942000, 0x0153987f888982d0ULL },
-};
-
-calculated_number test14_results[] = {
- 23.1383300, 21.8515600, 21.8804600, 21.7788000, 22.0112200, 22.4386100, 22.0906100, 21.9150800
-};
-
-struct test test14 = {
- "test14", // name
- "issue #981 with real data",
- 30, // update_every
- 8, // multiplier
- 1000000000, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 8, // result entries
- test14_feed, // feed
- test14_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-struct feed_values test14b_feed[] = {
- { 0, 0 },
- { 13573000, 13573000 },
- { 29969000, 13573000 + 29969000 },
- { 29958000, 13573000 + 29969000 + 29958000 },
- { 30054000, 13573000 + 29969000 + 29958000 + 30054000 },
- { 34952000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 },
- { 25046000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 },
- { 29947000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 + 29947000 },
- { 30054000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 + 29947000 + 30054000 },
- { 29942000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 + 29947000 + 30054000 + 29942000 },
-};
-
-calculated_number test14b_results[] = {
- 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000
-};
-
-struct test test14b = {
- "test14b", // name
- "issue #981 with dummy data",
- 30, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 8, // result entries
- test14b_feed, // feed
- test14b_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-struct feed_values test14c_feed[] = {
- { 29000000, 29000000 },
- { 1000000, 29000000 + 1000000 },
- { 30000000, 29000000 + 1000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
- { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
-};
-
-calculated_number test14c_results[] = {
- 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000
-};
-
-struct test test14c = {
- "test14c", // name
- "issue #981 with dummy data, checking for late start",
- 30, // update_every
- 1, // multiplier
- 1, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test14c_feed, // feed
- test14c_results, // results
- NULL, // feed2
- NULL // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-// test15
-
-struct feed_values test15_feed[] = {
- { 0, 1068066388 },
- { 1008752, 1068822698 },
- { 993809, 1069573072 },
- { 995911, 1070324135 },
- { 1014562, 1071078166 },
- { 994684, 1071831349 },
- { 993128, 1072235739 },
- { 1010332, 1072958871 },
- { 1003394, 1073707019 },
- { 995201, 1074460255 },
-};
-
-collected_number test15_feed2[] = {
- 178825286, 178825286, 178825286, 178825286, 178825498, 178825498, 179165652, 179202964, 179203282, 179204130
-};
-
-calculated_number test15_results[] = {
- 5857.4080000, 5898.4540000, 5891.6590000, 5806.3160000, 5914.2640000, 3202.2630000, 5589.6560000, 5822.5260000, 5911.7520000
-};
-
-calculated_number test15_results2[] = {
- 0.0000000, 0.0000000, 0.0024944, 1.6324779, 0.0212777, 2655.1890000, 290.5387000, 5.6733610, 6.5960220
-};
-
-struct test test15 = {
- "test15", // name
- "test incremental with 2 dimensions",
- 1, // update_every
- 8, // multiplier
- 1024, // divisor
- RRD_ALGORITHM_INCREMENTAL, // algorithm
- 10, // feed entries
- 9, // result entries
- test15_feed, // feed
- test15_results, // results
- test15_feed2, // feed2
- test15_results2 // results2
-};
-
-// --------------------------------------------------------------------------------------------------------------------
-
-int run_test(struct test *test)
-{
- fprintf(stderr, "\nRunning test '%s':\n%s\n", test->name, test->description);
-
- default_rrd_memory_mode = RRD_MEMORY_MODE_ALLOC;
- default_rrd_update_every = test->update_every;
-
- char name[101];
- snprintfz(name, 100, "unittest-%s", test->name);
-
- // create the chart
- RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", "unittest", NULL, 1
- , test->update_every, RRDSET_TYPE_LINE);
- RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm);
-
- RRDDIM *rd2 = NULL;
- if(test->feed2)
- rd2 = rrddim_add(st, "dim2", NULL, test->multiplier, test->divisor, test->algorithm);
-
- rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
-
- // feed it with the test data
- time_t time_now = 0, time_start = now_realtime_sec();
- unsigned long c;
- collected_number last = 0;
- for(c = 0; c < test->feed_entries; c++) {
- if(debug_flags) fprintf(stderr, "\n\n");
-
- if(c) {
- time_now += test->feed[c].microseconds;
- fprintf(stderr, " > %s: feeding position %lu, after %0.3f seconds (%0.3f seconds from start), delta " CALCULATED_NUMBER_FORMAT ", rate " CALCULATED_NUMBER_FORMAT "\n",
- test->name, c+1,
- (float)test->feed[c].microseconds / 1000000.0,
- (float)time_now / 1000000.0,
- ((calculated_number)test->feed[c].value - (calculated_number)last) * (calculated_number)test->multiplier / (calculated_number)test->divisor,
- (((calculated_number)test->feed[c].value - (calculated_number)last) * (calculated_number)test->multiplier / (calculated_number)test->divisor) / (calculated_number)test->feed[c].microseconds * (calculated_number)1000000);
-
- // rrdset_next_usec_unfiltered(st, test->feed[c].microseconds);
- st->usec_since_last_update = test->feed[c].microseconds;
- }
- else {
- fprintf(stderr, " > %s: feeding position %lu\n", test->name, c+1);
- }
-
- fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd->name, test->feed[c].value);
- rrddim_set(st, "dim1", test->feed[c].value);
- last = test->feed[c].value;
-
- if(rd2) {
- fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd2->name, test->feed2[c]);
- rrddim_set(st, "dim2", test->feed2[c]);
- }
-
- rrdset_done(st);
-
- // align the first entry to second boundary
- if(!c) {
- fprintf(stderr, " > %s: fixing first collection time to be %llu microseconds to second boundary\n", test->name, test->feed[c].microseconds);
- rd->last_collected_time.tv_usec = st->last_collected_time.tv_usec = st->last_updated.tv_usec = test->feed[c].microseconds;
- // time_start = st->last_collected_time.tv_sec;
- }
- }
-
- // check the result
- int errors = 0;
-
- if(st->counter != test->result_entries) {
- fprintf(stderr, " %s stored %zu entries, but we were expecting %lu, ### E R R O R ###\n", test->name, st->counter, test->result_entries);
- errors++;
- }
-
- unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries;
- for(c = 0 ; c < max ; c++) {
- calculated_number v = unpack_storage_number(rd->values[c]);
- calculated_number n = test->results[c];
- int same = (calculated_number_round(v * 10000000.0) == calculated_number_round(n * 10000000.0))?1:0;
- fprintf(stderr, " %s/%s: checking position %lu (at %lu secs), expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n",
- test->name, rd->name, c+1,
- (rrdset_first_entry_t(st) + c * st->update_every) - time_start,
- n, v, (same)?"OK":"### E R R O R ###");
-
- if(!same) errors++;
-
- if(rd2) {
- v = unpack_storage_number(rd2->values[c]);
- n = test->results2[c];
- same = (calculated_number_round(v * 10000000.0) == calculated_number_round(n * 10000000.0))?1:0;
- fprintf(stderr, " %s/%s: checking position %lu (at %lu secs), expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n",
- test->name, rd2->name, c+1,
- (rrdset_first_entry_t(st) + c * st->update_every) - time_start,
- n, v, (same)?"OK":"### E R R O R ###");
- if(!same) errors++;
- }
- }
-
- return errors;
-}
-
-static int test_variable_renames(void) {
- fprintf(stderr, "Creating chart\n");
- RRDSET *st = rrdset_create_localhost("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", "unittest", NULL, 1, 1, RRDSET_TYPE_LINE);
- fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name);
-
- fprintf(stderr, "Creating dimension DIM1\n");
- RRDDIM *rd1 = rrddim_add(st, "DIM1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd1->id, rd1->name);
-
- fprintf(stderr, "Creating dimension DIM2\n");
- RRDDIM *rd2 = rrddim_add(st, "DIM2", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd2->id, rd2->name);
-
- fprintf(stderr, "Renaming chart to CHARTNAME1\n");
- rrdset_set_name(st, "CHARTNAME1");
- fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", st->id, st->name);
-
- fprintf(stderr, "Renaming chart to CHARTNAME2\n");
- rrdset_set_name(st, "CHARTNAME2");
- fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", st->id, st->name);
-
- fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME1\n");
- rrddim_set_name(st, rd1, "DIM1NAME1");
- fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd1->id, rd1->name);
-
- fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME2\n");
- rrddim_set_name(st, rd1, "DIM1NAME2");
- fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd1->id, rd1->name);
-
- fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME1\n");
- rrddim_set_name(st, rd2, "DIM2NAME1");
- fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name);
-
- fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME2\n");
- rrddim_set_name(st, rd2, "DIM2NAME2");
- fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rd2->id, rd2->name);
-
- BUFFER *buf = buffer_create(1);
- health_api_v1_chart_variables2json(st, buf);
- fprintf(stderr, "%s", buffer_tostring(buf));
- buffer_free(buf);
- return 1;
-}
-
-int run_all_mockup_tests(void)
-{
- if(check_number_printing())
- return 1;
-
- if(check_rrdcalc_comparisons())
- return 1;
-
- if(!test_variable_renames())
- return 1;
-
- if(run_test(&test1))
- return 1;
-
- if(run_test(&test2))
- return 1;
-
- if(run_test(&test3))
- return 1;
-
- if(run_test(&test4))
- return 1;
-
- if(run_test(&test5))
- return 1;
-
- if(run_test(&test6))
- return 1;
-
- if(run_test(&test7))
- return 1;
-
- if(run_test(&test8))
- return 1;
-
- if(run_test(&test9))
- return 1;
-
- if(run_test(&test10))
- return 1;
-
- if(run_test(&test11))
- return 1;
-
- if(run_test(&test12))
- return 1;
-
- if(run_test(&test13))
- return 1;
-
- if(run_test(&test14))
- return 1;
-
- if(run_test(&test14b))
- return 1;
-
- if(run_test(&test14c))
- return 1;
-
- if(run_test(&test15))
- return 1;
-
-
-
- return 0;
-}
-
-int unit_test(long delay, long shift)
-{
- static int repeat = 0;
- repeat++;
-
- char name[101];
- snprintfz(name, 100, "unittest-%d-%ld-%ld", repeat, delay, shift);
-
- //debug_flags = 0xffffffff;
- default_rrd_memory_mode = RRD_MEMORY_MODE_ALLOC;
- default_rrd_update_every = 1;
-
- int do_abs = 1;
- int do_inc = 1;
- int do_abst = 0;
- int do_absi = 0;
-
- RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", "unittest", NULL, 1, 1
- , RRDSET_TYPE_LINE);
- rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
-
- RRDDIM *rdabs = NULL;
- RRDDIM *rdinc = NULL;
- RRDDIM *rdabst = NULL;
- RRDDIM *rdabsi = NULL;
-
- if(do_abs) rdabs = rrddim_add(st, "absolute", "absolute", 1, 1, RRD_ALGORITHM_ABSOLUTE);
- if(do_inc) rdinc = rrddim_add(st, "incremental", "incremental", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- if(do_abst) rdabst = rrddim_add(st, "percentage-of-absolute-row", "percentage-of-absolute-row", 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL);
- if(do_absi) rdabsi = rrddim_add(st, "percentage-of-incremental-row", "percentage-of-incremental-row", 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
-
- long increment = 1000;
- collected_number i = 0;
-
- unsigned long c, dimensions = 0;
- RRDDIM *rd;
- for(rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
-
- for(c = 0; c < 20 ;c++) {
- i += increment;
-
- fprintf(stderr, "\n\nLOOP = %lu, DELAY = %ld, VALUE = " COLLECTED_NUMBER_FORMAT "\n", c, delay, i);
- if(c) {
- // rrdset_next_usec_unfiltered(st, delay);
- st->usec_since_last_update = delay;
- }
- if(do_abs) rrddim_set(st, "absolute", i);
- if(do_inc) rrddim_set(st, "incremental", i);
- if(do_abst) rrddim_set(st, "percentage-of-absolute-row", i);
- if(do_absi) rrddim_set(st, "percentage-of-incremental-row", i);
-
- if(!c) {
- now_realtime_timeval(&st->last_collected_time);
- st->last_collected_time.tv_usec = shift;
- }
-
- // prevent it from deleting the dimensions
- for(rd = st->dimensions ; rd ; rd = rd->next)
- rd->last_collected_time.tv_sec = st->last_collected_time.tv_sec;
-
- rrdset_done(st);
- }
-
- unsigned long oincrement = increment;
- increment = increment * st->update_every * 1000000 / delay;
- fprintf(stderr, "\n\nORIGINAL INCREMENT: %lu, INCREMENT %ld, DELAY %ld, SHIFT %ld\n", oincrement * 10, increment * 10, delay, shift);
-
- int ret = 0;
- storage_number sn;
- calculated_number cn, v;
- for(c = 0 ; c < st->counter ; c++) {
- fprintf(stderr, "\nPOSITION: c = %lu, EXPECTED VALUE %lu\n", c, (oincrement + c * increment + increment * (1000000 - shift) / 1000000 )* 10);
-
- for(rd = st->dimensions ; rd ; rd = rd->next) {
- sn = rd->values[c];
- cn = unpack_storage_number(sn);
- fprintf(stderr, "\t %s " CALCULATED_NUMBER_FORMAT " (PACKED AS " STORAGE_NUMBER_FORMAT ") -> ", rd->id, cn, sn);
-
- if(rd == rdabs) v =
- ( oincrement
- // + (increment * (1000000 - shift) / 1000000)
- + (c + 1) * increment
- );
-
- else if(rd == rdinc) v = (c?(increment):(increment * (1000000 - shift) / 1000000));
- else if(rd == rdabst) v = oincrement / dimensions / 10;
- else if(rd == rdabsi) v = oincrement / dimensions / 10;
- else v = 0;
-
- if(v == cn) fprintf(stderr, "passed.\n");
- else {
- fprintf(stderr, "ERROR! (expected " CALCULATED_NUMBER_FORMAT ")\n", v);
- ret = 1;
- }
- }
- }
-
- if(ret)
- fprintf(stderr, "\n\nUNIT TEST(%ld, %ld) FAILED\n\n", delay, shift);
-
- return ret;
-}
diff --git a/src/unit_test.h b/src/unit_test.h
deleted file mode 100644
index 68ed61fcb..000000000
--- a/src/unit_test.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef NETDATA_UNIT_TEST_H
-#define NETDATA_UNIT_TEST_H 1
-
-extern int unit_test_storage(void);
-extern int unit_test(long delay, long shift);
-extern int run_all_mockup_tests(void);
-extern int unit_test_str2ld(void);
-extern int unit_test_buffer(void);
-
-#endif /* NETDATA_UNIT_TEST_H */
diff --git a/src/url.c b/src/url.c
deleted file mode 100644
index 6be4d9648..000000000
--- a/src/url.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "common.h"
-
-// ----------------------------------------------------------------------------
-// URL encode / decode
-// code from: http://www.geekhideout.com/urlcode.shtml
-
-/* Converts a hex character to its integer value */
-char from_hex(char ch) {
- return (char)(isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10);
-}
-
-/* Converts an integer value to its hex character*/
-char to_hex(char code) {
- static char hex[] = "0123456789abcdef";
- return hex[code & 15];
-}
-
-/* Returns a url-encoded version of str */
-/* IMPORTANT: be sure to free() the returned string after use */
-char *url_encode(char *str) {
- char *buf, *pbuf;
-
- pbuf = buf = mallocz(strlen(str) * 3 + 1);
-
- while (*str) {
- if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~')
- *pbuf++ = *str;
-
- else if (*str == ' ')
- *pbuf++ = '+';
-
- else
- *pbuf++ = '%', *pbuf++ = to_hex(*str >> 4), *pbuf++ = to_hex(*str & 15);
-
- str++;
- }
- *pbuf = '\0';
-
- pbuf = strdupz(buf);
- freez(buf);
- return pbuf;
-}
-
-/* Returns a url-decoded version of str */
-/* IMPORTANT: be sure to free() the returned string after use */
-char *url_decode(char *str) {
- size_t size = strlen(str) + 1;
-
- char *buf = mallocz(size);
- return url_decode_r(buf, str, size);
-}
-
-char *url_decode_r(char *to, char *url, size_t size) {
- char *s = url, // source
- *d = to, // destination
- *e = &to[size - 1]; // destination end
-
- while(*s && d < e) {
- if(unlikely(*s == '%')) {
- if(likely(s[1] && s[2])) {
- *d++ = from_hex(s[1]) << 4 | from_hex(s[2]);
- s += 2;
- }
- }
- else if(unlikely(*s == '+'))
- *d++ = ' ';
-
- else
- *d++ = *s;
-
- s++;
- }
-
- *d = '\0';
-
- return to;
-}
diff --git a/src/url.h b/src/url.h
deleted file mode 100644
index fa44d49a8..000000000
--- a/src/url.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef NETDATA_URL_H
-#define NETDATA_URL_H 1
-
-// ----------------------------------------------------------------------------
-// URL encode / decode
-// code from: http://www.geekhideout.com/urlcode.shtml
-
-/* Converts a hex character to its integer value */
-extern char from_hex(char ch);
-
-/* Converts an integer value to its hex character*/
-extern char to_hex(char code);
-
-/* Returns a url-encoded version of str */
-/* IMPORTANT: be sure to free() the returned string after use */
-extern char *url_encode(char *str);
-
-/* Returns a url-decoded version of str */
-/* IMPORTANT: be sure to free() the returned string after use */
-extern char *url_decode(char *str);
-
-extern char *url_decode_r(char *to, char *url, size_t size);
-
-#endif /* NETDATA_URL_H */
diff --git a/src/web_api_old.c b/src/web_api_old.c
deleted file mode 100644
index 373e7e9f8..000000000
--- a/src/web_api_old.c
+++ /dev/null
@@ -1,237 +0,0 @@
-#include "common.h"
-
-int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type) {
- if(!url || !*url) {
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Incomplete request.");
- return 400;
- }
-
- RRDSET *st = NULL;
-
- char *args = strchr(url, '?');
- if(args) {
- *args='\0';
- args = &args[1];
- }
-
- // get the name of the data to show
- char *tok = mystrsep(&url, "/");
- if(!tok) tok = "";
-
- // do we have such a data set?
- if(*tok) {
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
- st = rrdset_find_byname(host, tok);
- if(!st) st = rrdset_find(host, tok);
- }
-
- if(!st) {
- // we don't have it
- // try to send a file with that name
- buffer_flush(w->response.data);
- return(mysendfile(w, tok));
- }
-
- // we have it
- debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok);
-
- // how many entries does the client want?
- int lines = (int)st->entries;
- int group_count = 1;
- time_t after = 0, before = 0;
- int group_method = GROUP_AVERAGE;
- int nonzero = 0;
-
- if(url) {
- // parse the lines required
- tok = mystrsep(&url, "/");
- if(tok) lines = str2i(tok);
- if(lines < 1) lines = 1;
- }
- if(url) {
- // parse the group count required
- tok = mystrsep(&url, "/");
- if(tok && *tok) group_count = str2i(tok);
- if(group_count < 1) group_count = 1;
- //if(group_count > save_history / 20) group_count = save_history / 20;
- }
- if(url) {
- // parse the grouping method required
- tok = mystrsep(&url, "/");
- if(tok && *tok) {
- if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
- else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
- else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
- else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
- }
- }
- if(url) {
- // parse after time
- tok = mystrsep(&url, "/");
- if(tok && *tok) after = str2ul(tok);
- if(after < 0) after = 0;
- }
- if(url) {
- // parse before time
- tok = mystrsep(&url, "/");
- if(tok && *tok) before = str2ul(tok);
- if(before < 0) before = 0;
- }
- if(url) {
- // parse nonzero
- tok = mystrsep(&url, "/");
- if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
- }
-
- w->response.data->contenttype = CT_APPLICATION_JSON;
- buffer_flush(w->response.data);
-
- char *google_version = "0.6";
- char *google_reqId = "0";
- char *google_sig = "0";
- char *google_out = "json";
- char *google_responseHandler = "google.visualization.Query.setResponse";
- char *google_outFileName = NULL;
- time_t last_timestamp_in_data = 0;
- if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) {
-
- w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
-
- while(args) {
- tok = mystrsep(&args, "&");
- if(tok && *tok) {
- char *name = mystrsep(&tok, "=");
- if(name && *name && strcmp(name, "tqx") == 0) {
- char *key = mystrsep(&tok, ":");
- char *value = mystrsep(&tok, ";");
- if(key && value && *key && *value) {
- if(strcmp(key, "version") == 0)
- google_version = value;
-
- else if(strcmp(key, "reqId") == 0)
- google_reqId = value;
-
- else if(strcmp(key, "sig") == 0)
- google_sig = value;
-
- else if(strcmp(key, "out") == 0)
- google_out = value;
-
- else if(strcmp(key, "responseHandler") == 0)
- google_responseHandler = value;
-
- else if(strcmp(key, "outFileName") == 0)
- google_outFileName = value;
- }
- }
- }
- }
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
- w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName
- );
-
- if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
- last_timestamp_in_data = strtoul(google_sig, NULL, 0);
-
- // check the client wants json
- if(strcmp(google_out, "json") != 0) {
- buffer_sprintf(w->response.data,
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
- google_responseHandler, google_version, google_reqId, google_out);
- return 200;
- }
- }
- }
-
- if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
- buffer_sprintf(w->response.data,
- "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
- google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
- }
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).",
- w->id, st->name, st->id, lines, group_count, group_method, after, before);
-
- time_t timestamp_in_data = rrdset2json_api_old(datasource_type, st, w->response.data, lines, group_count
- , group_method, (unsigned long) after, (unsigned long) before
- , nonzero);
-
- if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
- if(timestamp_in_data > last_timestamp_in_data)
- buffer_strcat(w->response.data, "});");
-
- else {
- // the client already has the latest data
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data,
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
- google_responseHandler, google_version, google_reqId);
- }
- }
-
- return 200;
-}
-
-inline int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url) {
- return web_client_api_old_data_request(host, w, url, DATASOURCE_JSON);
-}
-
-inline int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url) {
- return web_client_api_old_data_request(host, w, url, DATASOURCE_DATATABLE_JSONP);
-}
-
-inline int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url) {
- // get the name of the data to show
- char *tok = mystrsep(&url, "/?&");
- if(tok && *tok) {
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
-
- // do we have such a data set?
- RRDSET *st = rrdset_find_byname(host, tok);
- if(!st) st = rrdset_find(host, tok);
- if(!st) {
- // we don't have it
- // try to send a file with that name
- buffer_flush(w->response.data);
- return mysendfile(w, tok);
- }
- st->last_accessed_time = now_realtime_sec();
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
- w->response.data->contenttype = CT_APPLICATION_JSON;
- buffer_flush(w->response.data);
- rrd_graph2json_api_old(st, url, w->response.data);
- return 200;
- }
-
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Graph name?\r\n");
- return 400;
-}
-
-inline int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url) {
- (void)url;
-
- buffer_flush(w->response.data);
- RRDSET *st;
-
- rrdhost_rdlock(host);
- rrdset_foreach_read(st, host) {
- if(rrdset_is_available_for_viewers(st))
- buffer_sprintf(w->response.data, "%s\n", st->name);
- }
- rrdhost_unlock(host);
-
- return 200;
-}
-
-inline int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url) {
- (void)url;
-
- w->response.data->contenttype = CT_APPLICATION_JSON;
- buffer_flush(w->response.data);
- rrd_all2json_api_old(host, w->response.data);
- return 200;
-}
diff --git a/src/web_api_old.h b/src/web_api_old.h
deleted file mode 100644
index dff48c2f3..000000000
--- a/src/web_api_old.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef NETDATA_WEB_API_OLD_H
-#define NETDATA_WEB_API_OLD_H
-
-#include "common.h"
-
-extern int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type);
-extern int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url);
-
-#endif //NETDATA_WEB_API_OLD_H
diff --git a/src/web_api_v1.c b/src/web_api_v1.c
deleted file mode 100644
index c32660c81..000000000
--- a/src/web_api_v1.c
+++ /dev/null
@@ -1,1017 +0,0 @@
-#include "common.h"
-
-static struct {
- const char *name;
- uint32_t hash;
- int value;
-} api_v1_data_groups[] = {
- { "average" , 0 , GROUP_AVERAGE}
- , {"min" , 0 , GROUP_MIN}
- , {"max" , 0 , GROUP_MAX}
- , {"sum" , 0 , GROUP_SUM}
- , {"incremental_sum", 0 , GROUP_INCREMENTAL_SUM}
- , {"incremental-sum", 0 , GROUP_INCREMENTAL_SUM}
- , { NULL, 0, 0}
-};
-
-static struct {
- const char *name;
- uint32_t hash;
- uint32_t value;
-} api_v1_data_options[] = {
- { "nonzero" , 0 , RRDR_OPTION_NONZERO}
- , {"flip" , 0 , RRDR_OPTION_REVERSED}
- , {"reversed" , 0 , RRDR_OPTION_REVERSED}
- , {"reverse" , 0 , RRDR_OPTION_REVERSED}
- , {"jsonwrap" , 0 , RRDR_OPTION_JSON_WRAP}
- , {"min2max" , 0 , RRDR_OPTION_MIN2MAX}
- , {"ms" , 0 , RRDR_OPTION_MILLISECONDS}
- , {"milliseconds" , 0 , RRDR_OPTION_MILLISECONDS}
- , {"abs" , 0 , RRDR_OPTION_ABSOLUTE}
- , {"absolute" , 0 , RRDR_OPTION_ABSOLUTE}
- , {"absolute_sum" , 0 , RRDR_OPTION_ABSOLUTE}
- , {"absolute-sum" , 0 , RRDR_OPTION_ABSOLUTE}
- , {"display_absolute", 0 , RRDR_OPTION_DISPLAY_ABS}
- , {"display-absolute", 0 , RRDR_OPTION_DISPLAY_ABS}
- , {"seconds" , 0 , RRDR_OPTION_SECONDS}
- , {"null2zero" , 0 , RRDR_OPTION_NULL2ZERO}
- , {"objectrows" , 0 , RRDR_OPTION_OBJECTSROWS}
- , {"google_json" , 0 , RRDR_OPTION_GOOGLE_JSON}
- , {"google-json" , 0 , RRDR_OPTION_GOOGLE_JSON}
- , {"percentage" , 0 , RRDR_OPTION_PERCENTAGE}
- , {"unaligned" , 0 , RRDR_OPTION_NOT_ALIGNED}
- , {"match_ids" , 0 , RRDR_OPTION_MATCH_IDS}
- , {"match-ids" , 0 , RRDR_OPTION_MATCH_IDS}
- , {"match_names" , 0 , RRDR_OPTION_MATCH_NAMES}
- , {"match-names" , 0 , RRDR_OPTION_MATCH_NAMES}
- , { NULL, 0, 0}
-};
-
-static struct {
- const char *name;
- uint32_t hash;
- uint32_t value;
-} api_v1_data_formats[] = {
- { DATASOURCE_FORMAT_DATATABLE_JSON , 0 , DATASOURCE_DATATABLE_JSON}
- , {DATASOURCE_FORMAT_DATATABLE_JSONP, 0 , DATASOURCE_DATATABLE_JSONP}
- , {DATASOURCE_FORMAT_JSON , 0 , DATASOURCE_JSON}
- , {DATASOURCE_FORMAT_JSONP , 0 , DATASOURCE_JSONP}
- , {DATASOURCE_FORMAT_SSV , 0 , DATASOURCE_SSV}
- , {DATASOURCE_FORMAT_CSV , 0 , DATASOURCE_CSV}
- , {DATASOURCE_FORMAT_TSV , 0 , DATASOURCE_TSV}
- , {"tsv-excel" , 0 , DATASOURCE_TSV}
- , {DATASOURCE_FORMAT_HTML , 0 , DATASOURCE_HTML}
- , {DATASOURCE_FORMAT_JS_ARRAY , 0 , DATASOURCE_JS_ARRAY}
- , {DATASOURCE_FORMAT_SSV_COMMA , 0 , DATASOURCE_SSV_COMMA}
- , {DATASOURCE_FORMAT_CSV_JSON_ARRAY , 0 , DATASOURCE_CSV_JSON_ARRAY}
- , { NULL, 0, 0}
-};
-
-static struct {
- const char *name;
- uint32_t hash;
- uint32_t value;
-} api_v1_data_google_formats[] = {
- // this is not error - when google requests json, it expects javascript
- // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source#responseformat
- { "json" , 0 , DATASOURCE_DATATABLE_JSONP}
- , {"html" , 0 , DATASOURCE_HTML}
- , {"csv" , 0 , DATASOURCE_CSV}
- , {"tsv-excel", 0 , DATASOURCE_TSV}
- , { NULL, 0, 0}
-};
-
-void web_client_api_v1_init(void) {
- int i;
-
- for(i = 0; api_v1_data_groups[i].name ; i++)
- api_v1_data_groups[i].hash = simple_hash(api_v1_data_groups[i].name);
-
- for(i = 0; api_v1_data_options[i].name ; i++)
- api_v1_data_options[i].hash = simple_hash(api_v1_data_options[i].name);
-
- for(i = 0; api_v1_data_formats[i].name ; i++)
- api_v1_data_formats[i].hash = simple_hash(api_v1_data_formats[i].name);
-
- for(i = 0; api_v1_data_google_formats[i].name ; i++)
- api_v1_data_google_formats[i].hash = simple_hash(api_v1_data_google_formats[i].name);
-}
-
-inline int web_client_api_request_v1_data_group(char *name, int def) {
- int i;
-
- uint32_t hash = simple_hash(name);
- for(i = 0; api_v1_data_groups[i].name ; i++)
- if(unlikely(hash == api_v1_data_groups[i].hash && !strcmp(name, api_v1_data_groups[i].name)))
- return api_v1_data_groups[i].value;
-
- return def;
-}
-
-inline uint32_t web_client_api_request_v1_data_options(char *o) {
- uint32_t ret = 0x00000000;
- char *tok;
-
- while(o && *o && (tok = mystrsep(&o, ", |"))) {
- if(!*tok) continue;
-
- uint32_t hash = simple_hash(tok);
- int i;
- for(i = 0; api_v1_data_options[i].name ; i++) {
- if (unlikely(hash == api_v1_data_options[i].hash && !strcmp(tok, api_v1_data_options[i].name))) {
- ret |= api_v1_data_options[i].value;
- break;
- }
- }
- }
-
- return ret;
-}
-
-inline uint32_t web_client_api_request_v1_data_format(char *name) {
- uint32_t hash = simple_hash(name);
- int i;
-
- for(i = 0; api_v1_data_formats[i].name ; i++) {
- if (unlikely(hash == api_v1_data_formats[i].hash && !strcmp(name, api_v1_data_formats[i].name))) {
- return api_v1_data_formats[i].value;
- }
- }
-
- return DATASOURCE_JSON;
-}
-
-inline uint32_t web_client_api_request_v1_data_google_format(char *name) {
- uint32_t hash = simple_hash(name);
- int i;
-
- for(i = 0; api_v1_data_google_formats[i].name ; i++) {
- if (unlikely(hash == api_v1_data_google_formats[i].hash && !strcmp(name, api_v1_data_google_formats[i].name))) {
- return api_v1_data_google_formats[i].value;
- }
- }
-
- return DATASOURCE_JSON;
-}
-
-
-inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) {
- int all = 0;
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if (!value || !*value) continue;
-
- if(!strcmp(value, "all")) all = 1;
- else if(!strcmp(value, "active")) all = 0;
- }
-
- buffer_flush(w->response.data);
- w->response.data->contenttype = CT_APPLICATION_JSON;
- health_alarms2json(host, w->response.data, all);
- return 200;
-}
-
-inline int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url) {
- uint32_t after = 0;
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if (!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if(!name || !*name) continue;
- if(!value || !*value) continue;
-
- if(!strcmp(name, "after")) after = (uint32_t)strtoul(value, NULL, 0);
- }
-
- buffer_flush(w->response.data);
- w->response.data->contenttype = CT_APPLICATION_JSON;
- health_alarm_log2json(host, w->response.data, after);
- return 200;
-}
-
-inline int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) {
- int ret = 400;
- char *chart = NULL;
-
- buffer_flush(w->response.data);
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if(!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if(!name || !*name) continue;
- if(!value || !*value) continue;
-
- // name and value are now the parameters
- // they are not null and not empty
-
- if(!strcmp(name, "chart")) chart = value;
- //else {
- /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
- // goto cleanup;
- //}
- }
-
- if(!chart || !*chart) {
- buffer_sprintf(w->response.data, "No chart id is given at the request.");
- goto cleanup;
- }
-
- RRDSET *st = rrdset_find(host, chart);
- if(!st) st = rrdset_find_byname(host, chart);
- if(!st) {
- buffer_strcat(w->response.data, "Chart is not found: ");
- buffer_strcat_htmlescape(w->response.data, chart);
- ret = 404;
- goto cleanup;
- }
-
- w->response.data->contenttype = CT_APPLICATION_JSON;
- st->last_accessed_time = now_realtime_sec();
- callback(st, w->response.data);
- return 200;
-
- cleanup:
- return ret;
-}
-
-inline int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url) {
- return web_client_api_request_single_chart(host, w, url, health_api_v1_chart_variables2json);
-}
-
-inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url) {
- (void)url;
-
- buffer_flush(w->response.data);
- w->response.data->contenttype = CT_APPLICATION_JSON;
- rrd_stats_api_v1_charts(host, w->response.data);
- return 200;
-}
-
-inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) {
- int format = ALLMETRICS_SHELL;
- int help = 0, types = 0, timestamps = 1, names = backend_send_names; // prometheus options
- const char *prometheus_server = w->client_ip;
- uint32_t prometheus_options = backend_options;
- const char *prometheus_prefix = backend_prefix;
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if (!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if(!name || !*name) continue;
- if(!value || !*value) continue;
-
- if(!strcmp(name, "format")) {
- if(!strcmp(value, ALLMETRICS_FORMAT_SHELL))
- format = ALLMETRICS_SHELL;
- else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS))
- format = ALLMETRICS_PROMETHEUS;
- else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS))
- format = ALLMETRICS_PROMETHEUS_ALL_HOSTS;
- else if(!strcmp(value, ALLMETRICS_FORMAT_JSON))
- format = ALLMETRICS_JSON;
- else
- format = 0;
- }
- else if(!strcmp(name, "help")) {
- if(!strcmp(value, "yes"))
- help = 1;
- else
- help = 0;
- }
- else if(!strcmp(name, "types")) {
- if(!strcmp(value, "yes"))
- types = 1;
- else
- types = 0;
- }
- else if(!strcmp(name, "names")) {
- if(!strcmp(value, "yes"))
- names = 1;
- else
- names = 0;
- }
- else if(!strcmp(name, "timestamps")) {
- if(!strcmp(value, "yes"))
- timestamps = 1;
- else
- timestamps = 0;
- }
- else if(!strcmp(name, "server")) {
- prometheus_server = value;
- }
- else if(!strcmp(name, "prefix")) {
- prometheus_prefix = value;
- }
- else if(!strcmp(name, "data") || !strcmp(name, "source") || !strcmp(name, "data source") || !strcmp(name, "data-source") || !strcmp(name, "data_source") || !strcmp(name, "datasource")) {
- prometheus_options = backend_parse_data_source(value, prometheus_options);
- }
- }
-
- buffer_flush(w->response.data);
- 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);
- return 200;
-
- case ALLMETRICS_PROMETHEUS:
- w->response.data->contenttype = CT_PROMETHEUS;
- rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_options, help, types, names, timestamps);
- return 200;
-
- case ALLMETRICS_PROMETHEUS_ALL_HOSTS:
- w->response.data->contenttype = CT_PROMETHEUS;
- rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_options, help, types, names, timestamps);
- return 200;
-
- default:
- w->response.data->contenttype = CT_TEXT_PLAIN;
- buffer_strcat(w->response.data, "Which format? '" ALLMETRICS_FORMAT_SHELL "', '" ALLMETRICS_FORMAT_PROMETHEUS "', '" ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS "' and '" ALLMETRICS_FORMAT_JSON "' are currently supported.");
- return 400;
- }
-}
-
-inline int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url) {
- return web_client_api_request_single_chart(host, w, url, rrd_stats_api_v1_chart);
-}
-
-int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
- int ret = 400;
- buffer_flush(w->response.data);
-
- BUFFER *dimensions = NULL;
-
- const char *chart = NULL
- , *before_str = NULL
- , *after_str = NULL
- , *points_str = NULL
- , *multiply_str = NULL
- , *divide_str = NULL
- , *label = NULL
- , *units = NULL
- , *label_color = NULL
- , *value_color = NULL
- , *refresh_str = NULL
- , *precision_str = NULL
- , *scale_str = NULL
- , *alarm = NULL;
-
- int group = GROUP_AVERAGE;
- uint32_t options = 0x00000000;
-
- while(url) {
- char *value = mystrsep(&url, "/?&");
- if(!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if(!name || !*name) continue;
- if(!value || !*value) continue;
-
- debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);
-
- // name and value are now the parameters
- // they are not null and not empty
-
- if(!strcmp(name, "chart")) chart = value;
- else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
- if(!dimensions)
- dimensions = buffer_create(100);
-
- buffer_strcat(dimensions, "|");
- buffer_strcat(dimensions, value);
- }
- else if(!strcmp(name, "after")) after_str = value;
- else if(!strcmp(name, "before")) before_str = value;
- else if(!strcmp(name, "points")) points_str = value;
- else if(!strcmp(name, "group")) {
- group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
- }
- else if(!strcmp(name, "options")) {
- options |= web_client_api_request_v1_data_options(value);
- }
- else if(!strcmp(name, "label")) label = value;
- else if(!strcmp(name, "units")) units = value;
- else if(!strcmp(name, "label_color")) label_color = value;
- else if(!strcmp(name, "value_color")) value_color = value;
- else if(!strcmp(name, "multiply")) multiply_str = value;
- else if(!strcmp(name, "divide")) divide_str = value;
- else if(!strcmp(name, "refresh")) refresh_str = value;
- else if(!strcmp(name, "precision")) precision_str = value;
- else if(!strcmp(name, "scale")) scale_str = value;
- else if(!strcmp(name, "alarm")) alarm = value;
- }
-
- if(!chart || !*chart) {
- buffer_no_cacheable(w->response.data);
- buffer_sprintf(w->response.data, "No chart id is given at the request.");
- goto cleanup;
- }
-
- int scale = (scale_str && *scale_str)?str2i(scale_str):100;
-
- RRDSET *st = rrdset_find(host, chart);
- if(!st) st = rrdset_find_byname(host, chart);
- if(!st) {
- buffer_no_cacheable(w->response.data);
- buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0);
- ret = 200;
- goto cleanup;
- }
- st->last_accessed_time = now_realtime_sec();
-
- RRDCALC *rc = NULL;
- if(alarm) {
- rc = rrdcalc_find(st, alarm);
- if (!rc) {
- buffer_no_cacheable(w->response.data);
- buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0);
- ret = 200;
- goto cleanup;
- }
- }
-
- long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1;
- long long divide = (divide_str && *divide_str )?str2l(divide_str):1;
- long long before = (before_str && *before_str )?str2l(before_str):0;
- long long after = (after_str && *after_str )?str2l(after_str):-st->update_every;
- int points = (points_str && *points_str )?str2i(points_str):1;
- int precision = (precision_str && *precision_str)?str2i(precision_str):-1;
-
- if(!multiply) multiply = 1;
- if(!divide) divide = 1;
-
- int refresh = 0;
- if(refresh_str && *refresh_str) {
- if(!strcmp(refresh_str, "auto")) {
- if(rc) refresh = rc->update_every;
- else if(options & RRDR_OPTION_NOT_ALIGNED)
- refresh = st->update_every;
- else {
- refresh = (int)(before - after);
- if(refresh < 0) refresh = -refresh;
- }
- }
- else {
- refresh = str2i(refresh_str);
- if(refresh < 0) refresh = -refresh;
- }
- }
-
- if(!label) {
- if(alarm) {
- char *s = (char *)alarm;
- while(*s) {
- if(*s == '_') *s = ' ';
- s++;
- }
- label = alarm;
- }
- else if(dimensions) {
- const char *dim = buffer_tostring(dimensions);
- if(*dim == '|') dim++;
- label = dim;
- }
- else
- label = st->name;
- }
- if(!units) {
- if(alarm) {
- if(rc->units)
- units = rc->units;
- else
- units = "";
- }
- else if(options & RRDR_OPTION_PERCENTAGE)
- units = "%";
- else
- units = st->units;
- }
-
- debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'"
- , w->id
- , chart
- , alarm?alarm:""
- , (dimensions)?buffer_tostring(dimensions):""
- , after
- , before
- , points
- , group
- , options
- );
-
- if(rc) {
- if (refresh > 0) {
- buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
- w->response.data->expires = now_realtime_sec() + refresh;
- }
- else buffer_no_cacheable(w->response.data);
-
- if(!value_color) {
- switch(rc->status) {
- case RRDCALC_STATUS_CRITICAL:
- value_color = "red";
- break;
-
- case RRDCALC_STATUS_WARNING:
- value_color = "orange";
- break;
-
- case RRDCALC_STATUS_CLEAR:
- value_color = "brightgreen";
- break;
-
- case RRDCALC_STATUS_UNDEFINED:
- value_color = "lightgrey";
- break;
-
- case RRDCALC_STATUS_UNINITIALIZED:
- value_color = "#000";
- break;
-
- default:
- value_color = "grey";
- break;
- }
- }
-
- buffer_svg(w->response.data,
- label,
- (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide,
- units,
- label_color,
- value_color,
- precision,
- scale,
- options
- );
- ret = 200;
- }
- else {
- time_t latest_timestamp = 0;
- int value_is_null = 1;
- calculated_number n = NAN;
- ret = 500;
-
- // if the collected value is too old, don't calculate its value
- if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above)))
- ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL
- , points, after, before, group, 0, options, NULL, &latest_timestamp, &value_is_null);
-
- // if the value cannot be calculated, show empty badge
- if (ret != 200) {
- buffer_no_cacheable(w->response.data);
- value_is_null = 1;
- n = 0;
- ret = 200;
- }
- else if (refresh > 0) {
- buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
- w->response.data->expires = now_realtime_sec() + refresh;
- }
- else buffer_no_cacheable(w->response.data);
-
- // render the badge
- buffer_svg(w->response.data,
- label,
- (value_is_null)?NAN:(n * multiply / divide),
- units,
- label_color,
- value_color,
- precision,
- scale,
- options
- );
- }
-
- cleanup:
- buffer_free(dimensions);
- return ret;
-}
-
-// returns the HTTP code
-inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) {
- debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
-
- int ret = 400;
- BUFFER *dimensions = NULL;
-
- buffer_flush(w->response.data);
-
- char *google_version = "0.6",
- *google_reqId = "0",
- *google_sig = "0",
- *google_out = "json",
- *responseHandler = NULL,
- *outFileName = NULL;
-
- time_t last_timestamp_in_data = 0, google_timestamp = 0;
-
- char *chart = NULL
- , *before_str = NULL
- , *after_str = NULL
- , *group_time_str = NULL
- , *points_str = NULL;
-
- int group = GROUP_AVERAGE;
- uint32_t format = DATASOURCE_JSON;
- uint32_t options = 0x00000000;
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if(!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if(!name || !*name) continue;
- if(!value || !*value) continue;
-
- debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
-
- // name and value are now the parameters
- // they are not null and not empty
-
- if(!strcmp(name, "chart")) chart = value;
- else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
- if(!dimensions) dimensions = buffer_create(100);
- buffer_strcat(dimensions, "|");
- buffer_strcat(dimensions, value);
- }
- else if(!strcmp(name, "after")) after_str = value;
- else if(!strcmp(name, "before")) before_str = value;
- else if(!strcmp(name, "points")) points_str = value;
- else if(!strcmp(name, "gtime")) group_time_str = value;
- else if(!strcmp(name, "group")) {
- group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
- }
- else if(!strcmp(name, "format")) {
- format = web_client_api_request_v1_data_format(value);
- }
- else if(!strcmp(name, "options")) {
- options |= web_client_api_request_v1_data_options(value);
- }
- else if(!strcmp(name, "callback")) {
- responseHandler = value;
- }
- else if(!strcmp(name, "filename")) {
- outFileName = value;
- }
- else if(!strcmp(name, "tqx")) {
- // parse Google Visualization API options
- // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
- char *tqx_name, *tqx_value;
-
- while(value) {
- tqx_value = mystrsep(&value, ";");
- if(!tqx_value || !*tqx_value) continue;
-
- tqx_name = mystrsep(&tqx_value, ":");
- if(!tqx_name || !*tqx_name) continue;
- if(!tqx_value || !*tqx_value) continue;
-
- if(!strcmp(tqx_name, "version"))
- google_version = tqx_value;
- else if(!strcmp(tqx_name, "reqId"))
- google_reqId = tqx_value;
- else if(!strcmp(tqx_name, "sig")) {
- google_sig = tqx_value;
- google_timestamp = strtoul(google_sig, NULL, 0);
- }
- else if(!strcmp(tqx_name, "out")) {
- google_out = tqx_value;
- format = web_client_api_request_v1_data_google_format(google_out);
- }
- else if(!strcmp(tqx_name, "responseHandler"))
- responseHandler = tqx_value;
- else if(!strcmp(tqx_name, "outFileName"))
- outFileName = tqx_value;
- }
- }
- }
-
- if(!chart || !*chart) {
- buffer_sprintf(w->response.data, "No chart id is given at the request.");
- goto cleanup;
- }
-
- RRDSET *st = rrdset_find(host, chart);
- if(!st) st = rrdset_find_byname(host, chart);
- if(!st) {
- buffer_strcat(w->response.data, "Chart is not found: ");
- buffer_strcat_htmlescape(w->response.data, chart);
- ret = 404;
- goto cleanup;
- }
- st->last_accessed_time = now_realtime_sec();
-
- long long before = (before_str && *before_str)?str2l(before_str):0;
- long long after = (after_str && *after_str) ?str2l(after_str):0;
- int points = (points_str && *points_str)?str2i(points_str):0;
- long group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0;
-
- debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
- , w->id
- , chart
- , (dimensions)?buffer_tostring(dimensions):""
- , after
- , before
- , points
- , group
- , format
- , options
- );
-
- if(outFileName && *outFileName) {
- buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
- debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
- }
-
- if(format == DATASOURCE_DATATABLE_JSONP) {
- if(responseHandler == NULL)
- responseHandler = "google.visualization.Query.setResponse";
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
- w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
- );
-
- buffer_sprintf(w->response.data,
- "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
- responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
- }
- else if(format == DATASOURCE_JSONP) {
- if(responseHandler == NULL)
- responseHandler = "callback";
-
- buffer_strcat(w->response.data, responseHandler);
- buffer_strcat(w->response.data, "(");
- }
-
- ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time
- , options, &last_timestamp_in_data);
-
- if(format == DATASOURCE_DATATABLE_JSONP) {
- if(google_timestamp < last_timestamp_in_data)
- buffer_strcat(w->response.data, "});");
-
- else {
- // the client already has the latest data
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data,
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
- responseHandler, google_version, google_reqId);
- }
- }
- else if(format == DATASOURCE_JSONP)
- buffer_strcat(w->response.data, ");");
-
- cleanup:
- buffer_free(dimensions);
- return ret;
-}
-
-inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url) {
- static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0,
- hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0,
- hash_to = 0 /*, hash_redirects = 0 */;
-
- if(unlikely(!hash_action)) {
- hash_action = simple_hash("action");
- hash_access = simple_hash("access");
- hash_hello = simple_hash("hello");
- hash_delete = simple_hash("delete");
- hash_search = simple_hash("search");
- hash_switch = simple_hash("switch");
- hash_machine = simple_hash("machine");
- hash_url = simple_hash("url");
- hash_name = simple_hash("name");
- hash_delete_url = simple_hash("delete_url");
- hash_for = simple_hash("for");
- hash_to = simple_hash("to");
-/*
- hash_redirects = simple_hash("redirects");
-*/
- }
-
- char person_guid[GUID_LEN + 1] = "";
-
- debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url);
-
- // FIXME
- // The browser may send multiple cookies with our id
-
- char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
- if(cookie)
- strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
-
- char action = '\0';
- char *machine_guid = NULL,
- *machine_url = NULL,
- *url_name = NULL,
- *search_machine_guid = NULL,
- *delete_url = NULL,
- *to_person_guid = NULL;
-/*
- int redirects = 0;
-*/
-
- while(url) {
- char *value = mystrsep(&url, "?&");
- if (!value || !*value) continue;
-
- char *name = mystrsep(&value, "=");
- if (!name || !*name) continue;
- if (!value || !*value) continue;
-
- debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
-
- uint32_t hash = simple_hash(name);
-
- if(hash == hash_action && !strcmp(name, "action")) {
- uint32_t vhash = simple_hash(value);
-
- if(vhash == hash_access && !strcmp(value, "access")) action = 'A';
- else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H';
- else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
- else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
- else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
-#ifdef NETDATA_INTERNAL_CHECKS
- else error("unknown registry action '%s'", value);
-#endif /* NETDATA_INTERNAL_CHECKS */
- }
-/*
- else if(hash == hash_redirects && !strcmp(name, "redirects"))
- redirects = atoi(value);
-*/
- else if(hash == hash_machine && !strcmp(name, "machine"))
- machine_guid = value;
-
- else if(hash == hash_url && !strcmp(name, "url"))
- machine_url = value;
-
- else if(action == 'A') {
- if(hash == hash_name && !strcmp(name, "name"))
- url_name = value;
- }
- else if(action == 'D') {
- if(hash == hash_delete_url && !strcmp(name, "delete_url"))
- delete_url = value;
- }
- else if(action == 'S') {
- if(hash == hash_for && !strcmp(name, "for"))
- search_machine_guid = value;
- }
- else if(action == 'W') {
- if(hash == hash_to && !strcmp(name, "to"))
- to_person_guid = value;
- }
-#ifdef NETDATA_INTERNAL_CHECKS
- else error("unused registry URL parameter '%s' with value '%s'", name, value);
-#endif /* NETDATA_INTERNAL_CHECKS */
- }
-
- if(unlikely(respect_web_browser_do_not_track_policy && web_client_has_donottrack(w))) {
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work.");
- return 400;
- }
-
- if(unlikely(action == 'H')) {
- // HELLO request, dashboard ACL
- if(unlikely(!web_client_can_access_dashboard(w)))
- return web_client_permission_denied(w);
- }
- else {
- // everything else, registry ACL
- if(unlikely(!web_client_can_access_registry(w)))
- return web_client_permission_denied(w);
- }
-
- switch(action) {
- case 'A':
- if(unlikely(!machine_guid || !machine_url || !url_name)) {
- error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", machine_guid ? machine_guid : "UNSET", machine_url ? machine_url : "UNSET", url_name ? url_name : "UNSET");
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Invalid registry Access request.");
- return 400;
- }
-
- web_client_enable_tracking_required(w);
- return registry_request_access_json(host, w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec());
-
- case 'D':
- if(unlikely(!machine_guid || !machine_url || !delete_url)) {
- error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Invalid registry Delete request.");
- return 400;
- }
-
- web_client_enable_tracking_required(w);
- return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec());
-
- case 'S':
- if(unlikely(!machine_guid || !machine_url || !search_machine_guid)) {
- error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Invalid registry Search request.");
- return 400;
- }
-
- web_client_enable_tracking_required(w);
- return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec());
-
- case 'W':
- if(unlikely(!machine_guid || !machine_url || !to_person_guid)) {
- error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Invalid registry Switch request.");
- return 400;
- }
-
- web_client_enable_tracking_required(w);
- return registry_request_switch_json(host, w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec());
-
- case 'H':
- return registry_request_hello_json(host, w);
-
- default:
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search");
- return 400;
- }
-}
-
-static struct api_command {
- const char *command;
- uint32_t hash;
- WEB_CLIENT_ACL acl;
- int (*callback)(RRDHOST *host, struct web_client *w, char *url);
-} api_commands[] = {
- { "data", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_data },
- { "chart", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_chart },
- { "charts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_charts },
-
- // registry checks the ACL by itself, so we allow everything
- { "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry },
-
- // badges can be fetched with both dashboard and badge permissions
- { "badge.svg", 0, WEB_CLIENT_ACL_DASHBOARD|WEB_CLIENT_ACL_BADGE, web_client_api_request_v1_badge },
-
- { "alarms", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms },
- { "alarm_log", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_log },
- { "alarm_variables", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_variables },
- { "allmetrics", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_allmetrics },
-
- // terminator
- { NULL, 0, WEB_CLIENT_ACL_NONE, NULL },
-};
-
-inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url) {
- static int initialized = 0;
- int i;
-
- if(unlikely(initialized == 0)) {
- initialized = 1;
-
- for(i = 0; api_commands[i].command ; i++)
- api_commands[i].hash = simple_hash(api_commands[i].command);
- }
-
- // get the command
- char *tok = mystrsep(&url, "/?&");
- if(tok && *tok) {
- debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
- uint32_t hash = simple_hash(tok);
-
- for(i = 0; api_commands[i].command ;i++) {
- if(unlikely(hash == api_commands[i].hash && !strcmp(tok, api_commands[i].command))) {
- if(unlikely(api_commands[i].acl != WEB_CLIENT_ACL_NOCHECK) && !(w->acl & api_commands[i].acl))
- return web_client_permission_denied(w);
-
- return api_commands[i].callback(host, w, url);
- }
- }
-
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Unsupported v1 API command: ");
- buffer_strcat_htmlescape(w->response.data, tok);
- return 404;
- }
- else {
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Which API v1 command?");
- return 400;
- }
-}
diff --git a/src/web_api_v1.h b/src/web_api_v1.h
deleted file mode 100644
index 6f4de1aba..000000000
--- a/src/web_api_v1.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef NETDATA_WEB_API_V1_H
-#define NETDATA_WEB_API_V1_H
-
-extern int web_client_api_request_v1_data_group(char *name, int def);
-extern uint32_t web_client_api_request_v1_data_options(char *o);
-extern uint32_t web_client_api_request_v1_data_format(char *name);
-extern uint32_t web_client_api_request_v1_data_google_format(char *name);
-
-extern int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf));
-extern int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url);
-extern int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url);
-
-extern void web_client_api_v1_init(void);
-
-#endif //NETDATA_WEB_API_V1_H
diff --git a/src/web_buffer.c b/src/web_buffer.c
deleted file mode 100644
index 50c76f6d6..000000000
--- a/src/web_buffer.c
+++ /dev/null
@@ -1,400 +0,0 @@
-#include "common.h"
-
-#define BUFFER_OVERFLOW_EOF "EOF"
-
-static inline void buffer_overflow_init(BUFFER *b)
-{
- b->buffer[b->size] = '\0';
- strcpy(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF);
-}
-
-#ifdef NETDATA_INTERNAL_CHECKS
-#define buffer_overflow_check(b) _buffer_overflow_check(b, __FILE__, __FUNCTION__, __LINE__)
-#else
-#define buffer_overflow_check(b)
-#endif
-
-static inline void _buffer_overflow_check(BUFFER *b, const char *file, const char *function, const unsigned long line)
-{
- if(b->len > b->size) {
- error("BUFFER: length %zu is above size %zu, at line %lu, at function %s() of file '%s'.", b->len, b->size, line, function, file);
- b->len = b->size;
- }
-
- if(b->buffer[b->size] != '\0' || strcmp(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF) != 0) {
- error("BUFFER: detected overflow at line %lu, at function %s() of file '%s'.", line, function, file);
- buffer_overflow_init(b);
- }
-}
-
-
-void buffer_reset(BUFFER *wb)
-{
- buffer_flush(wb);
-
- wb->contenttype = CT_TEXT_PLAIN;
- wb->options = 0;
- wb->date = 0;
- wb->expires = 0;
-
- buffer_overflow_check(wb);
-}
-
-const char *buffer_tostring(BUFFER *wb)
-{
- buffer_need_bytes(wb, 1);
- wb->buffer[wb->len] = '\0';
-
- buffer_overflow_check(wb);
-
- return(wb->buffer);
-}
-
-void buffer_char_replace(BUFFER *wb, char from, char to)
-{
- char *s = wb->buffer, *end = &wb->buffer[wb->len];
-
- while(s != end) {
- if(*s == from) *s = to;
- s++;
- }
-
- buffer_overflow_check(wb);
-}
-
-// This trick seems to give an 80% speed increase in 32bit systems
-// print_calculated_number_llu_r() will just print the digits up to the
-// point the remaining value fits in 32 bits, and then calls
-// print_calculated_number_lu_r() to print the rest with 32 bit arithmetic.
-
-inline char *print_number_lu_r(char *str, unsigned long uvalue) {
- char *wstr = str;
-
- // print each digit
- do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
- return wstr;
-}
-
-inline char *print_number_llu_r(char *str, unsigned long long uvalue) {
- char *wstr = str;
-
- // print each digit
- do *wstr++ = (char)('0' + (uvalue % 10)); while((uvalue /= 10) && uvalue > (unsigned long long)0xffffffff);
- if(uvalue) return print_number_lu_r(wstr, uvalue);
- return wstr;
-}
-
-inline char *print_number_llu_r_smart(char *str, unsigned long long uvalue) {
-#ifdef ENVIRONMENT32
- if(uvalue > (unsigned long long)0xffffffff)
- str = print_number_llu_r(str, uvalue);
- else
- str = print_number_lu_r(str, uvalue);
-#else
- do *str++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
-#endif
-
- return str;
-}
-
-void buffer_print_llu(BUFFER *wb, unsigned long long uvalue)
-{
- buffer_need_bytes(wb, 50);
-
- char *str = &wb->buffer[wb->len];
- char *wstr = str;
-
-#ifdef ENVIRONMENT32
- if(uvalue > (unsigned long long)0xffffffff)
- wstr = print_number_llu_r(wstr, uvalue);
- else
- wstr = print_number_lu_r(wstr, uvalue);
-#else
- do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
-#endif
-
- // terminate it
- *wstr = '\0';
-
- // reverse it
- char *begin = str, *end = wstr - 1, aux;
- while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
-
- // return the buffer length
- wb->len += wstr - str;
-}
-
-void buffer_strcat(BUFFER *wb, const char *txt)
-{
- // buffer_sprintf(wb, "%s", txt);
-
- if(unlikely(!txt || !*txt)) return;
-
- buffer_need_bytes(wb, 1);
-
- char *s = &wb->buffer[wb->len], *start, *end = &wb->buffer[wb->size];
- size_t len = wb->len;
-
- start = s;
- while(*txt && s != end)
- *s++ = *txt++;
-
- len += s - start;
-
- wb->len = len;
- buffer_overflow_check(wb);
-
- if(*txt) {
- debug(D_WEB_BUFFER, "strcat(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
- len = strlen(txt);
- buffer_increase(wb, len);
- buffer_strcat(wb, txt);
- }
- else {
- // terminate the string
- // without increasing the length
- buffer_need_bytes(wb, (size_t)1);
- wb->buffer[wb->len] = '\0';
- }
-}
-
-void buffer_strcat_htmlescape(BUFFER *wb, const char *txt)
-{
- while(*txt) {
- switch(*txt) {
- case '&': buffer_strcat(wb, "&amp;"); break;
- case '<': buffer_strcat(wb, "&lt;"); break;
- case '>': buffer_strcat(wb, "&gt;"); break;
- case '"': buffer_strcat(wb, "&quot;"); break;
- case '/': buffer_strcat(wb, "&#x2F;"); break;
- case '\'': buffer_strcat(wb, "&#x27;"); break;
- default: {
- buffer_need_bytes(wb, 1);
- wb->buffer[wb->len++] = *txt;
- }
- }
- txt++;
- }
-
- buffer_overflow_check(wb);
-}
-
-void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...)
-{
- if(unlikely(!fmt || !*fmt)) return;
-
- buffer_need_bytes(wb, len + 1);
-
- va_list args;
- va_start(args, fmt);
- wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
- va_end(args);
-
- buffer_overflow_check(wb);
-
- // the buffer is \0 terminated by vsnprintfz
-}
-
-void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args)
-{
- if(unlikely(!fmt || !*fmt)) return;
-
- buffer_need_bytes(wb, 2);
-
- size_t len = wb->size - wb->len - 1;
-
- wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
-
- buffer_overflow_check(wb);
-
- // the buffer is \0 terminated by vsnprintfz
-}
-
-void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
-{
- if(unlikely(!fmt || !*fmt)) return;
-
- va_list args;
- size_t wrote = 0, need = 2, multiplier = 0, len;
-
- do {
- need += wrote + multiplier * WEB_DATA_LENGTH_INCREASE_STEP;
- multiplier++;
-
- debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu, by %zu bytes (wrote = %zu)\n", wb->len, wb->size, need, wrote);
- buffer_need_bytes(wb, need);
-
- len = wb->size - wb->len - 1;
-
- va_start(args, fmt);
- wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
- va_end(args);
-
- } while(wrote >= len);
-
- wb->len += wrote;
-
- // the buffer is \0 terminated by vsnprintf
-}
-
-
-void buffer_rrd_value(BUFFER *wb, calculated_number value)
-{
- buffer_need_bytes(wb, 50);
-
- if(isnan(value) || isinf(value)) {
- buffer_strcat(wb, "null");
- return;
- }
- else
- wb->len += print_calculated_number(&wb->buffer[wb->len], value);
-
- // terminate it
- buffer_need_bytes(wb, 1);
- wb->buffer[wb->len] = '\0';
-
- buffer_overflow_check(wb);
-}
-
-// generate a javascript date, the fastest possible way...
-void buffer_jsdate(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds)
-{
- // 10 20 30 = 35
- // 01234567890123456789012345678901234
- // Date(2014,04,01,03,28,20)
-
- buffer_need_bytes(wb, 30);
-
- char *b = &wb->buffer[wb->len], *p;
- unsigned int *q = (unsigned int *)b;
-
- #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- *q++ = 0x65746144; // "Date" backwards.
- #else
- *q++ = 0x44617465; // "Date"
- #endif
- p = (char *)q;
-
- *p++ = '(';
- *p++ = '0' + year / 1000; year %= 1000;
- *p++ = '0' + year / 100; year %= 100;
- *p++ = '0' + year / 10;
- *p++ = '0' + year % 10;
- *p++ = ',';
- *p = '0' + month / 10; if (*p != '0') p++;
- *p++ = '0' + month % 10;
- *p++ = ',';
- *p = '0' + day / 10; if (*p != '0') p++;
- *p++ = '0' + day % 10;
- *p++ = ',';
- *p = '0' + hours / 10; if (*p != '0') p++;
- *p++ = '0' + hours % 10;
- *p++ = ',';
- *p = '0' + minutes / 10; if (*p != '0') p++;
- *p++ = '0' + minutes % 10;
- *p++ = ',';
- *p = '0' + seconds / 10; if (*p != '0') p++;
- *p++ = '0' + seconds % 10;
-
- unsigned short *r = (unsigned short *)p;
-
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- *r++ = 0x0029; // ")\0" backwards.
- #else
- *r++ = 0x2900; // ")\0"
- #endif
-
- wb->len += (size_t)((char *)r - b - 1);
-
- // terminate it
- wb->buffer[wb->len] = '\0';
- buffer_overflow_check(wb);
-}
-
-// generate a date, the fastest possible way...
-void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds)
-{
- // 10 20 30 = 35
- // 01234567890123456789012345678901234
- // 2014-04-01 03:28:20
-
- buffer_need_bytes(wb, 36);
-
- char *b = &wb->buffer[wb->len];
- char *p = b;
-
- *p++ = '0' + year / 1000; year %= 1000;
- *p++ = '0' + year / 100; year %= 100;
- *p++ = '0' + year / 10;
- *p++ = '0' + year % 10;
- *p++ = '-';
- *p++ = '0' + month / 10;
- *p++ = '0' + month % 10;
- *p++ = '-';
- *p++ = '0' + day / 10;
- *p++ = '0' + day % 10;
- *p++ = ' ';
- *p++ = '0' + hours / 10;
- *p++ = '0' + hours % 10;
- *p++ = ':';
- *p++ = '0' + minutes / 10;
- *p++ = '0' + minutes % 10;
- *p++ = ':';
- *p++ = '0' + seconds / 10;
- *p++ = '0' + seconds % 10;
- *p = '\0';
-
- wb->len += (size_t)(p - b);
-
- // terminate it
- wb->buffer[wb->len] = '\0';
- buffer_overflow_check(wb);
-}
-
-BUFFER *buffer_create(size_t size)
-{
- BUFFER *b;
-
- debug(D_WEB_BUFFER, "Creating new web buffer of size %zu.", size);
-
- b = callocz(1, sizeof(BUFFER));
- b->buffer = mallocz(size + sizeof(BUFFER_OVERFLOW_EOF) + 2);
- b->buffer[0] = '\0';
- b->size = size;
- b->contenttype = CT_TEXT_PLAIN;
- buffer_overflow_init(b);
- buffer_overflow_check(b);
-
- return(b);
-}
-
-void buffer_free(BUFFER *b) {
- if(unlikely(!b)) return;
-
- buffer_overflow_check(b);
-
- debug(D_WEB_BUFFER, "Freeing web buffer of size %zu.", b->size);
-
- freez(b->buffer);
- freez(b);
-}
-
-void buffer_increase(BUFFER *b, size_t free_size_required)
-{
- buffer_overflow_check(b);
-
- size_t left = b->size - b->len;
-
- if(left >= free_size_required) return;
-
- size_t increase = free_size_required - left;
- if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
-
- debug(D_WEB_BUFFER, "Increasing data buffer from size %zu to %zu.", b->size, b->size + increase);
-
- b->buffer = reallocz(b->buffer, b->size + increase + sizeof(BUFFER_OVERFLOW_EOF) + 2);
- b->size += increase;
-
- buffer_overflow_init(b);
- buffer_overflow_check(b);
-}
diff --git a/src/web_buffer.h b/src/web_buffer.h
deleted file mode 100644
index 694c9d4ce..000000000
--- a/src/web_buffer.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef NETDATA_WEB_BUFFER_H
-#define NETDATA_WEB_BUFFER_H 1
-
-#define WEB_DATA_LENGTH_INCREASE_STEP 1024
-
-typedef struct web_buffer {
- size_t size; // allocation size of buffer, in bytes
- size_t len; // current data length in buffer, in bytes
- char *buffer; // the buffer itself
- uint8_t contenttype; // the content type of the data in the buffer
- uint8_t options; // options related to the content
- time_t date; // the timestamp this content has been generated
- time_t expires; // the timestamp this content expires
-} BUFFER;
-
-// options
-#define WB_CONTENT_CACHEABLE 1
-#define WB_CONTENT_NO_CACHEABLE 2
-
-// content-types
-#define CT_APPLICATION_JSON 1
-#define CT_TEXT_PLAIN 2
-#define CT_TEXT_HTML 3
-#define CT_APPLICATION_X_JAVASCRIPT 4
-#define CT_TEXT_CSS 5
-#define CT_TEXT_XML 6
-#define CT_APPLICATION_XML 7
-#define CT_TEXT_XSL 8
-#define CT_APPLICATION_OCTET_STREAM 9
-#define CT_APPLICATION_X_FONT_TRUETYPE 10
-#define CT_APPLICATION_X_FONT_OPENTYPE 11
-#define CT_APPLICATION_FONT_WOFF 12
-#define CT_APPLICATION_FONT_WOFF2 13
-#define CT_APPLICATION_VND_MS_FONTOBJ 14
-#define CT_IMAGE_SVG_XML 15
-#define CT_IMAGE_PNG 16
-#define CT_IMAGE_JPG 17
-#define CT_IMAGE_GIF 18
-#define CT_IMAGE_XICON 19
-#define CT_IMAGE_ICNS 20
-#define CT_IMAGE_BMP 21
-#define CT_PROMETHEUS 22
-
-#define buffer_cacheable(wb) do { (wb)->options |= WB_CONTENT_CACHEABLE; if((wb)->options & WB_CONTENT_NO_CACHEABLE) (wb)->options &= ~WB_CONTENT_NO_CACHEABLE; } while(0)
-#define buffer_no_cacheable(wb) do { (wb)->options |= WB_CONTENT_NO_CACHEABLE; if((wb)->options & WB_CONTENT_CACHEABLE) (wb)->options &= ~WB_CONTENT_CACHEABLE; (wb)->expires = 0; } while(0)
-
-#define buffer_strlen(wb) ((wb)->len)
-extern const char *buffer_tostring(BUFFER *wb);
-
-#define buffer_flush(wb) wb->buffer[(wb)->len = 0] = '\0'
-extern void buffer_reset(BUFFER *wb);
-
-extern void buffer_strcat(BUFFER *wb, const char *txt);
-extern void buffer_rrd_value(BUFFER *wb, calculated_number value);
-
-extern void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds);
-extern void buffer_jsdate(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds);
-
-extern BUFFER *buffer_create(size_t size);
-extern void buffer_free(BUFFER *b);
-extern void buffer_increase(BUFFER *b, size_t free_size_required);
-
-extern void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) PRINTFLIKE(3, 4);
-extern void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args);
-extern void buffer_sprintf(BUFFER *wb, const char *fmt, ...) PRINTFLIKE(2,3);
-extern void buffer_strcat_htmlescape(BUFFER *wb, const char *txt);
-
-extern void buffer_char_replace(BUFFER *wb, char from, char to);
-
-extern char *print_number_lu_r(char *str, unsigned long uvalue);
-extern char *print_number_llu_r(char *str, unsigned long long uvalue);
-extern char *print_number_llu_r_smart(char *str, unsigned long long uvalue);
-
-extern void buffer_print_llu(BUFFER *wb, unsigned long long uvalue);
-
-static inline void buffer_need_bytes(BUFFER *buffer, size_t needed_free_size) {
- if(unlikely(buffer->size - buffer->len < needed_free_size))
- buffer_increase(buffer, needed_free_size);
-}
-
-#endif /* NETDATA_WEB_BUFFER_H */
diff --git a/src/web_buffer_svg.c b/src/web_buffer_svg.c
deleted file mode 100644
index c05e526ed..000000000
--- a/src/web_buffer_svg.c
+++ /dev/null
@@ -1,832 +0,0 @@
-#include "common.h"
-
-#define BADGE_HORIZONTAL_PADDING 4
-#define VERDANA_KERNING 0.2
-#define VERDANA_PADDING 1.0
-
-/*
- * verdana11_widths[] has been generated with this method:
- * https://github.com/badges/shields/blob/master/measure-text.js
-*/
-
-double verdana11_widths[256] = {
- [0] = 0.0,
- [1] = 0.0,
- [2] = 0.0,
- [3] = 0.0,
- [4] = 0.0,
- [5] = 0.0,
- [6] = 0.0,
- [7] = 0.0,
- [8] = 0.0,
- [9] = 0.0,
- [10] = 0.0,
- [11] = 0.0,
- [12] = 0.0,
- [13] = 0.0,
- [14] = 0.0,
- [15] = 0.0,
- [16] = 0.0,
- [17] = 0.0,
- [18] = 0.0,
- [19] = 0.0,
- [20] = 0.0,
- [21] = 0.0,
- [22] = 0.0,
- [23] = 0.0,
- [24] = 0.0,
- [25] = 0.0,
- [26] = 0.0,
- [27] = 0.0,
- [28] = 0.0,
- [29] = 0.0,
- [30] = 0.0,
- [31] = 0.0,
- [32] = 3.8671874999999996, //
- [33] = 4.3291015625, // !
- [34] = 5.048828125, // "
- [35] = 9.001953125, // #
- [36] = 6.9931640625, // $
- [37] = 11.837890625, // %
- [38] = 7.992187499999999, // &
- [39] = 2.9541015625, // '
- [40] = 4.9951171875, // (
- [41] = 4.9951171875, // )
- [42] = 6.9931640625, // *
- [43] = 9.001953125, // +
- [44] = 4.00146484375, // ,
- [45] = 4.9951171875, // -
- [46] = 4.00146484375, // .
- [47] = 4.9951171875, // /
- [48] = 6.9931640625, // 0
- [49] = 6.9931640625, // 1
- [50] = 6.9931640625, // 2
- [51] = 6.9931640625, // 3
- [52] = 6.9931640625, // 4
- [53] = 6.9931640625, // 5
- [54] = 6.9931640625, // 6
- [55] = 6.9931640625, // 7
- [56] = 6.9931640625, // 8
- [57] = 6.9931640625, // 9
- [58] = 4.9951171875, // :
- [59] = 4.9951171875, // ;
- [60] = 9.001953125, // <
- [61] = 9.001953125, // =
- [62] = 9.001953125, // >
- [63] = 5.99951171875, // ?
- [64] = 11.0, // @
- [65] = 7.51953125, // A
- [66] = 7.541015625, // B
- [67] = 7.680664062499999, // C
- [68] = 8.4755859375, // D
- [69] = 6.95556640625, // E
- [70] = 6.32177734375, // F
- [71] = 8.529296875, // G
- [72] = 8.26611328125, // H
- [73] = 4.6298828125, // I
- [74] = 5.00048828125, // J
- [75] = 7.62158203125, // K
- [76] = 6.123046875, // L
- [77] = 9.2705078125, // M
- [78] = 8.228515625, // N
- [79] = 8.658203125, // O
- [80] = 6.63330078125, // P
- [81] = 8.658203125, // Q
- [82] = 7.6484375, // R
- [83] = 7.51953125, // S
- [84] = 6.7783203125, // T
- [85] = 8.05126953125, // U
- [86] = 7.51953125, // V
- [87] = 10.87646484375, // W
- [88] = 7.53564453125, // X
- [89] = 6.767578125, // Y
- [90] = 7.53564453125, // Z
- [91] = 4.9951171875, // [
- [92] = 4.9951171875, // backslash
- [93] = 4.9951171875, // ]
- [94] = 9.001953125, // ^
- [95] = 6.9931640625, // _
- [96] = 6.9931640625, // `
- [97] = 6.6064453125, // a
- [98] = 6.853515625, // b
- [99] = 5.73095703125, // c
- [100] = 6.853515625, // d
- [101] = 6.552734375, // e
- [102] = 3.8671874999999996, // f
- [103] = 6.853515625, // g
- [104] = 6.9609375, // h
- [105] = 3.0185546875, // i
- [106] = 3.78662109375, // j
- [107] = 6.509765625, // k
- [108] = 3.0185546875, // l
- [109] = 10.69921875, // m
- [110] = 6.9609375, // n
- [111] = 6.67626953125, // o
- [112] = 6.853515625, // p
- [113] = 6.853515625, // q
- [114] = 4.6943359375, // r
- [115] = 5.73095703125, // s
- [116] = 4.33447265625, // t
- [117] = 6.9609375, // u
- [118] = 6.509765625, // v
- [119] = 9.001953125, // w
- [120] = 6.509765625, // x
- [121] = 6.509765625, // y
- [122] = 5.779296875, // z
- [123] = 6.982421875, // {
- [124] = 4.9951171875, // |
- [125] = 6.982421875, // }
- [126] = 9.001953125, // ~
- [127] = 0.0,
- [128] = 0.0,
- [129] = 0.0,
- [130] = 0.0,
- [131] = 0.0,
- [132] = 0.0,
- [133] = 0.0,
- [134] = 0.0,
- [135] = 0.0,
- [136] = 0.0,
- [137] = 0.0,
- [138] = 0.0,
- [139] = 0.0,
- [140] = 0.0,
- [141] = 0.0,
- [142] = 0.0,
- [143] = 0.0,
- [144] = 0.0,
- [145] = 0.0,
- [146] = 0.0,
- [147] = 0.0,
- [148] = 0.0,
- [149] = 0.0,
- [150] = 0.0,
- [151] = 0.0,
- [152] = 0.0,
- [153] = 0.0,
- [154] = 0.0,
- [155] = 0.0,
- [156] = 0.0,
- [157] = 0.0,
- [158] = 0.0,
- [159] = 0.0,
- [160] = 0.0,
- [161] = 0.0,
- [162] = 0.0,
- [163] = 0.0,
- [164] = 0.0,
- [165] = 0.0,
- [166] = 0.0,
- [167] = 0.0,
- [168] = 0.0,
- [169] = 0.0,
- [170] = 0.0,
- [171] = 0.0,
- [172] = 0.0,
- [173] = 0.0,
- [174] = 0.0,
- [175] = 0.0,
- [176] = 0.0,
- [177] = 0.0,
- [178] = 0.0,
- [179] = 0.0,
- [180] = 0.0,
- [181] = 0.0,
- [182] = 0.0,
- [183] = 0.0,
- [184] = 0.0,
- [185] = 0.0,
- [186] = 0.0,
- [187] = 0.0,
- [188] = 0.0,
- [189] = 0.0,
- [190] = 0.0,
- [191] = 0.0,
- [192] = 0.0,
- [193] = 0.0,
- [194] = 0.0,
- [195] = 0.0,
- [196] = 0.0,
- [197] = 0.0,
- [198] = 0.0,
- [199] = 0.0,
- [200] = 0.0,
- [201] = 0.0,
- [202] = 0.0,
- [203] = 0.0,
- [204] = 0.0,
- [205] = 0.0,
- [206] = 0.0,
- [207] = 0.0,
- [208] = 0.0,
- [209] = 0.0,
- [210] = 0.0,
- [211] = 0.0,
- [212] = 0.0,
- [213] = 0.0,
- [214] = 0.0,
- [215] = 0.0,
- [216] = 0.0,
- [217] = 0.0,
- [218] = 0.0,
- [219] = 0.0,
- [220] = 0.0,
- [221] = 0.0,
- [222] = 0.0,
- [223] = 0.0,
- [224] = 0.0,
- [225] = 0.0,
- [226] = 0.0,
- [227] = 0.0,
- [228] = 0.0,
- [229] = 0.0,
- [230] = 0.0,
- [231] = 0.0,
- [232] = 0.0,
- [233] = 0.0,
- [234] = 0.0,
- [235] = 0.0,
- [236] = 0.0,
- [237] = 0.0,
- [238] = 0.0,
- [239] = 0.0,
- [240] = 0.0,
- [241] = 0.0,
- [242] = 0.0,
- [243] = 0.0,
- [244] = 0.0,
- [245] = 0.0,
- [246] = 0.0,
- [247] = 0.0,
- [248] = 0.0,
- [249] = 0.0,
- [250] = 0.0,
- [251] = 0.0,
- [252] = 0.0,
- [253] = 0.0,
- [254] = 0.0,
- [255] = 0.0
-};
-
-// find the width of the string using the verdana 11points font
-// re-write the string in place, skiping zero-length characters
-static inline double verdana11_width(char *s) {
- double w = 0.0;
- char *d = s;
-
- while(*s) {
- double t = verdana11_widths[(unsigned char)*s];
- if(t == 0.0)
- s++;
- else {
- w += t + VERDANA_KERNING;
- if(d != s)
- *d++ = *s++;
- else
- d = ++s;
- }
- }
-
- *d = '\0';
- w -= VERDANA_KERNING;
- w += VERDANA_PADDING;
- return w;
-}
-
-static inline size_t escape_xmlz(char *dst, const char *src, size_t len) {
- size_t i = len;
-
- // required escapes from
- // https://github.com/badges/shields/blob/master/badge.js
- while(*src && i) {
- switch(*src) {
- case '\\':
- *dst++ = '/';
- src++;
- i--;
- break;
-
- case '&':
- if(i > 5) {
- strcpy(dst, "&amp;");
- i -= 5;
- dst += 5;
- src++;
- }
- else goto cleanup;
- break;
-
- case '<':
- if(i > 4) {
- strcpy(dst, "&lt;");
- i -= 4;
- dst += 4;
- src++;
- }
- else goto cleanup;
- break;
-
- case '>':
- if(i > 4) {
- strcpy(dst, "&gt;");
- i -= 4;
- dst += 4;
- src++;
- }
- else goto cleanup;
- break;
-
- case '"':
- if(i > 6) {
- strcpy(dst, "&quot;");
- i -= 6;
- dst += 6;
- src++;
- }
- else goto cleanup;
- break;
-
- case '\'':
- if(i > 6) {
- strcpy(dst, "&apos;");
- i -= 6;
- dst += 6;
- src++;
- }
- else goto cleanup;
- break;
-
- default:
- i--;
- *dst++ = *src++;
- break;
- }
- }
-
-cleanup:
- *dst = '\0';
- return len - i;
-}
-
-static inline char *format_value_with_precision_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) {
- if(unlikely(isnan(value) || isinf(value)))
- value = 0.0;
-
- char *separator = "";
- if(unlikely(isalnum(*units)))
- separator = " ";
-
- if(precision < 0) {
- int len, lstop = 0, trim_zeros = 1;
-
- calculated_number abs = value;
- if(isless(value, 0)) {
- lstop = 1;
- abs = calculated_number_fabs(value);
- }
-
- if(isgreaterequal(abs, 1000)) {
- len = snprintfz(value_string, value_string_len, "%0.0" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- trim_zeros = 0;
- }
- else if(isgreaterequal(abs, 10)) len = snprintfz(value_string, value_string_len, "%0.1" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- else if(isgreaterequal(abs, 1)) len = snprintfz(value_string, value_string_len, "%0.2" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, value_string_len, "%0.2" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- else if(isgreaterequal(abs, 0.01)) len = snprintfz(value_string, value_string_len, "%0.4" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- else if(isgreaterequal(abs, 0.001)) len = snprintfz(value_string, value_string_len, "%0.5" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- else if(isgreaterequal(abs, 0.0001)) len = snprintfz(value_string, value_string_len, "%0.6" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
- else len = snprintfz(value_string, value_string_len, "%0.7" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value);
-
- if(unlikely(trim_zeros)) {
- int l;
- // remove trailing zeros from the decimal part
- for(l = len - 1; l > lstop; l--) {
- if(likely(value_string[l] == '0')) {
- value_string[l] = '\0';
- len--;
- }
-
- else if(unlikely(value_string[l] == '.')) {
- value_string[l] = '\0';
- len--;
- break;
- }
-
- else
- break;
- }
- }
-
- if(unlikely(len <= 0)) len = 1;
- snprintfz(&value_string[len], value_string_len - len, "%s%s", separator, units);
- }
- else {
- if(precision > 50) precision = 50;
- snprintfz(value_string, value_string_len, "%0.*" LONG_DOUBLE_MODIFIER "%s%s", precision, (LONG_DOUBLE) value, separator, units);
- }
-
- return value_string;
-}
-
-inline char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) {
- static uint32_t
- hash_seconds = 0,
- hash_seconds_ago = 0,
- hash_minutes = 0,
- hash_minutes_ago = 0,
- hash_hours = 0,
- hash_hours_ago = 0,
- hash_onoff = 0,
- hash_updown = 0,
- hash_okerror = 0,
- hash_okfailed = 0,
- hash_empty = 0,
- hash_null = 0,
- hash_percentage = 0,
- hash_percent = 0,
- hash_pcent = 0;
-
- if(unlikely(!hash_seconds)) {
- hash_seconds = simple_hash("seconds");
- hash_seconds_ago = simple_hash("seconds ago");
- hash_minutes = simple_hash("minutes");
- hash_minutes_ago = simple_hash("minutes ago");
- hash_hours = simple_hash("hours");
- hash_hours_ago = simple_hash("hours ago");
- hash_onoff = simple_hash("on/off");
- hash_updown = simple_hash("up/down");
- hash_okerror = simple_hash("ok/error");
- hash_okfailed = simple_hash("ok/failed");
- hash_empty = simple_hash("empty");
- hash_null = simple_hash("null");
- hash_percentage = simple_hash("percentage");
- hash_percent = simple_hash("percent");
- hash_pcent = simple_hash("pcent");
- }
-
- if(unlikely(!units)) units = "";
-
- uint32_t hash_units = simple_hash(units);
-
- if(unlikely((hash_units == hash_seconds && !strcmp(units, "seconds")) || (hash_units == hash_seconds_ago && !strcmp(units, "seconds ago")))) {
- if(value == 0.0) {
- snprintfz(value_string, value_string_len, "%s", "now");
- return value_string;
- }
- else if(isnan(value) || isinf(value)) {
- snprintfz(value_string, value_string_len, "%s", "never");
- return value_string;
- }
-
- const char *suffix = (hash_units == hash_seconds_ago)?" ago":"";
-
- size_t s = (size_t)value;
- size_t d = s / 86400;
- s = s % 86400;
-
- size_t h = s / 3600;
- s = s % 3600;
-
- size_t m = s / 60;
- s = s % 60;
-
- if(d)
- snprintfz(value_string, value_string_len, "%zu %s %02zu:%02zu:%02zu%s", d, (d == 1)?"day":"days", h, m, s, suffix);
- else
- snprintfz(value_string, value_string_len, "%02zu:%02zu:%02zu%s", h, m, s, suffix);
-
- return value_string;
- }
-
- else if(unlikely((hash_units == hash_minutes && !strcmp(units, "minutes")) || (hash_units == hash_minutes_ago && !strcmp(units, "minutes ago")))) {
- if(value == 0.0) {
- snprintfz(value_string, value_string_len, "%s", "now");
- return value_string;
- }
- else if(isnan(value) || isinf(value)) {
- snprintfz(value_string, value_string_len, "%s", "never");
- return value_string;
- }
-
- const char *suffix = (hash_units == hash_minutes_ago)?" ago":"";
-
- size_t m = (size_t)value;
- size_t d = m / (60 * 24);
- m = m % (60 * 24);
-
- size_t h = m / 60;
- m = m % 60;
-
- if(d)
- snprintfz(value_string, value_string_len, "%zud %02zuh %02zum%s", d, h, m, suffix);
- else
- snprintfz(value_string, value_string_len, "%zuh %zum%s", h, m, suffix);
-
- return value_string;
- }
-
- else if(unlikely((hash_units == hash_hours && !strcmp(units, "hours")) || (hash_units == hash_hours_ago && !strcmp(units, "hours ago")))) {
- if(value == 0.0) {
- snprintfz(value_string, value_string_len, "%s", "now");
- return value_string;
- }
- else if(isnan(value) || isinf(value)) {
- snprintfz(value_string, value_string_len, "%s", "never");
- return value_string;
- }
-
- const char *suffix = (hash_units == hash_hours_ago)?" ago":"";
-
- size_t h = (size_t)value;
- size_t d = h / 24;
- h = h % 24;
-
- if(d)
- snprintfz(value_string, value_string_len, "%zud %zuh%s", d, h, suffix);
- else
- snprintfz(value_string, value_string_len, "%zuh%s", h, suffix);
-
- return value_string;
- }
-
- else if(unlikely(hash_units == hash_onoff && !strcmp(units, "on/off"))) {
- snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"on":"off");
- return value_string;
- }
-
- else if(unlikely(hash_units == hash_updown && !strcmp(units, "up/down"))) {
- snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"up":"down");
- return value_string;
- }
-
- else if(unlikely(hash_units == hash_okerror && !strcmp(units, "ok/error"))) {
- snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"error");
- return value_string;
- }
-
- else if(unlikely(hash_units == hash_okfailed && !strcmp(units, "ok/failed"))) {
- snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"failed");
- return value_string;
- }
-
- else if(unlikely(hash_units == hash_empty && !strcmp(units, "empty")))
- units = "";
-
- else if(unlikely(hash_units == hash_null && !strcmp(units, "null")))
- units = "";
-
- else if(unlikely(hash_units == hash_percentage && !strcmp(units, "percentage")))
- units = "%";
-
- else if(unlikely(hash_units == hash_percent && !strcmp(units, "percent")))
- units = "%";
-
- else if(unlikely(hash_units == hash_pcent && !strcmp(units, "pcent")))
- units = "%";
-
-
- if(unlikely(isnan(value) || isinf(value))) {
- strcpy(value_string, "-");
- return value_string;
- }
-
- return format_value_with_precision_and_unit(value_string, value_string_len, value, units, precision);
-}
-
-static inline const char *color_map(const char *color) {
- // colors from:
- // https://github.com/badges/shields/blob/master/colorscheme.json
- if(!strcmp(color, "brightgreen")) return "#4c1";
- else if(!strcmp(color, "green")) return "#97CA00";
- else if(!strcmp(color, "yellow")) return "#dfb317";
- else if(!strcmp(color, "yellowgreen")) return "#a4a61d";
- else if(!strcmp(color, "orange")) return "#fe7d37";
- else if(!strcmp(color, "red")) return "#e05d44";
- else if(!strcmp(color, "blue")) return "#007ec6";
- else if(!strcmp(color, "grey")) return "#555";
- else if(!strcmp(color, "gray")) return "#555";
- else if(!strcmp(color, "lightgrey")) return "#9f9f9f";
- else if(!strcmp(color, "lightgray")) return "#9f9f9f";
- return color;
-}
-
-typedef enum color_comparison {
- COLOR_COMPARE_EQUAL,
- COLOR_COMPARE_NOTEQUAL,
- COLOR_COMPARE_LESS,
- COLOR_COMPARE_LESSEQUAL,
- COLOR_COMPARE_GREATER,
- COLOR_COMPARE_GREATEREQUAL,
-} BADGE_COLOR_COMPARISON;
-
-static inline void calc_colorz(const char *color, char *final, size_t len, calculated_number value) {
- if(isnan(value) || isinf(value))
- value = NAN;
-
- char color_buffer[256 + 1] = "";
- char value_buffer[256 + 1] = "";
- BADGE_COLOR_COMPARISON comparison = COLOR_COMPARE_GREATER;
-
- // example input:
- // color<max|color>min|color:null...
-
- const char *c = color;
- while(*c) {
- char *dc = color_buffer, *dv = NULL;
- size_t ci = 0, vi = 0;
-
- const char *t = c;
-
- while(*t && *t != '|') {
- switch(*t) {
- case '!':
- if(t[1] == '=') t++;
- comparison = COLOR_COMPARE_NOTEQUAL;
- dv = value_buffer;
- break;
-
- case '=':
- case ':':
- comparison = COLOR_COMPARE_EQUAL;
- dv = value_buffer;
- break;
-
- case '}':
- case ')':
- case '>':
- if(t[1] == '=') {
- comparison = COLOR_COMPARE_GREATEREQUAL;
- t++;
- }
- else
- comparison = COLOR_COMPARE_GREATER;
- dv = value_buffer;
- break;
-
- case '{':
- case '(':
- case '<':
- if(t[1] == '=') {
- comparison = COLOR_COMPARE_LESSEQUAL;
- t++;
- }
- else if(t[1] == '>' || t[1] == ')' || t[1] == '}') {
- comparison = COLOR_COMPARE_NOTEQUAL;
- t++;
- }
- else
- comparison = COLOR_COMPARE_LESS;
- dv = value_buffer;
- break;
-
- default:
- if(dv) {
- if(vi < 256) {
- vi++;
- *dv++ = *t;
- }
- }
- else {
- if(ci < 256) {
- ci++;
- *dc++ = *t;
- }
- }
- break;
- }
-
- t++;
- }
-
- // prepare for next iteration
- if(*t == '|') t++;
- c = t;
-
- // do the math
- *dc = '\0';
- if(dv) {
- *dv = '\0';
- calculated_number v;
-
- if(!*value_buffer || !strcmp(value_buffer, "null")) {
- v = NAN;
- }
- else {
- v = str2l(value_buffer);
- if(isnan(v) || isinf(v))
- v = NAN;
- }
-
- if(unlikely(isnan(value) || isnan(v))) {
- if(isnan(value) && isnan(v))
- break;
- }
- else {
- if (unlikely(comparison == COLOR_COMPARE_LESS && isless(value, v))) break;
- else if (unlikely(comparison == COLOR_COMPARE_LESSEQUAL && islessequal(value, v))) break;
- else if (unlikely(comparison == COLOR_COMPARE_GREATER && isgreater(value, v))) break;
- else if (unlikely(comparison == COLOR_COMPARE_GREATEREQUAL && isgreaterequal(value, v))) break;
- else if (unlikely(comparison == COLOR_COMPARE_EQUAL && !islessgreater(value, v))) break;
- else if (unlikely(comparison == COLOR_COMPARE_NOTEQUAL && islessgreater(value, v))) break;
- }
- }
- else
- break;
- }
-
- const char *b;
- if(color_buffer[0])
- b = color_buffer;
- else
- b = color;
-
- strncpyz(final, b, len);
-}
-
-// value + units
-#define VALUE_STRING_SIZE 100
-
-// label
-#define LABEL_STRING_SIZE 200
-
-// colors
-#define COLOR_STRING_SIZE 100
-
-void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options) {
- char label_buffer[LABEL_STRING_SIZE + 1]
- , value_color_buffer[COLOR_STRING_SIZE + 1]
- , value_string[VALUE_STRING_SIZE + 1]
- , label_escaped[LABEL_STRING_SIZE + 1]
- , value_escaped[VALUE_STRING_SIZE + 1]
- , label_color_escaped[COLOR_STRING_SIZE + 1]
- , value_color_escaped[COLOR_STRING_SIZE + 1];
-
- double label_width, value_width, total_width, height = 20.0, font_size = 11.0, text_offset = 5.8, round_corner = 3.0;
-
- if(scale < 100) scale = 100;
-
- if(unlikely(!label_color || !*label_color))
- label_color = "#555";
-
- if(unlikely(!value_color || !*value_color))
- value_color = (isnan(value) || isinf(value))?"#999":"#4c1";
-
- calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value);
- format_value_and_unit(value_string, VALUE_STRING_SIZE, (options & RRDR_OPTION_DISPLAY_ABS)?calculated_number_fabs(value):value, units, precision);
-
- // we need to copy the label, since verdana11_width may write to it
- strncpyz(label_buffer, label, LABEL_STRING_SIZE);
-
- label_width = verdana11_width(label_buffer) + (BADGE_HORIZONTAL_PADDING * 2);
- value_width = verdana11_width(value_string) + (BADGE_HORIZONTAL_PADDING * 2);
- total_width = label_width + value_width;
-
- escape_xmlz(label_escaped, label_buffer, LABEL_STRING_SIZE);
- escape_xmlz(value_escaped, value_string, VALUE_STRING_SIZE);
- escape_xmlz(label_color_escaped, color_map(label_color), COLOR_STRING_SIZE);
- escape_xmlz(value_color_escaped, color_map(value_color_buffer), COLOR_STRING_SIZE);
-
- wb->contenttype = CT_IMAGE_SVG_XML;
-
- total_width = total_width * scale / 100.0;
- height = height * scale / 100.0;
- font_size = font_size * scale / 100.0;
- text_offset = text_offset * scale / 100.0;
- label_width = label_width * scale / 100.0;
- value_width = value_width * scale / 100.0;
- round_corner = round_corner * scale / 100.0;
-
- // svg template from:
- // https://raw.githubusercontent.com/badges/shields/master/templates/flat-template.svg
- buffer_sprintf(wb,
- "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"%0.2f\" height=\"%0.2f\">"
- "<linearGradient id=\"smooth\" x2=\"0\" y2=\"100%%\">"
- "<stop offset=\"0\" stop-color=\"#bbb\" stop-opacity=\".1\"/>"
- "<stop offset=\"1\" stop-opacity=\".1\"/>"
- "</linearGradient>"
- "<mask id=\"round\">"
- "<rect width=\"%0.2f\" height=\"%0.2f\" rx=\"%0.2f\" fill=\"#fff\"/>"
- "</mask>"
- "<g mask=\"url(#round)\">"
- "<rect width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>"
- "<rect x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>"
- "<rect width=\"%0.2f\" height=\"%0.2f\" fill=\"url(#smooth)\"/>"
- "</g>"
- "<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"%0.2f\">"
- "<text x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
- "<text x=\"%0.2f\" y=\"%0.0f\">%s</text>"
- "<text x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
- "<text x=\"%0.2f\" y=\"%0.0f\">%s</text>"
- "</g>"
- "</svg>",
- total_width, height,
- total_width, height, round_corner,
- label_width, height, label_color_escaped,
- label_width, value_width, height, value_color_escaped,
- total_width, height,
- font_size,
- label_width / 2, ceil(height - text_offset), label_escaped,
- label_width / 2, ceil(height - text_offset - 1.0), label_escaped,
- label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped,
- label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped);
-}
diff --git a/src/web_buffer_svg.h b/src/web_buffer_svg.h
deleted file mode 100644
index c23abf0dc..000000000
--- a/src/web_buffer_svg.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef NETDATA_WEB_BUFFER_SVG_H
-#define NETDATA_WEB_BUFFER_SVG_H 1
-
-extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options);
-extern char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision);
-
-#endif /* NETDATA_WEB_BUFFER_SVG_H */
diff --git a/src/web_client.c b/src/web_client.c
deleted file mode 100644
index 477fb3d57..000000000
--- a/src/web_client.c
+++ /dev/null
@@ -1,1706 +0,0 @@
-#include "common.h"
-
-// this is an async I/O implementation of the web server request parser
-// it is used by all netdata web servers
-
-int respect_web_browser_do_not_track_policy = 0;
-char *web_x_frame_options = NULL;
-
-#ifdef NETDATA_WITH_ZLIB
-int web_enable_gzip = 1, web_gzip_level = 3, web_gzip_strategy = Z_DEFAULT_STRATEGY;
-#endif /* NETDATA_WITH_ZLIB */
-
-inline int web_client_permission_denied(struct web_client *w) {
- w->response.data->contenttype = CT_TEXT_PLAIN;
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "You are not allowed to access this resource.");
- w->response.code = 403;
- return 403;
-}
-
-static inline int web_client_crock_socket(struct web_client *w) {
-#ifdef TCP_CORK
- if(likely(web_client_is_corkable(w) && !w->tcp_cork && w->ofd != -1)) {
- w->tcp_cork = 1;
- if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
- error("%llu: failed to enable TCP_CORK on socket.", w->id);
-
- w->tcp_cork = 0;
- return -1;
- }
- }
-#else
- (void)w;
-#endif /* TCP_CORK */
-
- return 0;
-}
-
-static inline int web_client_uncrock_socket(struct web_client *w) {
-#ifdef TCP_CORK
- if(likely(w->tcp_cork && w->ofd != -1)) {
- w->tcp_cork = 0;
- if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
- error("%llu: failed to disable TCP_CORK on socket.", w->id);
- w->tcp_cork = 1;
- return -1;
- }
- }
-#else
- (void)w;
-#endif /* TCP_CORK */
-
- return 0;
-}
-
-void web_client_request_done(struct web_client *w) {
- web_client_uncrock_socket(w);
-
- debug(D_WEB_CLIENT, "%llu: Resetting client.", w->id);
-
- if(likely(w->last_url[0])) {
- struct timeval tv;
- now_realtime_timeval(&tv);
-
- size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
- size_t sent = size;
-#ifdef NETDATA_WITH_ZLIB
- if(likely(w->response.zoutput)) sent = (size_t)w->response.zstream.total_out;
-#endif
-
- // --------------------------------------------------------------------
- // global statistics
-
- finished_web_request_statistics(dt_usec(&tv, &w->tv_in),
- w->stats_received_bytes,
- w->stats_sent_bytes,
- size,
- sent);
-
- w->stats_received_bytes = 0;
- w->stats_sent_bytes = 0;
-
-
- // --------------------------------------------------------------------
-
- const char *mode;
- switch(w->mode) {
- case WEB_CLIENT_MODE_FILECOPY:
- mode = "FILECOPY";
- break;
-
- case WEB_CLIENT_MODE_OPTIONS:
- mode = "OPTIONS";
- break;
-
- case WEB_CLIENT_MODE_STREAM:
- mode = "STREAM";
- break;
-
- case WEB_CLIENT_MODE_NORMAL:
- mode = "DATA";
- break;
-
- default:
- mode = "UNKNOWN";
- break;
- }
-
- // access log
- log_access("%llu: %d '[%s]:%s' '%s' (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %d '%s'",
- w->id
- , gettid()
- , w->client_ip
- , w->client_port
- , mode
- , sent
- , size
- , -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0)
- , dt_usec(&w->tv_ready, &w->tv_in) / 1000.0
- , dt_usec(&tv, &w->tv_ready) / 1000.0
- , dt_usec(&tv, &w->tv_in) / 1000.0
- , w->response.code
- , w->last_url
- );
- }
-
- if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
- if(w->ifd != w->ofd) {
- debug(D_WEB_CLIENT, "%llu: Closing filecopy input file descriptor %d.", w->id, w->ifd);
-
- if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
- if (w->ifd != -1) close(w->ifd);
- }
-
- w->ifd = w->ofd;
- }
- }
-
- w->last_url[0] = '\0';
- w->cookie1[0] = '\0';
- w->cookie2[0] = '\0';
- w->origin[0] = '*';
- w->origin[1] = '\0';
-
- freez(w->user_agent); w->user_agent = NULL;
-
- w->mode = WEB_CLIENT_MODE_NORMAL;
-
- w->tcp_cork = 0;
- web_client_disable_donottrack(w);
- web_client_disable_tracking_required(w);
- web_client_disable_keepalive(w);
- w->decoded_url[0] = '\0';
-
- buffer_reset(w->response.header_output);
- buffer_reset(w->response.header);
- buffer_reset(w->response.data);
- w->response.rlen = 0;
- w->response.sent = 0;
- w->response.code = 0;
-
- w->header_parse_tries = 0;
- w->header_parse_last_size = 0;
-
- web_client_enable_wait_receive(w);
- web_client_disable_wait_send(w);
-
- w->response.zoutput = 0;
-
- // if we had enabled compression, release it
-#ifdef NETDATA_WITH_ZLIB
- if(w->response.zinitialized) {
- debug(D_DEFLATE, "%llu: Freeing compression resources.", w->id);
- deflateEnd(&w->response.zstream);
- w->response.zsent = 0;
- w->response.zhave = 0;
- w->response.zstream.avail_in = 0;
- w->response.zstream.avail_out = 0;
- w->response.zstream.total_in = 0;
- w->response.zstream.total_out = 0;
- w->response.zinitialized = 0;
- }
-#endif // NETDATA_WITH_ZLIB
-}
-
-uid_t web_files_uid(void) {
- static char *web_owner = NULL;
- static uid_t owner_uid = 0;
-
- if(unlikely(!web_owner)) {
- // getpwuid() is not thread safe,
- // but we have called this function once
- // while single threaded
- struct passwd *pw = getpwuid(geteuid());
- web_owner = config_get(CONFIG_SECTION_WEB, "web files owner", (pw)?(pw->pw_name?pw->pw_name:""):"");
- if(!web_owner || !*web_owner)
- owner_uid = geteuid();
- else {
- // getpwnam() is not thread safe,
- // but we have called this function once
- // while single threaded
- pw = getpwnam(web_owner);
- if(!pw) {
- error("User '%s' is not present. Ignoring option.", web_owner);
- owner_uid = geteuid();
- }
- else {
- debug(D_WEB_CLIENT, "Web files owner set to %s.", web_owner);
- owner_uid = pw->pw_uid;
- }
- }
- }
-
- return(owner_uid);
-}
-
-gid_t web_files_gid(void) {
- static char *web_group = NULL;
- static gid_t owner_gid = 0;
-
- if(unlikely(!web_group)) {
- // getgrgid() is not thread safe,
- // but we have called this function once
- // while single threaded
- struct group *gr = getgrgid(getegid());
- web_group = config_get(CONFIG_SECTION_WEB, "web files group", (gr)?(gr->gr_name?gr->gr_name:""):"");
- if(!web_group || !*web_group)
- owner_gid = getegid();
- else {
- // getgrnam() is not thread safe,
- // but we have called this function once
- // while single threaded
- gr = getgrnam(web_group);
- if(!gr) {
- error("Group '%s' is not present. Ignoring option.", web_group);
- owner_gid = getegid();
- }
- else {
- debug(D_WEB_CLIENT, "Web files group set to %s.", web_group);
- owner_gid = gr->gr_gid;
- }
- }
- }
-
- return(owner_gid);
-}
-
-static struct {
- const char *extension;
- uint32_t hash;
- uint8_t contenttype;
-} mime_types[] = {
- { "html" , 0 , CT_TEXT_HTML}
- , {"js" , 0 , CT_APPLICATION_X_JAVASCRIPT}
- , {"css" , 0 , CT_TEXT_CSS}
- , {"xml" , 0 , CT_TEXT_XML}
- , {"xsl" , 0 , CT_TEXT_XSL}
- , {"txt" , 0 , CT_TEXT_PLAIN}
- , {"svg" , 0 , CT_IMAGE_SVG_XML}
- , {"ttf" , 0 , CT_APPLICATION_X_FONT_TRUETYPE}
- , {"otf" , 0 , CT_APPLICATION_X_FONT_OPENTYPE}
- , {"woff2", 0 , CT_APPLICATION_FONT_WOFF2}
- , {"woff" , 0 , CT_APPLICATION_FONT_WOFF}
- , {"eot" , 0 , CT_APPLICATION_VND_MS_FONTOBJ}
- , {"png" , 0 , CT_IMAGE_PNG}
- , {"jpg" , 0 , CT_IMAGE_JPG}
- , {"jpeg" , 0 , CT_IMAGE_JPG}
- , {"gif" , 0 , CT_IMAGE_GIF}
- , {"bmp" , 0 , CT_IMAGE_BMP}
- , {"ico" , 0 , CT_IMAGE_XICON}
- , {"icns" , 0 , CT_IMAGE_ICNS}
- , { NULL, 0, 0}
-};
-
-static inline uint8_t contenttype_for_filename(const char *filename) {
- // info("checking filename '%s'", filename);
-
- static int initialized = 0;
- int i;
-
- if(unlikely(!initialized)) {
- for (i = 0; mime_types[i].extension; i++)
- mime_types[i].hash = simple_hash(mime_types[i].extension);
-
- initialized = 1;
- }
-
- const char *s = filename, *last_dot = NULL;
-
- // find the last dot
- while(*s) {
- if(unlikely(*s == '.')) last_dot = s;
- s++;
- }
-
- if(unlikely(!last_dot || !*last_dot || !last_dot[1])) {
- // info("no extension for filename '%s'", filename);
- return CT_APPLICATION_OCTET_STREAM;
- }
- last_dot++;
-
- // info("extension for filename '%s' is '%s'", filename, last_dot);
-
- uint32_t hash = simple_hash(last_dot);
- for(i = 0; mime_types[i].extension ; i++) {
- if(unlikely(hash == mime_types[i].hash && !strcmp(last_dot, mime_types[i].extension))) {
- // info("matched extension for filename '%s': '%s'", filename, last_dot);
- return mime_types[i].contenttype;
- }
- }
-
- // info("not matched extension for filename '%s': '%s'", filename, last_dot);
- return CT_APPLICATION_OCTET_STREAM;
-}
-
-static inline int access_to_file_is_not_permitted(struct web_client *w, const char *filename) {
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "Access to file is not permitted: ");
- buffer_strcat_htmlescape(w->response.data, filename);
- return 403;
-}
-
-int mysendfile(struct web_client *w, char *filename) {
- debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, netdata_configured_web_dir, filename);
-
- if(!web_client_can_access_dashboard(w))
- return web_client_permission_denied(w);
-
- // skip leading slashes
- while (*filename == '/') filename++;
-
- // if the filename contain known paths, skip them
- if(strncmp(filename, WEB_PATH_FILE "/", strlen(WEB_PATH_FILE) + 1) == 0)
- filename = &filename[strlen(WEB_PATH_FILE) + 1];
-
- // if the filename contains "strange" characters, refuse to serve it
- char *s;
- for(s = filename; *s ;s++) {
- if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_sprintf(w->response.data, "Filename contains invalid characters: ");
- buffer_strcat_htmlescape(w->response.data, filename);
- return 400;
- }
- }
-
- // if the filename contains a .. refuse to serve it
- if(strstr(filename, "..") != 0) {
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "Relative filenames are not supported: ");
- buffer_strcat_htmlescape(w->response.data, filename);
- return 400;
- }
-
- // find the physical file on disk
- char webfilename[FILENAME_MAX + 1];
- snprintfz(webfilename, FILENAME_MAX, "%s/%s", netdata_configured_web_dir, filename);
-
- struct stat statbuf;
- int done = 0;
- while(!done) {
- // check if the file exists
- if (lstat(webfilename, &statbuf) != 0) {
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "File does not exist, or is not accessible: ");
- buffer_strcat_htmlescape(w->response.data, webfilename);
- return 404;
- }
-
- if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
- snprintfz(webfilename, FILENAME_MAX, "%s/%s/index.html", netdata_configured_web_dir, filename);
- continue;
- }
-
- if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
- error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
- return access_to_file_is_not_permitted(w, webfilename);
- }
-
- // check if the file is owned by expected user
- if (statbuf.st_uid != web_files_uid()) {
- error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, statbuf.st_uid, web_files_uid());
- return access_to_file_is_not_permitted(w, webfilename);
- }
-
- // check if the file is owned by expected group
- if (statbuf.st_gid != web_files_gid()) {
- error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, statbuf.st_gid, web_files_gid());
- return access_to_file_is_not_permitted(w, webfilename);
- }
-
- done = 1;
- }
-
- // open the file
- w->ifd = open(webfilename, O_NONBLOCK, O_RDONLY);
- if(w->ifd == -1) {
- w->ifd = w->ofd;
-
- if(errno == EBUSY || errno == EAGAIN) {
- error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
- buffer_strcat(w->response.data, "File is currently busy, please try again later: ");
- buffer_strcat_htmlescape(w->response.data, webfilename);
- return 307;
- }
- else {
- error("%llu: Cannot open file '%s'.", w->id, webfilename);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "Cannot open file: ");
- buffer_strcat_htmlescape(w->response.data, webfilename);
- return 404;
- }
- }
-
- sock_setnonblock(w->ifd);
-
- w->response.data->contenttype = contenttype_for_filename(webfilename);
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, statbuf.st_size, w->ifd, w->ofd);
-
- w->mode = WEB_CLIENT_MODE_FILECOPY;
- web_client_enable_wait_receive(w);
- web_client_disable_wait_send(w);
- buffer_flush(w->response.data);
- buffer_need_bytes(w->response.data, (size_t)statbuf.st_size);
- w->response.rlen = (size_t)statbuf.st_size;
-#ifdef __APPLE__
- w->response.data->date = statbuf.st_mtimespec.tv_sec;
-#else
- w->response.data->date = statbuf.st_mtim.tv_sec;
-#endif /* __APPLE__ */
- buffer_cacheable(w->response.data);
-
- return 200;
-}
-
-
-#ifdef NETDATA_WITH_ZLIB
-void web_client_enable_deflate(struct web_client *w, int gzip) {
- if(unlikely(w->response.zinitialized)) {
- debug(D_DEFLATE, "%llu: Compression has already be initialized for this client.", w->id);
- return;
- }
-
- if(unlikely(w->response.sent)) {
- error("%llu: Cannot enable compression in the middle of a conversation.", w->id);
- return;
- }
-
- w->response.zstream.zalloc = Z_NULL;
- w->response.zstream.zfree = Z_NULL;
- w->response.zstream.opaque = Z_NULL;
-
- w->response.zstream.next_in = (Bytef *)w->response.data->buffer;
- w->response.zstream.avail_in = 0;
- w->response.zstream.total_in = 0;
-
- w->response.zstream.next_out = w->response.zbuffer;
- w->response.zstream.avail_out = 0;
- w->response.zstream.total_out = 0;
-
- w->response.zstream.zalloc = Z_NULL;
- w->response.zstream.zfree = Z_NULL;
- w->response.zstream.opaque = Z_NULL;
-
-// if(deflateInit(&w->response.zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
-// error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
-// return;
-// }
-
- // Select GZIP compression: windowbits = 15 + 16 = 31
- if(deflateInit2(&w->response.zstream, web_gzip_level, Z_DEFLATED, 15 + ((gzip)?16:0), 8, web_gzip_strategy) != Z_OK) {
- error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
- return;
- }
-
- w->response.zsent = 0;
- w->response.zoutput = 1;
- w->response.zinitialized = 1;
-
- debug(D_DEFLATE, "%llu: Initialized compression.", w->id);
-}
-#endif // NETDATA_WITH_ZLIB
-
-void buffer_data_options2string(BUFFER *wb, uint32_t options) {
- int count = 0;
-
- if(options & RRDR_OPTION_NONZERO) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "nonzero");
- }
-
- if(options & RRDR_OPTION_REVERSED) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "flip");
- }
-
- if(options & RRDR_OPTION_JSON_WRAP) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "jsonwrap");
- }
-
- if(options & RRDR_OPTION_MIN2MAX) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "min2max");
- }
-
- if(options & RRDR_OPTION_MILLISECONDS) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "ms");
- }
-
- if(options & RRDR_OPTION_ABSOLUTE) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "absolute");
- }
-
- if(options & RRDR_OPTION_SECONDS) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "seconds");
- }
-
- if(options & RRDR_OPTION_NULL2ZERO) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "null2zero");
- }
-
- if(options & RRDR_OPTION_OBJECTSROWS) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "objectrows");
- }
-
- if(options & RRDR_OPTION_GOOGLE_JSON) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "google_json");
- }
-
- if(options & RRDR_OPTION_PERCENTAGE) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "percentage");
- }
-
- if(options & RRDR_OPTION_NOT_ALIGNED) {
- if(count++) buffer_strcat(wb, " ");
- buffer_strcat(wb, "unaligned");
- }
-}
-
-const char *group_method2string(int group) {
- switch(group) {
- case GROUP_UNDEFINED:
- return "";
-
- case GROUP_AVERAGE:
- return "average";
-
- case GROUP_MIN:
- return "min";
-
- case GROUP_MAX:
- return "max";
-
- case GROUP_SUM:
- return "sum";
-
- case GROUP_INCREMENTAL_SUM:
- return "incremental-sum";
-
- default:
- return "unknown-group-method";
- }
-}
-
-static inline int check_host_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) {
- if(unlikely(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) {
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "This host does not maintain a database");
- return 400;
- }
-
- return func(host, w, url);
-}
-
-static inline int check_host_and_dashboard_acl_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) {
- if(!web_client_can_access_dashboard(w))
- return web_client_permission_denied(w);
-
- return check_host_and_call(host, w, url, func);
-}
-
-int web_client_api_request(RRDHOST *host, struct web_client *w, char *url)
-{
- // get the api version
- char *tok = mystrsep(&url, "/?&");
- if(tok && *tok) {
- debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
- if(strcmp(tok, "v1") == 0)
- return web_client_api_request_v1(host, w, url);
- else {
- buffer_flush(w->response.data);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "Unsupported API version: ");
- buffer_strcat_htmlescape(w->response.data, tok);
- return 404;
- }
- }
- else {
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Which API version?");
- return 400;
- }
-}
-
-const char *web_content_type_to_string(uint8_t contenttype) {
- switch(contenttype) {
- case CT_TEXT_HTML:
- return "text/html; charset=utf-8";
-
- case CT_APPLICATION_XML:
- return "application/xml; charset=utf-8";
-
- case CT_APPLICATION_JSON:
- return "application/json; charset=utf-8";
-
- case CT_APPLICATION_X_JAVASCRIPT:
- return "application/x-javascript; charset=utf-8";
-
- case CT_TEXT_CSS:
- return "text/css; charset=utf-8";
-
- case CT_TEXT_XML:
- return "text/xml; charset=utf-8";
-
- case CT_TEXT_XSL:
- return "text/xsl; charset=utf-8";
-
- case CT_APPLICATION_OCTET_STREAM:
- return "application/octet-stream";
-
- case CT_IMAGE_SVG_XML:
- return "image/svg+xml";
-
- case CT_APPLICATION_X_FONT_TRUETYPE:
- return "application/x-font-truetype";
-
- case CT_APPLICATION_X_FONT_OPENTYPE:
- return "application/x-font-opentype";
-
- case CT_APPLICATION_FONT_WOFF:
- return "application/font-woff";
-
- case CT_APPLICATION_FONT_WOFF2:
- return "application/font-woff2";
-
- case CT_APPLICATION_VND_MS_FONTOBJ:
- return "application/vnd.ms-fontobject";
-
- case CT_IMAGE_PNG:
- return "image/png";
-
- case CT_IMAGE_JPG:
- return "image/jpeg";
-
- case CT_IMAGE_GIF:
- return "image/gif";
-
- case CT_IMAGE_XICON:
- return "image/x-icon";
-
- case CT_IMAGE_BMP:
- return "image/bmp";
-
- case CT_IMAGE_ICNS:
- return "image/icns";
-
- case CT_PROMETHEUS:
- return "text/plain; version=0.0.4";
-
- default:
- case CT_TEXT_PLAIN:
- return "text/plain; charset=utf-8";
- }
-}
-
-
-const char *web_response_code_to_string(int code) {
- switch(code) {
- case 200:
- return "OK";
-
- case 307:
- return "Temporary Redirect";
-
- case 400:
- return "Bad Request";
-
- case 403:
- return "Forbidden";
-
- case 404:
- return "Not Found";
-
- case 412:
- return "Preconditions Failed";
-
- default:
- if(code >= 100 && code < 200)
- return "Informational";
-
- if(code >= 200 && code < 300)
- return "Successful";
-
- if(code >= 300 && code < 400)
- return "Redirection";
-
- if(code >= 400 && code < 500)
- return "Bad Request";
-
- if(code >= 500 && code < 600)
- return "Server Error";
-
- return "Undefined Error";
- }
-}
-
-static inline char *http_header_parse(struct web_client *w, char *s, int parse_useragent) {
- static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0, hash_useragent = 0;
-
- if(unlikely(!hash_origin)) {
- hash_origin = simple_uhash("Origin");
- hash_connection = simple_uhash("Connection");
- hash_accept_encoding = simple_uhash("Accept-Encoding");
- hash_donottrack = simple_uhash("DNT");
- hash_useragent = simple_uhash("User-Agent");
- }
-
- char *e = s;
-
- // find the :
- while(*e && *e != ':') e++;
- if(!*e) return e;
-
- // get the name
- *e = '\0';
-
- // find the value
- char *v = e + 1, *ve;
-
- // skip leading spaces from value
- while(*v == ' ') v++;
- ve = v;
-
- // find the \r
- while(*ve && *ve != '\r') ve++;
- if(!*ve || ve[1] != '\n') {
- *e = ':';
- return ve;
- }
-
- // terminate the value
- *ve = '\0';
-
- // fprintf(stderr, "HEADER: '%s' = '%s'\n", s, v);
- uint32_t hash = simple_uhash(s);
-
- if(hash == hash_origin && !strcasecmp(s, "Origin"))
- strncpyz(w->origin, v, NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE);
-
- else if(hash == hash_connection && !strcasecmp(s, "Connection")) {
- if(strcasestr(v, "keep-alive"))
- web_client_enable_keepalive(w);
- }
- else if(respect_web_browser_do_not_track_policy && hash == hash_donottrack && !strcasecmp(s, "DNT")) {
- if(*v == '0') web_client_disable_donottrack(w);
- else if(*v == '1') web_client_enable_donottrack(w);
- }
- else if(parse_useragent && hash == hash_useragent && !strcasecmp(s, "User-Agent")) {
- w->user_agent = strdupz(v);
- }
-#ifdef NETDATA_WITH_ZLIB
- else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
- if(web_enable_gzip) {
- if(strcasestr(v, "gzip"))
- web_client_enable_deflate(w, 1);
- //
- // does not seem to work
- // else if(strcasestr(v, "deflate"))
- // web_client_enable_deflate(w, 0);
- }
- }
-#endif /* NETDATA_WITH_ZLIB */
-
- *e = ':';
- *ve = '\r';
- return ve;
-}
-
-// http_request_validate()
-// returns:
-// = 0 : all good, process the request
-// > 0 : request is not supported
-// < 0 : request is incomplete - wait for more data
-
-typedef enum {
- HTTP_VALIDATION_OK,
- HTTP_VALIDATION_NOT_SUPPORTED,
- HTTP_VALIDATION_INCOMPLETE
-} HTTP_VALIDATION;
-
-static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
- char *s = (char *)buffer_tostring(w->response.data), *encoded_url = NULL;
-
- size_t last_pos = w->header_parse_last_size;
- if(last_pos > 4) last_pos -= 4; // allow searching for \r\n\r\n
- else last_pos = 0;
-
- w->header_parse_tries++;
- w->header_parse_last_size = buffer_strlen(w->response.data);
-
- if(w->header_parse_tries > 1) {
- if(w->header_parse_last_size < last_pos)
- last_pos = 0;
-
- if(strstr(&s[last_pos], "\r\n\r\n") == NULL) {
- if(w->header_parse_tries > 10) {
- info("Disabling slow client after %zu attempts to read the request (%zu bytes received)", w->header_parse_tries, buffer_strlen(w->response.data));
- w->header_parse_tries = 0;
- w->header_parse_last_size = 0;
- web_client_disable_wait_receive(w);
- return HTTP_VALIDATION_NOT_SUPPORTED;
- }
-
- return HTTP_VALIDATION_INCOMPLETE;
- }
- }
-
- // is is a valid request?
- if(!strncmp(s, "GET ", 4)) {
- encoded_url = s = &s[4];
- w->mode = WEB_CLIENT_MODE_NORMAL;
- }
- else if(!strncmp(s, "OPTIONS ", 8)) {
- encoded_url = s = &s[8];
- w->mode = WEB_CLIENT_MODE_OPTIONS;
- }
- else if(!strncmp(s, "STREAM ", 7)) {
- encoded_url = s = &s[7];
- w->mode = WEB_CLIENT_MODE_STREAM;
- }
- else {
- w->header_parse_tries = 0;
- w->header_parse_last_size = 0;
- web_client_disable_wait_receive(w);
- return HTTP_VALIDATION_NOT_SUPPORTED;
- }
-
- // find the SPACE + "HTTP/"
- while(*s) {
- // find the next space
- while (*s && *s != ' ') s++;
-
- // is it SPACE + "HTTP/" ?
- if(*s && !strncmp(s, " HTTP/", 6)) break;
- else s++;
- }
-
- // incomplete requests
- if(unlikely(!*s)) {
- web_client_enable_wait_receive(w);
- return HTTP_VALIDATION_INCOMPLETE;
- }
-
- // we have the end of encoded_url - remember it
- char *ue = s;
-
- // make sure we have complete request
- // complete requests contain: \r\n\r\n
- while(*s) {
- // find a line feed
- while(*s && *s++ != '\r');
-
- // did we reach the end?
- if(unlikely(!*s)) break;
-
- // is it \r\n ?
- if(likely(*s++ == '\n')) {
-
- // is it again \r\n ? (header end)
- if(unlikely(*s == '\r' && s[1] == '\n')) {
- // a valid complete HTTP request found
-
- *ue = '\0';
- url_decode_r(w->decoded_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE + 1);
- *ue = ' ';
-
- // copy the URL - we are going to overwrite parts of it
- // FIXME -- we should avoid it
- strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE);
-
- w->header_parse_tries = 0;
- w->header_parse_last_size = 0;
- web_client_disable_wait_receive(w);
- return HTTP_VALIDATION_OK;
- }
-
- // another header line
- s = http_header_parse(w, s,
- (w->mode == WEB_CLIENT_MODE_STREAM) // parse user agent
- );
- }
- }
-
- // incomplete request
- web_client_enable_wait_receive(w);
- return HTTP_VALIDATION_INCOMPLETE;
-}
-
-static inline void web_client_send_http_header(struct web_client *w) {
- if(unlikely(w->response.code != 200))
- buffer_no_cacheable(w->response.data);
-
- // set a proper expiration date, if not already set
- if(unlikely(!w->response.data->expires)) {
- if(w->response.data->options & WB_CONTENT_NO_CACHEABLE)
- w->response.data->expires = w->tv_ready.tv_sec + localhost->rrd_update_every;
- else
- w->response.data->expires = w->tv_ready.tv_sec + 86400;
- }
-
- // prepare the HTTP response header
- debug(D_WEB_CLIENT, "%llu: Generating HTTP header with response %d.", w->id, w->response.code);
-
- const char *content_type_string = web_content_type_to_string(w->response.data->contenttype);
- const char *code_msg = web_response_code_to_string(w->response.code);
-
- // prepare the last modified and expiration dates
- char date[32], edate[32];
- {
- struct tm tmbuf, *tm;
-
- tm = gmtime_r(&w->response.data->date, &tmbuf);
- strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %Z", tm);
-
- tm = gmtime_r(&w->response.data->expires, &tmbuf);
- strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", tm);
- }
-
- buffer_sprintf(w->response.header_output,
- "HTTP/1.1 %d %s\r\n"
- "Connection: %s\r\n"
- "Server: NetData Embedded HTTP Server v%s\r\n"
- "Access-Control-Allow-Origin: %s\r\n"
- "Access-Control-Allow-Credentials: true\r\n"
- "Content-Type: %s\r\n"
- "Date: %s\r\n"
- , w->response.code, code_msg
- , web_client_has_keepalive(w)?"keep-alive":"close"
- , VERSION
- , w->origin
- , content_type_string
- , date
- );
-
- if(unlikely(web_x_frame_options))
- buffer_sprintf(w->response.header_output, "X-Frame-Options: %s\r\n", web_x_frame_options);
-
- if(w->cookie1[0] || w->cookie2[0]) {
- if(w->cookie1[0]) {
- buffer_sprintf(w->response.header_output,
- "Set-Cookie: %s\r\n",
- w->cookie1);
- }
-
- if(w->cookie2[0]) {
- buffer_sprintf(w->response.header_output,
- "Set-Cookie: %s\r\n",
- w->cookie2);
- }
-
- if(respect_web_browser_do_not_track_policy)
- buffer_sprintf(w->response.header_output,
- "Tk: T;cookies\r\n");
- }
- else {
- if(respect_web_browser_do_not_track_policy) {
- if(web_client_has_tracking_required(w))
- buffer_sprintf(w->response.header_output,
- "Tk: T;cookies\r\n");
- else
- buffer_sprintf(w->response.header_output,
- "Tk: N\r\n");
- }
- }
-
- if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
- buffer_strcat(w->response.header_output,
- "Access-Control-Allow-Methods: GET, OPTIONS\r\n"
- "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie, pragma, cache-control\r\n"
- "Access-Control-Max-Age: 1209600\r\n" // 86400 * 14
- );
- }
- else {
- buffer_sprintf(w->response.header_output,
- "Cache-Control: %s\r\n"
- "Expires: %s\r\n",
- (w->response.data->options & WB_CONTENT_NO_CACHEABLE)?"no-cache":"public",
- edate);
- }
-
- // copy a possibly available custom header
- if(unlikely(buffer_strlen(w->response.header)))
- buffer_strcat(w->response.header_output, buffer_tostring(w->response.header));
-
- // headers related to the transfer method
- if(likely(w->response.zoutput)) {
- buffer_strcat(w->response.header_output,
- "Content-Encoding: gzip\r\n"
- "Transfer-Encoding: chunked\r\n"
- );
- }
- else {
- if(likely((w->response.data->len || w->response.rlen))) {
- // we know the content length, put it
- buffer_sprintf(w->response.header_output, "Content-Length: %zu\r\n", w->response.data->len? w->response.data->len: w->response.rlen);
- }
- else {
- // we don't know the content length, disable keep-alive
- web_client_disable_keepalive(w);
- }
- }
-
- // end of HTTP header
- buffer_strcat(w->response.header_output, "\r\n");
-
- // sent the HTTP header
- debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %zu: '%s'"
- , w->id
- , buffer_strlen(w->response.header_output)
- , buffer_tostring(w->response.header_output)
- );
-
- web_client_crock_socket(w);
-
- size_t count = 0;
- ssize_t bytes;
- while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) {
- count++;
-
- if(count > 100 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
- error("Cannot send HTTP headers to web client.");
- break;
- }
- }
-
- if(bytes != (ssize_t) buffer_strlen(w->response.header_output)) {
- if(bytes > 0)
- w->stats_sent_bytes += bytes;
-
- error("HTTP headers failed to be sent (I sent %zu bytes but the system sent %zd bytes). Closing web client."
- , buffer_strlen(w->response.header_output)
- , bytes);
-
- WEB_CLIENT_IS_DEAD(w);
- return;
- }
- else
- w->stats_sent_bytes += bytes;
-}
-
-static inline int web_client_process_url(RRDHOST *host, struct web_client *w, char *url);
-
-static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, char *url) {
- static uint32_t hash_localhost = 0;
-
- if(unlikely(!hash_localhost)) {
- hash_localhost = simple_hash("localhost");
- }
-
- if(host != localhost) {
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "Nesting of hosts is not allowed.");
- return 400;
- }
-
- char *tok = mystrsep(&url, "/?&");
- if(tok && *tok) {
- debug(D_WEB_CLIENT, "%llu: Searching for host with name '%s'.", w->id, tok);
-
- // copy the URL, we need it to serve files
- w->last_url[0] = '/';
- if(url && *url) strncpyz(&w->last_url[1], url, NETDATA_WEB_REQUEST_URL_SIZE - 1);
- else w->last_url[1] = '\0';
-
- uint32_t hash = simple_hash(tok);
-
- host = rrdhost_find_by_hostname(tok, hash);
- if(!host) host = rrdhost_find_by_guid(tok, hash);
-
- if(host) return web_client_process_url(host, w, url);
- }
-
- buffer_flush(w->response.data);
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "This netdata does not maintain a database for host: ");
- buffer_strcat_htmlescape(w->response.data, tok?tok:"");
- return 404;
-}
-
-static inline int web_client_process_url(RRDHOST *host, struct web_client *w, char *url) {
- static uint32_t
- hash_api = 0,
- hash_netdata_conf = 0,
- hash_data = 0,
- hash_datasource = 0,
- hash_graph = 0,
- hash_list = 0,
- hash_all_json = 0,
- hash_host = 0;
-
-#ifdef NETDATA_INTERNAL_CHECKS
- static uint32_t hash_exit = 0, hash_debug = 0, hash_mirror = 0;
-#endif
-
- if(unlikely(!hash_api)) {
- hash_api = simple_hash("api");
- hash_netdata_conf = simple_hash("netdata.conf");
- hash_data = simple_hash(WEB_PATH_DATA);
- hash_datasource = simple_hash(WEB_PATH_DATASOURCE);
- hash_graph = simple_hash(WEB_PATH_GRAPH);
- hash_list = simple_hash("list");
- hash_all_json = simple_hash("all.json");
- hash_host = simple_hash("host");
-#ifdef NETDATA_INTERNAL_CHECKS
- hash_exit = simple_hash("exit");
- hash_debug = simple_hash("debug");
- hash_mirror = simple_hash("mirror");
-#endif
- }
-
- char *tok = mystrsep(&url, "/?");
- if(likely(tok && *tok)) {
- uint32_t hash = simple_hash(tok);
- debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
-
- if(unlikely(hash == hash_api && strcmp(tok, "api") == 0)) { // current API
- debug(D_WEB_CLIENT_ACCESS, "%llu: API request ...", w->id);
- return check_host_and_call(host, w, url, web_client_api_request);
- }
- else if(unlikely(hash == hash_host && strcmp(tok, "host") == 0)) { // host switching
- debug(D_WEB_CLIENT_ACCESS, "%llu: host switch request ...", w->id);
- return web_client_switch_host(host, w, url);
- }
- else if(unlikely(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0)) { // old API "data"
- debug(D_WEB_CLIENT_ACCESS, "%llu: old API data request...", w->id);
- return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_data_request_json);
- }
- else if(unlikely(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0)) { // old API "datasource"
- debug(D_WEB_CLIENT_ACCESS, "%llu: old API datasource request...", w->id);
- return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_data_request_jsonp);
- }
- else if(unlikely(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0)) { // old API "graph"
- debug(D_WEB_CLIENT_ACCESS, "%llu: old API graph request...", w->id);
- return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_graph_request);
- }
- else if(unlikely(hash == hash_list && strcmp(tok, "list") == 0)) { // old API "list"
- debug(D_WEB_CLIENT_ACCESS, "%llu: old API list request...", w->id);
- return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_list_request);
- }
- else if(unlikely(hash == hash_all_json && strcmp(tok, "all.json") == 0)) { // old API "all.json"
- debug(D_WEB_CLIENT_ACCESS, "%llu: old API all.json request...", w->id);
- return check_host_and_dashboard_acl_and_call(host, w, url, web_client_api_old_all_json);
- }
- else if(unlikely(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0)) { // netdata.conf
- if(unlikely(!web_client_can_access_netdataconf(w)))
- return web_client_permission_denied(w);
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: generating netdata.conf ...", w->id);
- w->response.data->contenttype = CT_TEXT_PLAIN;
- buffer_flush(w->response.data);
- config_generate(w->response.data, 0);
- return 200;
- }
-#ifdef NETDATA_INTERNAL_CHECKS
- else if(unlikely(hash == hash_exit && strcmp(tok, "exit") == 0)) {
- if(unlikely(!web_client_can_access_netdataconf(w)))
- return web_client_permission_denied(w);
-
- w->response.data->contenttype = CT_TEXT_PLAIN;
- buffer_flush(w->response.data);
-
- if(!netdata_exit)
- buffer_strcat(w->response.data, "ok, will do...");
- else
- buffer_strcat(w->response.data, "I am doing it already");
-
- error("web request to exit received.");
- netdata_cleanup_and_exit(0);
- return 200;
- }
- else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) {
- if(unlikely(!web_client_can_access_netdataconf(w)))
- return web_client_permission_denied(w);
-
- buffer_flush(w->response.data);
-
- // get the name of the data to show
- tok = mystrsep(&url, "/?&");
- if(tok && *tok) {
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
-
- // do we have such a data set?
- RRDSET *st = rrdset_find_byname(host, tok);
- if(!st) st = rrdset_find(host, tok);
- if(!st) {
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "Chart is not found: ");
- buffer_strcat_htmlescape(w->response.data, tok);
- debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
- return 404;
- }
-
- debug_flags |= D_RRD_STATS;
-
- if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))
- rrdset_flag_clear(st, RRDSET_FLAG_DEBUG);
- else
- rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
-
- w->response.data->contenttype = CT_TEXT_HTML;
- buffer_sprintf(w->response.data, "Chart has now debug %s: ", rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled");
- buffer_strcat_htmlescape(w->response.data, tok);
- debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled");
- return 200;
- }
-
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "debug which chart?\r\n");
- return 400;
- }
- else if(unlikely(hash == hash_mirror && strcmp(tok, "mirror") == 0)) {
- if(unlikely(!web_client_can_access_netdataconf(w)))
- return web_client_permission_denied(w);
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
-
- // replace the zero bytes with spaces
- buffer_char_replace(w->response.data, '\0', ' ');
-
- // just leave the buffer as is
- // it will be copied back to the client
-
- return 200;
- }
-#endif /* NETDATA_INTERNAL_CHECKS */
- }
-
- char filename[FILENAME_MAX+1];
- url = filename;
- strncpyz(filename, w->last_url, FILENAME_MAX);
- tok = mystrsep(&url, "?");
- buffer_flush(w->response.data);
- return mysendfile(w, (tok && *tok)?tok:"/");
-}
-
-void web_client_process_request(struct web_client *w) {
-
- // start timing us
- now_realtime_timeval(&w->tv_in);
-
- switch(http_request_validate(w)) {
- case HTTP_VALIDATION_OK:
- switch(w->mode) {
- case WEB_CLIENT_MODE_STREAM:
- if(unlikely(!web_client_can_access_stream(w))) {
- web_client_permission_denied(w);
- return;
- }
-
- w->response.code = rrdpush_receiver_thread_spawn(localhost, w, w->decoded_url);
- return;
-
- case WEB_CLIENT_MODE_OPTIONS:
- if(unlikely(!web_client_can_access_dashboard(w) && !web_client_can_access_registry(w) && !web_client_can_access_badges(w))) {
- web_client_permission_denied(w);
- return;
- }
-
- w->response.data->contenttype = CT_TEXT_PLAIN;
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "OK");
- w->response.code = 200;
- break;
-
- case WEB_CLIENT_MODE_FILECOPY:
- case WEB_CLIENT_MODE_NORMAL:
- if(unlikely(!web_client_can_access_dashboard(w) && !web_client_can_access_registry(w) && !web_client_can_access_badges(w))) {
- web_client_permission_denied(w);
- return;
- }
-
- w->response.code = web_client_process_url(localhost, w, w->decoded_url);
- break;
- }
- break;
-
- case HTTP_VALIDATION_INCOMPLETE:
- if(w->response.data->len > NETDATA_WEB_REQUEST_MAX_SIZE) {
- strcpy(w->last_url, "too big request");
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big (%zu bytes).", w->id, w->response.data->len);
-
- buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len);
- w->response.code = 400;
- }
- else {
- // wait for more data
- return;
- }
- break;
-
- case HTTP_VALIDATION_NOT_SUPPORTED:
- debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer);
-
- buffer_flush(w->response.data);
- buffer_strcat(w->response.data, "I don't understand you...\r\n");
- w->response.code = 400;
- break;
- }
-
- // keep track of the time we done processing
- now_realtime_timeval(&w->tv_ready);
-
- w->response.sent = 0;
-
- // set a proper last modified date
- if(unlikely(!w->response.data->date))
- w->response.data->date = w->tv_ready.tv_sec;
-
- web_client_send_http_header(w);
-
- // enable sending immediately if we have data
- if(w->response.data->len) web_client_enable_wait_send(w);
- else web_client_disable_wait_send(w);
-
- switch(w->mode) {
- case WEB_CLIENT_MODE_STREAM:
- debug(D_WEB_CLIENT, "%llu: STREAM done.", w->id);
- break;
-
- case WEB_CLIENT_MODE_OPTIONS:
- debug(D_WEB_CLIENT, "%llu: Done preparing the OPTIONS response. Sending data (%zu bytes) to client.", w->id, w->response.data->len);
- break;
-
- case WEB_CLIENT_MODE_NORMAL:
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%zu bytes) to client.", w->id, w->response.data->len);
- break;
-
- case WEB_CLIENT_MODE_FILECOPY:
- if(w->response.rlen) {
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %zu bytes to client.", w->id, w->response.rlen);
- web_client_enable_wait_receive(w);
-
- /*
- // utilize the kernel sendfile() for copying the file to the socket.
- // this block of code can be commented, without anything missing.
- // when it is commented, the program will copy the data using async I/O.
- {
- long len = sendfile(w->ofd, w->ifd, NULL, w->response.data->rbytes);
- if(len != w->response.data->rbytes)
- error("%llu: sendfile() should copy %ld bytes, but copied %ld. Falling back to manual copy.", w->id, w->response.data->rbytes, len);
- else
- web_client_request_done(w);
- }
- */
- }
- else
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending an unknown amount of bytes to client.", w->id);
- break;
-
- default:
- fatal("%llu: Unknown client mode %u.", w->id, w->mode);
- break;
- }
-}
-
-ssize_t web_client_send_chunk_header(struct web_client *w, size_t len)
-{
- debug(D_DEFLATE, "%llu: OPEN CHUNK of %zu bytes (hex: %zx).", w->id, len, len);
- char buf[24];
- sprintf(buf, "%zX\r\n", len);
-
- ssize_t bytes = send(w->ofd, buf, strlen(buf), 0);
- if(bytes > 0) {
- debug(D_DEFLATE, "%llu: Sent chunk header %zd bytes.", w->id, bytes);
- w->stats_sent_bytes += bytes;
- }
-
- else if(bytes == 0) {
- debug(D_WEB_CLIENT, "%llu: Did not send chunk header to the client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
- else {
- debug(D_WEB_CLIENT, "%llu: Failed to send chunk header to client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return bytes;
-}
-
-ssize_t web_client_send_chunk_close(struct web_client *w)
-{
- //debug(D_DEFLATE, "%llu: CLOSE CHUNK.", w->id);
-
- ssize_t bytes = send(w->ofd, "\r\n", 2, 0);
- if(bytes > 0) {
- debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
- w->stats_sent_bytes += bytes;
- }
-
- else if(bytes == 0) {
- debug(D_WEB_CLIENT, "%llu: Did not send chunk suffix to the client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
- else {
- debug(D_WEB_CLIENT, "%llu: Failed to send chunk suffix to client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return bytes;
-}
-
-ssize_t web_client_send_chunk_finalize(struct web_client *w)
-{
- //debug(D_DEFLATE, "%llu: FINALIZE CHUNK.", w->id);
-
- ssize_t bytes = send(w->ofd, "\r\n0\r\n\r\n", 7, 0);
- if(bytes > 0) {
- debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
- w->stats_sent_bytes += bytes;
- }
-
- else if(bytes == 0) {
- debug(D_WEB_CLIENT, "%llu: Did not send chunk finalize suffix to the client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
- else {
- debug(D_WEB_CLIENT, "%llu: Failed to send chunk finalize suffix to client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return bytes;
-}
-
-#ifdef NETDATA_WITH_ZLIB
-ssize_t web_client_send_deflate(struct web_client *w)
-{
- ssize_t len = 0, t = 0;
-
- // when using compression,
- // w->response.sent is the amount of bytes passed through compression
-
- debug(D_DEFLATE, "%llu: web_client_send_deflate(): w->response.data->len = %zu, w->response.sent = %zu, w->response.zhave = %zu, w->response.zsent = %zu, w->response.zstream.avail_in = %u, w->response.zstream.avail_out = %u, w->response.zstream.total_in = %lu, w->response.zstream.total_out = %lu.",
- w->id, w->response.data->len, w->response.sent, w->response.zhave, w->response.zsent, w->response.zstream.avail_in, w->response.zstream.avail_out, w->response.zstream.total_in, w->response.zstream.total_out);
-
- if(w->response.data->len - w->response.sent == 0 && w->response.zstream.avail_in == 0 && w->response.zhave == w->response.zsent && w->response.zstream.avail_out != 0) {
- // there is nothing to send
-
- debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
-
- // finalize the chunk
- if(w->response.sent != 0) {
- t = web_client_send_chunk_finalize(w);
- if(t < 0) return t;
- }
-
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) {
- // we have to wait, more data will come
- debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
- web_client_disable_wait_send(w);
- return t;
- }
-
- if(unlikely(!web_client_has_keepalive(w))) {
- debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
- WEB_CLIENT_IS_DEAD(w);
- return t;
- }
-
- // reset the client
- web_client_request_done(w);
- debug(D_WEB_CLIENT, "%llu: Done sending all data on socket.", w->id);
- return t;
- }
-
- if(w->response.zhave == w->response.zsent) {
- // compress more input data
-
- // close the previous open chunk
- if(w->response.sent != 0) {
- t = web_client_send_chunk_close(w);
- if(t < 0) return t;
- }
-
- debug(D_DEFLATE, "%llu: Compressing %zu new bytes starting from %zu (and %u left behind).", w->id, (w->response.data->len - w->response.sent), w->response.sent, w->response.zstream.avail_in);
-
- // give the compressor all the data not passed through the compressor yet
- if(w->response.data->len > w->response.sent) {
- w->response.zstream.next_in = (Bytef *)&w->response.data->buffer[w->response.sent - w->response.zstream.avail_in];
- w->response.zstream.avail_in += (uInt) (w->response.data->len - w->response.sent);
- }
-
- // reset the compressor output buffer
- w->response.zstream.next_out = w->response.zbuffer;
- w->response.zstream.avail_out = NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE;
-
- // ask for FINISH if we have all the input
- int flush = Z_SYNC_FLUSH;
- if(w->mode == WEB_CLIENT_MODE_NORMAL
- || (w->mode == WEB_CLIENT_MODE_FILECOPY && !web_client_has_wait_receive(w) && w->response.data->len == w->response.rlen)) {
- flush = Z_FINISH;
- debug(D_DEFLATE, "%llu: Requesting Z_FINISH, if possible.", w->id);
- }
- else {
- debug(D_DEFLATE, "%llu: Requesting Z_SYNC_FLUSH.", w->id);
- }
-
- // compress
- if(deflate(&w->response.zstream, flush) == Z_STREAM_ERROR) {
- error("%llu: Compression failed. Closing down client.", w->id);
- web_client_request_done(w);
- return(-1);
- }
-
- w->response.zhave = NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE - w->response.zstream.avail_out;
- w->response.zsent = 0;
-
- // keep track of the bytes passed through the compressor
- w->response.sent = w->response.data->len;
-
- debug(D_DEFLATE, "%llu: Compression produced %zu bytes.", w->id, w->response.zhave);
-
- // open a new chunk
- ssize_t t2 = web_client_send_chunk_header(w, w->response.zhave);
- if(t2 < 0) return t2;
- t += t2;
- }
-
- debug(D_WEB_CLIENT, "%llu: Sending %zu bytes of data (+%zd of chunk header).", w->id, w->response.zhave - w->response.zsent, t);
-
- len = send(w->ofd, &w->response.zbuffer[w->response.zsent], (size_t) (w->response.zhave - w->response.zsent), MSG_DONTWAIT);
- if(len > 0) {
- w->stats_sent_bytes += len;
- w->response.zsent += len;
- len += t;
- debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, len);
- }
- else if(len == 0) {
- debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client (zhave = %zu, zsent = %zu, need to send = %zu).",
- w->id, w->response.zhave, w->response.zsent, w->response.zhave - w->response.zsent);
-
- WEB_CLIENT_IS_DEAD(w);
- }
- else {
- debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return(len);
-}
-#endif // NETDATA_WITH_ZLIB
-
-ssize_t web_client_send(struct web_client *w) {
-#ifdef NETDATA_WITH_ZLIB
- if(likely(w->response.zoutput)) return web_client_send_deflate(w);
-#endif // NETDATA_WITH_ZLIB
-
- ssize_t bytes;
-
- if(unlikely(w->response.data->len - w->response.sent == 0)) {
- // there is nothing to send
-
- debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
-
- // there can be two cases for this
- // A. we have done everything
- // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
-
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) {
- // we have to wait, more data will come
- debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
- web_client_disable_wait_send(w);
- return 0;
- }
-
- if(unlikely(!web_client_has_keepalive(w))) {
- debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
- WEB_CLIENT_IS_DEAD(w);
- return 0;
- }
-
- web_client_request_done(w);
- debug(D_WEB_CLIENT, "%llu: Done sending all data on socket. Waiting for next request on the same socket.", w->id);
- return 0;
- }
-
- bytes = send(w->ofd, &w->response.data->buffer[w->response.sent], w->response.data->len - w->response.sent, MSG_DONTWAIT);
- if(likely(bytes > 0)) {
- w->stats_sent_bytes += bytes;
- w->response.sent += bytes;
- debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, bytes);
- }
- else if(likely(bytes == 0)) {
- debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
- else {
- debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return(bytes);
-}
-
-ssize_t web_client_read_file(struct web_client *w)
-{
- if(unlikely(w->response.rlen > w->response.data->size))
- buffer_need_bytes(w->response.data, w->response.rlen - w->response.data->size);
-
- if(unlikely(w->response.rlen <= w->response.data->len))
- return 0;
-
- ssize_t left = w->response.rlen - w->response.data->len;
- ssize_t bytes = read(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t)left);
- if(likely(bytes > 0)) {
- size_t old = w->response.data->len;
- w->response.data->len += bytes;
- w->response.data->buffer[w->response.data->len] = '\0';
-
- debug(D_WEB_CLIENT, "%llu: Read %zd bytes.", w->id, bytes);
- debug(D_WEB_DATA, "%llu: Read data: '%s'.", w->id, &w->response.data->buffer[old]);
-
- web_client_enable_wait_send(w);
-
- if(w->response.rlen && w->response.data->len >= w->response.rlen)
- web_client_disable_wait_receive(w);
- }
- else if(likely(bytes == 0)) {
- debug(D_WEB_CLIENT, "%llu: Out of input file data.", w->id);
-
- // if we cannot read, it means we have an error on input.
- // if however, we are copying a file from ifd to ofd, we should not return an error.
- // in this case, the error should be generated when the file has been sent to the client.
-
- // we are copying data from ifd to ofd
- // let it finish copying...
- web_client_disable_wait_receive(w);
-
- debug(D_WEB_CLIENT, "%llu: Read the whole file.", w->id);
-
- if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
- if (w->ifd != w->ofd) close(w->ifd);
- }
-
- w->ifd = w->ofd;
- }
- else {
- debug(D_WEB_CLIENT, "%llu: read data failed.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return(bytes);
-}
-
-ssize_t web_client_receive(struct web_client *w)
-{
- if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY))
- return web_client_read_file(w);
-
- // do we have any space for more data?
- buffer_need_bytes(w->response.data, NETDATA_WEB_REQUEST_RECEIVE_SIZE);
-
- ssize_t left = w->response.data->size - w->response.data->len;
- ssize_t bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
-
- if(likely(bytes > 0)) {
- w->stats_received_bytes += bytes;
-
- size_t old = w->response.data->len;
- w->response.data->len += bytes;
- w->response.data->buffer[w->response.data->len] = '\0';
-
- debug(D_WEB_CLIENT, "%llu: Received %zd bytes.", w->id, bytes);
- debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]);
- }
- else {
- debug(D_WEB_CLIENT, "%llu: receive data failed.", w->id);
- WEB_CLIENT_IS_DEAD(w);
- }
-
- return(bytes);
-}
diff --git a/src/web_client.h b/src/web_client.h
deleted file mode 100644
index b495c37e1..000000000
--- a/src/web_client.h
+++ /dev/null
@@ -1,189 +0,0 @@
-#ifndef NETDATA_WEB_CLIENT_H
-#define NETDATA_WEB_CLIENT_H 1
-
-#ifdef NETDATA_WITH_ZLIB
-extern int web_enable_gzip,
- web_gzip_level,
- web_gzip_strategy;
-#endif /* NETDATA_WITH_ZLIB */
-
-extern int respect_web_browser_do_not_track_policy;
-extern char *web_x_frame_options;
-
-typedef enum web_client_mode {
- WEB_CLIENT_MODE_NORMAL = 0,
- WEB_CLIENT_MODE_FILECOPY = 1,
- WEB_CLIENT_MODE_OPTIONS = 2,
- WEB_CLIENT_MODE_STREAM = 3
-} WEB_CLIENT_MODE;
-
-typedef enum web_client_flags {
- WEB_CLIENT_FLAG_DEAD = 1 << 1, // if set, this client is dead
-
- WEB_CLIENT_FLAG_KEEPALIVE = 1 << 2, // if set, the web client will be re-used
-
- WEB_CLIENT_FLAG_WAIT_RECEIVE = 1 << 3, // if set, we are waiting more input data
- WEB_CLIENT_FLAG_WAIT_SEND = 1 << 4, // if set, we have data to send to the client
-
- WEB_CLIENT_FLAG_DO_NOT_TRACK = 1 << 5, // if set, we should not set cookies on this client
- WEB_CLIENT_FLAG_TRACKING_REQUIRED = 1 << 6, // if set, we need to send cookies
-
- WEB_CLIENT_FLAG_TCP_CLIENT = 1 << 7, // if set, the client is using a TCP socket
- WEB_CLIENT_FLAG_UNIX_CLIENT = 1 << 8, // if set, the client is using a UNIX socket
-
- WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET = 1 << 9, // don't close the socket when cleaning up (static-threaded web server)
-} WEB_CLIENT_FLAGS;
-
-//#ifdef HAVE_C___ATOMIC
-//#define web_client_flag_check(w, flag) (__atomic_load_n(&((w)->flags), __ATOMIC_SEQ_CST) & flag)
-//#define web_client_flag_set(w, flag) __atomic_or_fetch(&((w)->flags), flag, __ATOMIC_SEQ_CST)
-//#define web_client_flag_clear(w, flag) __atomic_and_fetch(&((w)->flags), ~flag, __ATOMIC_SEQ_CST)
-//#else
-#define web_client_flag_check(w, flag) ((w)->flags & (flag))
-#define web_client_flag_set(w, flag) (w)->flags |= flag
-#define web_client_flag_clear(w, flag) (w)->flags &= ~flag
-//#endif
-
-#define WEB_CLIENT_IS_DEAD(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DEAD)
-#define web_client_check_dead(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DEAD)
-
-#define web_client_has_keepalive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_KEEPALIVE)
-#define web_client_enable_keepalive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_KEEPALIVE)
-#define web_client_disable_keepalive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_KEEPALIVE)
-
-#define web_client_has_donottrack(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
-#define web_client_enable_donottrack(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
-#define web_client_disable_donottrack(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
-
-#define web_client_has_tracking_required(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
-#define web_client_enable_tracking_required(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
-#define web_client_disable_tracking_required(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
-
-#define web_client_has_wait_receive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
-#define web_client_enable_wait_receive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
-#define web_client_disable_wait_receive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
-
-#define web_client_has_wait_send(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_SEND)
-#define web_client_enable_wait_send(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_SEND)
-#define web_client_disable_wait_send(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_SEND)
-
-#define web_client_set_tcp(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TCP_CLIENT)
-#define web_client_set_unix(w) web_client_flag_set(w, WEB_CLIENT_FLAG_UNIX_CLIENT)
-#define web_client_check_unix(w) web_client_flag_check(w, WEB_CLIENT_FLAG_UNIX_CLIENT)
-
-#define web_client_is_corkable(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT)
-
-#define NETDATA_WEB_REQUEST_URL_SIZE 8192
-#define NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE 16384
-#define NETDATA_WEB_RESPONSE_HEADER_SIZE 4096
-#define NETDATA_WEB_REQUEST_COOKIE_SIZE 1024
-#define NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE 1024
-#define NETDATA_WEB_RESPONSE_INITIAL_SIZE 16384
-#define NETDATA_WEB_REQUEST_RECEIVE_SIZE 16384
-#define NETDATA_WEB_REQUEST_MAX_SIZE 16384
-
-struct response {
- BUFFER *header; // our response header
- BUFFER *header_output; // internal use
- BUFFER *data; // our response data buffer
-
- int code; // the HTTP response code
-
- size_t rlen; // if non-zero, the excepted size of ifd (input of firecopy)
- size_t sent; // current data length sent to output
-
- int zoutput; // if set to 1, web_client_send() will send compressed data
-#ifdef NETDATA_WITH_ZLIB
- z_stream zstream; // zlib stream for sending compressed output to client
- Bytef zbuffer[NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE]; // temporary buffer for storing compressed output
- size_t zsent; // the compressed bytes we have sent to the client
- size_t zhave; // the compressed bytes that we have received from zlib
- int zinitialized:1;
-#endif /* NETDATA_WITH_ZLIB */
-
-};
-
-typedef enum web_client_acl {
- WEB_CLIENT_ACL_NONE = 0,
- WEB_CLIENT_ACL_NOCHECK = 0,
- WEB_CLIENT_ACL_DASHBOARD = 1 << 0,
- WEB_CLIENT_ACL_REGISTRY = 1 << 1,
- WEB_CLIENT_ACL_BADGE = 1 << 2
-} WEB_CLIENT_ACL;
-
-#define web_client_can_access_dashboard(w) ((w)->acl & WEB_CLIENT_ACL_DASHBOARD)
-#define web_client_can_access_registry(w) ((w)->acl & WEB_CLIENT_ACL_REGISTRY)
-#define web_client_can_access_badges(w) ((w)->acl & WEB_CLIENT_ACL_BADGE)
-
-#define web_client_can_access_stream(w) \
- (!web_allow_streaming_from || simple_pattern_matches(web_allow_streaming_from, (w)->client_ip))
-
-#define web_client_can_access_netdataconf(w) \
- (!web_allow_netdataconf_from || simple_pattern_matches(web_allow_netdataconf_from, (w)->client_ip))
-
-struct web_client {
- unsigned long long id;
-
- WEB_CLIENT_FLAGS flags; // status flags for the client
- WEB_CLIENT_MODE mode; // the operational mode of the client
- WEB_CLIENT_ACL acl; // the access list of the client
-
- size_t header_parse_tries;
- size_t header_parse_last_size;
-
- int tcp_cork; // 1 = we have a cork on the socket
-
- int ifd;
- int ofd;
-
- char client_ip[NI_MAXHOST+1];
- char client_port[NI_MAXSERV+1];
-
- char decoded_url[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the URL in this buffer
- char last_url[NETDATA_WEB_REQUEST_URL_SIZE+1]; // we keep a copy of the decoded URL here
-
- struct timeval tv_in, tv_ready;
-
- char cookie1[NETDATA_WEB_REQUEST_COOKIE_SIZE+1];
- char cookie2[NETDATA_WEB_REQUEST_COOKIE_SIZE+1];
- char origin[NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE+1];
- char *user_agent;
-
- struct response response;
-
- size_t stats_received_bytes;
- size_t stats_sent_bytes;
-
- // cache of web_client allocations
- struct web_client *prev; // maintain a linked list of web clients
- struct web_client *next; // for the web servers that need it
-
- // MULTI-THREADED WEB SERVER MEMBERS
- netdata_thread_t thread; // the thread servicing this client
- volatile int running; // 1 when the thread runs, 0 otherwise
-
- // STATIC-THREADED WEB SERVER MEMBERS
- size_t pollinfo_slot; // POLLINFO slot of the web client
- size_t pollinfo_filecopy_slot; // POLLINFO slot of the file read
-};
-
-extern uid_t web_files_uid(void);
-extern uid_t web_files_gid(void);
-
-extern int web_client_permission_denied(struct web_client *w);
-
-extern ssize_t web_client_send(struct web_client *w);
-extern ssize_t web_client_receive(struct web_client *w);
-extern ssize_t web_client_read_file(struct web_client *w);
-
-extern void web_client_process_request(struct web_client *w);
-extern void web_client_request_done(struct web_client *w);
-
-extern int web_client_api_request_v1_data_group(char *name, int def);
-extern const char *group_method2string(int group);
-
-extern void buffer_data_options2string(BUFFER *wb, uint32_t options);
-
-extern int mysendfile(struct web_client *w, char *filename);
-
-#endif
diff --git a/src/web_server.c b/src/web_server.c
deleted file mode 100644
index 31c546411..000000000
--- a/src/web_server.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-#include "common.h"
-
-// this file includes 3 web servers:
-//
-// 1. single-threaded, based on select()
-// 2. multi-threaded, based on poll() that spawns threads to handle the requests, based on select()
-// 3. static-threaded, based on poll() using a fixed number of threads (configured at netdata.conf)
-
-WEB_SERVER_MODE web_server_mode = WEB_SERVER_MODE_STATIC_THREADED;
-
-// --------------------------------------------------------------------------------------
-
-WEB_SERVER_MODE web_server_mode_id(const char *mode) {
- if(!strcmp(mode, "none"))
- return WEB_SERVER_MODE_NONE;
- else if(!strcmp(mode, "single") || !strcmp(mode, "single-threaded"))
- return WEB_SERVER_MODE_SINGLE_THREADED;
- else if(!strcmp(mode, "static") || !strcmp(mode, "static-threaded"))
- return WEB_SERVER_MODE_STATIC_THREADED;
- else // if(!strcmp(mode, "multi") || !strcmp(mode, "multi-threaded"))
- return WEB_SERVER_MODE_MULTI_THREADED;
-}
-
-const char *web_server_mode_name(WEB_SERVER_MODE id) {
- switch(id) {
- case WEB_SERVER_MODE_NONE:
- return "none";
-
- case WEB_SERVER_MODE_SINGLE_THREADED:
- return "single-threaded";
-
- case WEB_SERVER_MODE_STATIC_THREADED:
- return "static-threaded";
-
- default:
- case WEB_SERVER_MODE_MULTI_THREADED:
- return "multi-threaded";
- }
-}
-
-// --------------------------------------------------------------------------------------
-// API sockets
-
-static LISTEN_SOCKETS api_sockets = {
- .config_section = CONFIG_SECTION_WEB,
- .default_bind_to = "*",
- .default_port = API_LISTEN_PORT,
- .backlog = API_LISTEN_BACKLOG
-};
-
-int api_listen_sockets_setup(void) {
- int socks = listen_sockets_setup(&api_sockets);
-
- if(!socks)
- fatal("LISTENER: Cannot listen on any API socket. Exiting...");
-
- return socks;
-}
-
-
-// --------------------------------------------------------------------------------------
-// access lists
-
-SIMPLE_PATTERN *web_allow_connections_from = NULL;
-SIMPLE_PATTERN *web_allow_streaming_from = NULL;
-SIMPLE_PATTERN *web_allow_netdataconf_from = NULL;
-
-// WEB_CLIENT_ACL
-SIMPLE_PATTERN *web_allow_dashboard_from = NULL;
-SIMPLE_PATTERN *web_allow_registry_from = NULL;
-SIMPLE_PATTERN *web_allow_badges_from = NULL;
-
-static void web_client_update_acl_matches(struct web_client *w) {
- w->acl = WEB_CLIENT_ACL_NONE;
-
- if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip))
- w->acl |= WEB_CLIENT_ACL_DASHBOARD;
-
- if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip))
- w->acl |= WEB_CLIENT_ACL_REGISTRY;
-
- if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip))
- w->acl |= WEB_CLIENT_ACL_BADGE;
-}
-
-
-// --------------------------------------------------------------------------------------
-
-static void log_connection(struct web_client *w, const char *msg) {
- log_access("%llu: %d '[%s]:%s' '%s'", w->id, gettid(), w->client_ip, w->client_port, msg);
-}
-
-// ----------------------------------------------------------------------------
-// allocate and free web_clients
-
-static void web_client_zero(struct web_client *w) {
- // zero everything about it - but keep the buffers
-
- // remember the pointers to the buffers
- BUFFER *b1 = w->response.data;
- BUFFER *b2 = w->response.header;
- BUFFER *b3 = w->response.header_output;
-
- // empty the buffers
- buffer_flush(b1);
- buffer_flush(b2);
- buffer_flush(b3);
-
- freez(w->user_agent);
-
- // zero everything
- memset(w, 0, sizeof(struct web_client));
-
- // restore the pointers of the buffers
- w->response.data = b1;
- w->response.header = b2;
- w->response.header_output = b3;
-}
-
-static void web_client_free(struct web_client *w) {
- buffer_free(w->response.header_output);
- buffer_free(w->response.header);
- buffer_free(w->response.data);
- freez(w->user_agent);
- freez(w);
-}
-
-static struct web_client *web_client_alloc(void) {
- struct web_client *w = callocz(1, sizeof(struct web_client));
- w->response.data = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE);
- w->response.header = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE);
- w->response.header_output = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE);
- return w;
-}
-
-// ----------------------------------------------------------------------------
-// web clients caching
-
-// When clients connect and disconnect, avoid allocating and releasing memory.
-// Instead, when new clients get connected, reuse any memory previously allocated
-// for serving web clients that are now disconnected.
-
-// The size of the cache is adaptive. It caches the structures of 2x
-// the number of currently connected clients.
-
-// Comments per server:
-// SINGLE-THREADED : 1 cache is maintained
-// MULTI-THREADED : 1 cache is maintained
-// STATIC-THREADED : 1 cache for each thred of the web server
-
-struct clients_cache {
- pid_t pid;
-
- struct web_client *used; // the structures of the currently connected clients
- size_t used_count; // the count the currently connected clients
-
- struct web_client *avail; // the cached structures, available for future clients
- size_t avail_count; // the number of cached structures
-
- size_t reused; // the number of re-uses
- size_t allocated; // the number of allocations
-};
-
-static __thread struct clients_cache web_clients_cache = {
- .pid = 0,
- .used = NULL,
- .used_count = 0,
- .avail = NULL,
- .avail_count = 0,
- .allocated = 0,
- .reused = 0
-};
-
-static inline void web_client_cache_verify(int force) {
-#ifdef NETDATA_INTERNAL_CHECKS
- static __thread size_t count = 0;
- count++;
-
- if(unlikely(force || count > 1000)) {
- count = 0;
-
- struct web_client *w;
- size_t used = 0, avail = 0;
- for(w = web_clients_cache.used; w ; w = w->next) used++;
- for(w = web_clients_cache.avail; w ; w = w->next) avail++;
-
- info("web_client_cache has %zu (%zu) used and %zu (%zu) available clients, allocated %zu, reused %zu (hit %zu%%)."
- , used, web_clients_cache.used_count
- , avail, web_clients_cache.avail_count
- , web_clients_cache.allocated
- , web_clients_cache.reused
- , (web_clients_cache.allocated + web_clients_cache.reused)?(web_clients_cache.reused * 100 / (web_clients_cache.allocated + web_clients_cache.reused)):0
- );
- }
-#else
- if(unlikely(force)) {
- info("web_client_cache has %zu used and %zu available clients, allocated %zu, reused %zu (hit %zu%%)."
- , web_clients_cache.used_count
- , web_clients_cache.avail_count
- , web_clients_cache.allocated
- , web_clients_cache.reused
- , (web_clients_cache.allocated + web_clients_cache.reused)?(web_clients_cache.reused * 100 / (web_clients_cache.allocated + web_clients_cache.reused)):0
- );
- }
-#endif
-}
-
-// destroy the cache and free all the memory it uses
-static void web_client_cache_destroy(void) {
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid()))
- error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid());
-
- web_client_cache_verify(1);
-#endif
-
- netdata_thread_disable_cancelability();
-
- struct web_client *w, *t;
-
- w = web_clients_cache.used;
- while(w) {
- t = w;
- w = w->next;
- web_client_free(t);
- }
- web_clients_cache.used = NULL;
- web_clients_cache.used_count = 0;
-
- w = web_clients_cache.avail;
- while(w) {
- t = w;
- w = w->next;
- web_client_free(t);
- }
- web_clients_cache.avail = NULL;
- web_clients_cache.avail_count = 0;
-
- netdata_thread_enable_cancelability();
-}
-
-static struct web_client *web_client_get_from_cache_or_allocate() {
-
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(web_clients_cache.pid == 0))
- web_clients_cache.pid = gettid();
-
- if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid()))
- error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid());
-#endif
-
- netdata_thread_disable_cancelability();
-
- struct web_client *w = web_clients_cache.avail;
-
- if(w) {
- // get it from avail
- if (w == web_clients_cache.avail) web_clients_cache.avail = w->next;
- if(w->prev) w->prev->next = w->next;
- if(w->next) w->next->prev = w->prev;
- web_clients_cache.avail_count--;
- web_client_zero(w);
- web_clients_cache.reused++;
- }
- else {
- // allocate it
- w = web_client_alloc();
- web_clients_cache.allocated++;
- }
-
- // link it to used web clients
- if (web_clients_cache.used) web_clients_cache.used->prev = w;
- w->next = web_clients_cache.used;
- w->prev = NULL;
- web_clients_cache.used = w;
- web_clients_cache.used_count++;
-
- // initialize it
- w->id = web_client_connected();
- w->mode = WEB_CLIENT_MODE_NORMAL;
-
- netdata_thread_enable_cancelability();
-
- return w;
-}
-
-static void web_client_release(struct web_client *w) {
-#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid()))
- error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid());
-
- if(unlikely(w->running))
- error("%llu: releasing web client from %s port %s, but it still running.", w->id, w->client_ip, w->client_port);
-#endif
-
- debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
-
- log_connection(w, "DISCONNECTED");
- web_client_request_done(w);
- web_client_disconnected();
-
- netdata_thread_disable_cancelability();
-
- if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
- if (w->ifd != -1) close(w->ifd);
- if (w->ofd != -1 && w->ofd != w->ifd) close(w->ofd);
- w->ifd = w->ofd = -1;
- }
-
- // unlink it from the used
- if (w == web_clients_cache.used) web_clients_cache.used = w->next;
- if(w->prev) w->prev->next = w->next;
- if(w->next) w->next->prev = w->prev;
- web_clients_cache.used_count--;
-
- if(web_clients_cache.avail_count >= 2 * web_clients_cache.used_count) {
- // we have too many of them - free it
- web_client_free(w);
- }
- else {
- // link it to the avail
- if (web_clients_cache.avail) web_clients_cache.avail->prev = w;
- w->next = web_clients_cache.avail;
- w->prev = NULL;
- web_clients_cache.avail = w;
- web_clients_cache.avail_count++;
- }
-
- netdata_thread_enable_cancelability();
-}
-
-
-// ----------------------------------------------------------------------------
-// high level web clients connection management
-
-static void web_client_initialize_connection(struct web_client *w) {
- int flag = 1;
- if(setsockopt(w->ifd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0)
- error("%llu: failed to enable TCP_NODELAY on socket fd %d.", w->id, w->ifd);
-
- flag = 1;
- if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0)
- error("%llu: failed to enable SO_KEEPALIVE on socket fd %d.", w->id, w->ifd);
-
- web_client_update_acl_matches(w);
-
- w->origin[0] = '*'; w->origin[1] = '\0';
- w->cookie1[0] = '\0'; w->cookie2[0] = '\0';
- freez(w->user_agent); w->user_agent = NULL;
-
- web_client_enable_wait_receive(w);
-
- log_connection(w, "CONNECTED");
-
- web_client_cache_verify(0);
-}
-
-static struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const char *client_port) {
- struct web_client *w;
-
- w = web_client_get_from_cache_or_allocate();
- w->ifd = w->ofd = fd;
-
- strncpyz(w->client_ip, client_ip, sizeof(w->client_ip) - 1);
- strncpyz(w->client_port, client_port, sizeof(w->client_port) - 1);
-
- if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-");
- if(unlikely(!*w->client_port)) strcpy(w->client_port, "-");
-
- web_client_initialize_connection(w);
- return(w);
-}
-
-static struct web_client *web_client_create_on_listenfd(int listener) {
- struct web_client *w;
-
- w = web_client_get_from_cache_or_allocate();
- w->ifd = w->ofd = accept_socket(listener, SOCK_NONBLOCK, w->client_ip, sizeof(w->client_ip), w->client_port, sizeof(w->client_port), web_allow_connections_from);
-
- if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-");
- if(unlikely(!*w->client_port)) strcpy(w->client_port, "-");
-
- if (w->ifd == -1) {
- if(errno == EPERM)
- log_connection(w, "ACCESS DENIED");
- else {
- log_connection(w, "CONNECTION FAILED");
- error("%llu: Failed to accept new incoming connection.", w->id);
- }
-
- web_client_release(w);
- return NULL;
- }
-
- web_client_initialize_connection(w);
- return(w);
-}
-
-
-// --------------------------------------------------------------------------------------
-// the thread of a single client - for the MULTI-THREADED web server
-
-// 1. waits for input and output, using async I/O
-// 2. it processes HTTP requests
-// 3. it generates HTTP responses
-// 4. it copies data from input to output if mode is FILECOPY
-
-int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS;
-int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST;
-
-static void multi_threaded_web_client_worker_main_cleanup(void *ptr) {
- struct web_client *w = ptr;
- WEB_CLIENT_IS_DEAD(w);
- w->running = 0;
-}
-
-static void *multi_threaded_web_client_worker_main(void *ptr) {
- netdata_thread_cleanup_push(multi_threaded_web_client_worker_main_cleanup, ptr);
-
- struct web_client *w = ptr;
- w->running = 1;
-
- struct pollfd fds[2], *ifd, *ofd;
- int retval, timeout_ms;
- nfds_t fdmax = 0;
-
- while(!netdata_exit) {
- if(unlikely(web_client_check_dead(w))) {
- debug(D_WEB_CLIENT, "%llu: client is dead.", w->id);
- break;
- }
- else if(unlikely(!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))) {
- debug(D_WEB_CLIENT, "%llu: client is not set for neither receiving nor sending data.", w->id);
- break;
- }
-
- if(unlikely(w->ifd < 0 || w->ofd < 0)) {
- error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd", w->id, w->ifd, w->ofd);
- break;
- }
-
- if(w->ifd == w->ofd) {
- fds[0].fd = w->ifd;
- fds[0].events = 0;
- fds[0].revents = 0;
-
- if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN;
- if(web_client_has_wait_send(w)) fds[0].events |= POLLOUT;
-
- fds[1].fd = -1;
- fds[1].events = 0;
- fds[1].revents = 0;
-
- ifd = ofd = &fds[0];
-
- fdmax = 1;
- }
- else {
- fds[0].fd = w->ifd;
- fds[0].events = 0;
- fds[0].revents = 0;
- if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN;
- ifd = &fds[0];
-
- fds[1].fd = w->ofd;
- fds[1].events = 0;
- fds[1].revents = 0;
- if(web_client_has_wait_send(w)) fds[1].events |= POLLOUT;
- ofd = &fds[1];
-
- fdmax = 2;
- }
-
- debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, web_client_has_wait_receive(w)?"INPUT":"", web_client_has_wait_send(w)?"OUTPUT":"");
- errno = 0;
- timeout_ms = web_client_timeout * 1000;
- retval = poll(fds, fdmax, timeout_ms);
-
- if(unlikely(netdata_exit)) break;
-
- if(unlikely(retval == -1)) {
- if(errno == EAGAIN || errno == EINTR) {
- debug(D_WEB_CLIENT, "%llu: EAGAIN received.", w->id);
- continue;
- }
-
- debug(D_WEB_CLIENT, "%llu: LISTENER: poll() failed (input fd = %d, output fd = %d). Closing client.", w->id, w->ifd, w->ofd);
- break;
- }
- else if(unlikely(!retval)) {
- debug(D_WEB_CLIENT, "%llu: Timeout while waiting socket async I/O for %s %s", w->id, web_client_has_wait_receive(w)?"INPUT":"", web_client_has_wait_send(w)?"OUTPUT":"");
- break;
- }
-
- if(unlikely(netdata_exit)) break;
-
- int used = 0;
- if(web_client_has_wait_send(w) && ofd->revents & POLLOUT) {
- used++;
- if(web_client_send(w) < 0) {
- debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
- break;
- }
- }
-
- if(unlikely(netdata_exit)) break;
-
- if(web_client_has_wait_receive(w) && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
- used++;
- if(web_client_receive(w) < 0) {
- debug(D_WEB_CLIENT, "%llu: Cannot receive data from client. Closing client.", w->id);
- break;
- }
-
- if(w->mode == WEB_CLIENT_MODE_NORMAL) {
- debug(D_WEB_CLIENT, "%llu: Attempting to process received data.", w->id);
- web_client_process_request(w);
-
- // if the sockets are closed, may have transferred this client
- // to plugins.d
- if(unlikely(w->mode == WEB_CLIENT_MODE_STREAM))
- break;
- }
- }
-
- if(unlikely(!used)) {
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on socket.", w->id);
- break;
- }
- }
-
- if(w->mode != WEB_CLIENT_MODE_STREAM)
- log_connection(w, "DISCONNECTED");
-
- web_client_request_done(w);
-
- debug(D_WEB_CLIENT, "%llu: done...", w->id);
-
- // close the sockets/files now
- // to free file descriptors
- if(w->ifd == w->ofd) {
- if(w->ifd != -1) close(w->ifd);
- }
- else {
- if(w->ifd != -1) close(w->ifd);
- if(w->ofd != -1) close(w->ofd);
- }
- w->ifd = -1;
- w->ofd = -1;
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-// --------------------------------------------------------------------------------------
-// the main socket listener - MULTI-THREADED
-
-// 1. it accepts new incoming requests on our port
-// 2. creates a new web_client for each connection received
-// 3. spawns a new netdata_thread to serve the client (this is optimal for keep-alive clients)
-// 4. cleans up old web_clients that their netdata_threads have been exited
-
-static void web_client_multi_threaded_web_server_release_clients(void) {
- struct web_client *w;
- for(w = web_clients_cache.used; w ; ) {
- if(unlikely(!w->running && web_client_check_dead(w))) {
- struct web_client *t = w->next;
- web_client_release(w);
- w = t;
- }
- else
- w = w->next;
- }
-}
-
-static void web_client_multi_threaded_web_server_stop_all_threads(void) {
- struct web_client *w;
-
- int found = 1, max = 2 * USEC_PER_SEC, step = 50000;
- for(w = web_clients_cache.used; w ; w = w->next) {
- if(w->running) {
- found++;
- info("stopping web client %s, id %llu", w->client_ip, w->id);
- netdata_thread_cancel(w->thread);
- }
- }
-
- while(found && max > 0) {
- max -= step;
- info("Waiting %d web threads to finish...", found);
- sleep_usec(step);
- found = 0;
- for(w = web_clients_cache.used; w ; w = w->next)
- if(w->running) found++;
- }
-
- if(found)
- error("%d web threads are taking too long to finish. Giving up.", found);
-}
-
-static struct pollfd *socket_listen_main_multi_threaded_fds = NULL;
-
-static void socket_listen_main_multi_threaded_cleanup(void *data) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)data;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("cleaning up...");
-
- info("releasing allocated memory...");
- freez(socket_listen_main_multi_threaded_fds);
-
- info("closing all sockets...");
- listen_sockets_close(&api_sockets);
-
- info("stopping all running web server threads...");
- web_client_multi_threaded_web_server_stop_all_threads();
-
- info("freeing web clients cache...");
- web_client_cache_destroy();
-
- info("cleanup completed.");
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-#define CLEANUP_EVERY_EVENTS 60
-void *socket_listen_main_multi_threaded(void *ptr) {
- netdata_thread_cleanup_push(socket_listen_main_multi_threaded_cleanup, ptr);
-
- web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
- web_server_is_multithreaded = 1;
-
- struct web_client *w;
- int retval, counter = 0;
-
- if(!api_sockets.opened)
- fatal("LISTENER: No sockets to listen to.");
-
- socket_listen_main_multi_threaded_fds = callocz(sizeof(struct pollfd), api_sockets.opened);
-
- size_t i;
- for(i = 0; i < api_sockets.opened ;i++) {
- socket_listen_main_multi_threaded_fds[i].fd = api_sockets.fds[i];
- socket_listen_main_multi_threaded_fds[i].events = POLLIN;
- socket_listen_main_multi_threaded_fds[i].revents = 0;
-
- info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN");
- }
-
- int timeout_ms = 1 * 1000;
-
- while(!netdata_exit) {
-
- // debug(D_WEB_CLIENT, "LISTENER: Waiting...");
- retval = poll(socket_listen_main_multi_threaded_fds, api_sockets.opened, timeout_ms);
-
- if(unlikely(retval == -1)) {
- error("LISTENER: poll() failed.");
- continue;
- }
- else if(unlikely(!retval)) {
- debug(D_WEB_CLIENT, "LISTENER: poll() timeout.");
- counter++;
- continue;
- }
-
- for(i = 0 ; i < api_sockets.opened ; i++) {
- short int revents = socket_listen_main_multi_threaded_fds[i].revents;
-
- // check for new incoming connections
- if(revents & POLLIN || revents & POLLPRI) {
- socket_listen_main_multi_threaded_fds[i].revents = 0;
-
- w = web_client_create_on_listenfd(socket_listen_main_multi_threaded_fds[i].fd);
- if(unlikely(!w)) {
- // no need for error log - web_client_create_on_listenfd already logged the error
- continue;
- }
-
- if(api_sockets.fds_families[i] == AF_UNIX)
- web_client_set_unix(w);
- else
- web_client_set_tcp(w);
-
- char tag[NETDATA_THREAD_TAG_MAX + 1];
- snprintfz(tag, NETDATA_THREAD_TAG_MAX, "WEB_CLIENT[%llu,[%s]:%s]", w->id, w->client_ip, w->client_port);
-
- w->running = 1;
- if(netdata_thread_create(&w->thread, tag, NETDATA_THREAD_OPTION_DONT_LOG, multi_threaded_web_client_worker_main, w) != 0) {
- w->running = 0;
- web_client_release(w);
- }
- }
- }
-
- counter++;
- if(counter > CLEANUP_EVERY_EVENTS) {
- counter = 0;
- web_client_multi_threaded_web_server_release_clients();
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-
-// --------------------------------------------------------------------------------------
-// the main socket listener - SINGLE-THREADED
-
-struct web_client *single_threaded_clients[FD_SETSIZE];
-
-static inline int single_threaded_link_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds, int *max) {
- if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) {
- return 1;
- }
-
- if(unlikely(w->ifd < 0 || w->ifd >= (int)FD_SETSIZE || w->ofd < 0 || w->ofd >= (int)FD_SETSIZE)) {
- error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd < FD_SETSIZE (%d)", w->id, w->ifd, w->ofd, (int)FD_SETSIZE);
- return 1;
- }
-
- FD_SET(w->ifd, efds);
- if(unlikely(*max < w->ifd)) *max = w->ifd;
-
- if(unlikely(w->ifd != w->ofd)) {
- if(*max < w->ofd) *max = w->ofd;
- FD_SET(w->ofd, efds);
- }
-
- if(web_client_has_wait_receive(w)) FD_SET(w->ifd, ifds);
- if(web_client_has_wait_send(w)) FD_SET(w->ofd, ofds);
-
- single_threaded_clients[w->ifd] = w;
- single_threaded_clients[w->ofd] = w;
-
- return 0;
-}
-
-static inline int single_threaded_unlink_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds) {
- FD_CLR(w->ifd, efds);
- if(unlikely(w->ifd != w->ofd)) FD_CLR(w->ofd, efds);
-
- if(web_client_has_wait_receive(w)) FD_CLR(w->ifd, ifds);
- if(web_client_has_wait_send(w)) FD_CLR(w->ofd, ofds);
-
- single_threaded_clients[w->ifd] = NULL;
- single_threaded_clients[w->ofd] = NULL;
-
- if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) {
- return 1;
- }
-
- return 0;
-}
-
-static void socket_listen_main_single_threaded_cleanup(void *data) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)data;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- info("closing all sockets...");
- listen_sockets_close(&api_sockets);
-
- info("freeing web clients cache...");
- web_client_cache_destroy();
-
- info("cleanup completed.");
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *socket_listen_main_single_threaded(void *ptr) {
- netdata_thread_cleanup_push(socket_listen_main_single_threaded_cleanup, ptr);
- web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED;
- web_server_is_multithreaded = 0;
-
- struct web_client *w;
-
- if(!api_sockets.opened)
- fatal("LISTENER: no listen sockets available.");
-
- size_t i;
- for(i = 0; i < (size_t)FD_SETSIZE ; i++)
- single_threaded_clients[i] = NULL;
-
- fd_set ifds, ofds, efds, rifds, rofds, refds;
- FD_ZERO (&ifds);
- FD_ZERO (&ofds);
- FD_ZERO (&efds);
- int fdmax = 0;
-
- for(i = 0; i < api_sockets.opened ; i++) {
- if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= (int)FD_SETSIZE)
- fatal("LISTENER: Listen socket %d is not ready, or invalid.", api_sockets.fds[i]);
-
- info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN");
-
- FD_SET(api_sockets.fds[i], &ifds);
- FD_SET(api_sockets.fds[i], &efds);
- if(fdmax < api_sockets.fds[i])
- fdmax = api_sockets.fds[i];
- }
-
- while(!netdata_exit) {
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server waiting (fdmax = %d)...", fdmax);
-
- struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
- rifds = ifds;
- rofds = ofds;
- refds = efds;
- int retval = select(fdmax+1, &rifds, &rofds, &refds, &tv);
-
- if(unlikely(retval == -1)) {
- error("LISTENER: select() failed.");
- continue;
- }
- else if(likely(retval)) {
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something.");
-
- for(i = 0; i < api_sockets.opened ; i++) {
- if (FD_ISSET(api_sockets.fds[i], &rifds)) {
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection.");
- w = web_client_create_on_listenfd(api_sockets.fds[i]);
- if(unlikely(!w))
- continue;
-
- if(api_sockets.fds_families[i] == AF_UNIX)
- web_client_set_unix(w);
- else
- web_client_set_tcp(w);
-
- if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) {
- web_client_release(w);
- }
- }
- }
-
- for(i = 0 ; i <= (size_t)fdmax ; i++) {
- if(likely(!FD_ISSET(i, &rifds) && !FD_ISSET(i, &rofds) && !FD_ISSET(i, &refds)))
- continue;
-
- w = single_threaded_clients[i];
- if(unlikely(!w)) {
- // error("no client on slot %zu", i);
- continue;
- }
-
- if(unlikely(single_threaded_unlink_client(w, &ifds, &ofds, &efds) != 0)) {
- // error("failed to unlink client %zu", i);
- web_client_release(w);
- continue;
- }
-
- if (unlikely(FD_ISSET(w->ifd, &refds) || FD_ISSET(w->ofd, &refds))) {
- // error("no input on client %zu", i);
- web_client_release(w);
- continue;
- }
-
- if (unlikely(web_client_has_wait_receive(w) && FD_ISSET(w->ifd, &rifds))) {
- if (unlikely(web_client_receive(w) < 0)) {
- // error("cannot read from client %zu", i);
- web_client_release(w);
- continue;
- }
-
- if (w->mode != WEB_CLIENT_MODE_FILECOPY) {
- debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id);
- web_client_process_request(w);
- }
- }
-
- if (unlikely(web_client_has_wait_send(w) && FD_ISSET(w->ofd, &rofds))) {
- if (unlikely(web_client_send(w) < 0)) {
- // error("cannot send data to client %zu", i);
- debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
- web_client_release(w);
- continue;
- }
- }
-
- if(unlikely(single_threaded_link_client(w, &ifds, &ofds, &efds, &fdmax) != 0)) {
- // error("failed to link client %zu", i);
- web_client_release(w);
- }
- }
- }
- else {
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server timeout.");
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-
-// --------------------------------------------------------------------------------------
-// the main socket listener - STATIC-THREADED
-
-struct web_server_static_threaded_worker {
- netdata_thread_t thread;
-
- int id;
- int running;
-
- size_t max_sockets;
-
- volatile size_t connected;
- volatile size_t disconnected;
- volatile size_t receptions;
- volatile size_t sends;
- volatile size_t max_concurrent;
-
- volatile size_t files_read;
- volatile size_t file_reads;
-};
-
-static long long static_threaded_workers_count = 1;
-static struct web_server_static_threaded_worker *static_workers_private_data = NULL;
-static __thread struct web_server_static_threaded_worker *worker_private = NULL;
-
-// ----------------------------------------------------------------------------
-
-static inline int web_server_check_client_status(struct web_client *w) {
- if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))))
- return -1;
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// web server files
-
-static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void *data) {
- struct web_client *w = (struct web_client *)data;
-
- worker_private->files_read++;
-
- debug(D_WEB_CLIENT, "%llu: ADDED FILE READ ON FD %d", w->id, pi->fd);
- *events = POLLIN;
- pi->data = w;
- return w;
-}
-
-static void web_werver_file_del_callback(POLLINFO *pi) {
- struct web_client *w = (struct web_client *)pi->data;
- debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd);
-
- w->pollinfo_filecopy_slot = 0;
-
- if(unlikely(!w->pollinfo_slot)) {
- debug(D_WEB_CLIENT, "%llu: CROSS WEB CLIENT CLEANUP (iFD %d, oFD %d)", w->id, pi->fd, w->ofd);
- web_client_release(w);
- }
-}
-
-static int web_server_file_read_callback(POLLINFO *pi, short int *events) {
- struct web_client *w = (struct web_client *)pi->data;
-
- // if there is no POLLINFO linked to this, it means the client disconnected
- // stop the file reading too
- if(unlikely(!w->pollinfo_slot)) {
- debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON CLOSED WEB CLIENT", w->id, pi->fd);
- return -1;
- }
-
- if(unlikely(w->mode != WEB_CLIENT_MODE_FILECOPY || w->ifd == w->ofd)) {
- debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON NON-FILECOPY WEB CLIENT", w->id, pi->fd);
- return -1;
- }
-
- debug(D_WEB_CLIENT, "%llu: READING FILE ON FD %d", w->id, pi->fd);
-
- worker_private->file_reads++;
- ssize_t ret = unlikely(web_client_read_file(w));
-
- if(likely(web_client_has_wait_send(w))) {
- POLLJOB *p = pi->p; // our POLLJOB
- POLLINFO *wpi = pollinfo_from_slot(p, w->pollinfo_slot); // POLLINFO of the client socket
-
- debug(D_WEB_CLIENT, "%llu: SIGNALING W TO SEND (iFD %d, oFD %d)", w->id, pi->fd, wpi->fd);
- p->fds[wpi->slot].events |= POLLOUT;
- }
-
- if(unlikely(ret <= 0 || w->ifd == w->ofd)) {
- debug(D_WEB_CLIENT, "%llu: DONE READING FILE ON FD %d", w->id, pi->fd);
- return -1;
- }
-
- *events = POLLIN;
- return 0;
-}
-
-static int web_server_file_write_callback(POLLINFO *pi, short int *events) {
- (void)pi;
- (void)events;
-
- error("Writing to web files is not supported!");
-
- return -1;
-}
-
-// ----------------------------------------------------------------------------
-// web server clients
-
-static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) {
- (void)data;
-
- worker_private->connected++;
-
- size_t concurrent = worker_private->connected - worker_private->disconnected;
- if(unlikely(concurrent > worker_private->max_concurrent))
- worker_private->max_concurrent = concurrent;
-
- *events = POLLIN;
-
- debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", pi->fd);
- struct web_client *w = web_client_create_on_fd(pi->fd, pi->client_ip, pi->client_port);
- w->pollinfo_slot = pi->slot;
-
- if(unlikely(pi->socktype == AF_UNIX))
- web_client_set_unix(w);
- else
- web_client_set_tcp(w);
-
- debug(D_WEB_CLIENT, "%llu: ADDED CLIENT FD %d", w->id, pi->fd);
- return w;
-}
-
-// TCP client disconnected
-static void web_server_del_callback(POLLINFO *pi) {
- worker_private->disconnected++;
-
- struct web_client *w = (struct web_client *)pi->data;
-
- w->pollinfo_slot = 0;
- if(unlikely(w->pollinfo_filecopy_slot)) {
- POLLINFO *fpi = pollinfo_from_slot(pi->p, w->pollinfo_filecopy_slot); // POLLINFO of the client socket
- debug(D_WEB_CLIENT, "%llu: THE CLIENT WILL BE FRED BY READING FILE JOB ON FD %d", w->id, fpi->fd);
- }
- else {
- if(web_client_flag_check(w, WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET))
- pi->flags |= POLLINFO_FLAG_DONT_CLOSE;
-
- debug(D_WEB_CLIENT, "%llu: CLOSING CLIENT FD %d", w->id, pi->fd);
- web_client_release(w);
- }
-}
-
-static int web_server_rcv_callback(POLLINFO *pi, short int *events) {
- worker_private->receptions++;
-
- struct web_client *w = (struct web_client *)pi->data;
- int fd = pi->fd;
-
- if(unlikely(web_client_receive(w) < 0))
- return -1;
-
- debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd);
- web_client_process_request(w);
-
- if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
- if(w->pollinfo_filecopy_slot == 0) {
- debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd);
-
- if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) {
- // add a new socket to poll_events, with the same
- debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd);
-
- POLLINFO *fpi = poll_add_fd(
- pi->p
- , w->ifd
- , 0
- , POLLINFO_FLAG_CLIENT_SOCKET
- , "FILENAME"
- , ""
- , web_server_file_add_callback
- , web_werver_file_del_callback
- , web_server_file_read_callback
- , web_server_file_write_callback
- , (void *) w
- );
-
- if(fpi)
- w->pollinfo_filecopy_slot = fpi->slot;
- else {
- error("Failed to add filecopy fd. Closing client.");
- return -1;
- }
- }
- }
- }
- else {
- if(unlikely(w->ifd == fd && web_client_has_wait_receive(w)))
- *events |= POLLIN;
- }
-
- if(unlikely(w->ofd == fd && web_client_has_wait_send(w)))
- *events |= POLLOUT;
-
- return web_server_check_client_status(w);
-}
-
-static int web_server_snd_callback(POLLINFO *pi, short int *events) {
- worker_private->sends++;
-
- struct web_client *w = (struct web_client *)pi->data;
- int fd = pi->fd;
-
- debug(D_WEB_CLIENT, "%llu: sending data on fd %d.", w->id, fd);
-
- if(unlikely(web_client_send(w) < 0))
- return -1;
-
- if(unlikely(w->ifd == fd && web_client_has_wait_receive(w)))
- *events |= POLLIN;
-
- if(unlikely(w->ofd == fd && web_client_has_wait_send(w)))
- *events |= POLLOUT;
-
- return web_server_check_client_status(w);
-}
-
-static void web_server_tmr_callback(void *timer_data) {
- worker_private = (struct web_server_static_threaded_worker *)timer_data;
-
- static __thread RRDSET *st = NULL;
- static __thread RRDDIM *rd_user = NULL, *rd_system = NULL;
-
- if(unlikely(!st)) {
- char id[100 + 1];
- char title[100 + 1];
-
- snprintfz(id, 100, "web_thread%d_cpu", worker_private->id + 1);
- snprintfz(title, 100, "NetData web server thread No %d CPU usage", worker_private->id + 1);
-
- st = rrdset_create_localhost(
- "netdata"
- , id
- , NULL
- , "web"
- , "netdata.web_cpu"
- , title
- , "milliseconds/s"
- , "web"
- , "stats"
- , 132000 + worker_private->id
- , default_rrd_update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_user = rrddim_add(st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- rd_system = rrddim_add(st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st);
-
- struct rusage rusage;
- getrusage(RUSAGE_THREAD, &rusage);
- rrddim_set_by_pointer(st, rd_user, rusage.ru_utime.tv_sec * 1000000ULL + rusage.ru_utime.tv_usec);
- rrddim_set_by_pointer(st, rd_system, rusage.ru_stime.tv_sec * 1000000ULL + rusage.ru_stime.tv_usec);
- rrdset_done(st);
-}
-
-// ----------------------------------------------------------------------------
-// web server worker thread
-
-static void socket_listen_main_static_threaded_worker_cleanup(void *ptr) {
- worker_private = (struct web_server_static_threaded_worker *)ptr;
-
- info("freeing local web clients cache...");
- web_client_cache_destroy();
-
- info("stopped after %zu connects, %zu disconnects (max concurrent %zu), %zu receptions and %zu sends",
- worker_private->connected,
- worker_private->disconnected,
- worker_private->max_concurrent,
- worker_private->receptions,
- worker_private->sends
- );
-
- worker_private->running = 0;
-}
-
-void *socket_listen_main_static_threaded_worker(void *ptr) {
- worker_private = (struct web_server_static_threaded_worker *)ptr;
- worker_private->running = 1;
-
- netdata_thread_cleanup_push(socket_listen_main_static_threaded_worker_cleanup, ptr);
-
- poll_events(&api_sockets
- , web_server_add_callback
- , web_server_del_callback
- , web_server_rcv_callback
- , web_server_snd_callback
- , web_server_tmr_callback
- , web_allow_connections_from
- , NULL
- , web_client_first_request_timeout
- , web_client_timeout
- , default_rrd_update_every * 1000 // timer_milliseconds
- , ptr // timer_data
- , worker_private->max_sockets
- );
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-
-// ----------------------------------------------------------------------------
-// web server main thread - also becomes a worker
-
-static void socket_listen_main_static_threaded_cleanup(void *ptr) {
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
-
- int i, found = 0, max = 2 * USEC_PER_SEC, step = 50000;
-
- // we start from 1, - 0 is self
- for(i = 1; i < static_threaded_workers_count; i++) {
- if(static_workers_private_data[i].running) {
- found++;
- info("stopping worker %d", i + 1);
- netdata_thread_cancel(static_workers_private_data[i].thread);
- }
- else
- info("found stopped worker %d", i + 1);
- }
-
- while(found && max > 0) {
- max -= step;
- info("Waiting %d static web threads to finish...", found);
- sleep_usec(step);
- found = 0;
-
- // we start from 1, - 0 is self
- for(i = 1; i < static_threaded_workers_count; i++) {
- if (static_workers_private_data[i].running)
- found++;
- }
- }
-
- if(found)
- error("%d static web threads are taking too long to finish. Giving up.", found);
-
- info("closing all web server sockets...");
- listen_sockets_close(&api_sockets);
-
- info("all static web threads stopped.");
- static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
-}
-
-void *socket_listen_main_static_threaded(void *ptr) {
- netdata_thread_cleanup_push(socket_listen_main_static_threaded_cleanup, ptr);
- web_server_mode = WEB_SERVER_MODE_STATIC_THREADED;
-
- if(!api_sockets.opened)
- fatal("LISTENER: no listen sockets available.");
-
- // 6 threads is the optimal value
- // since 6 are the parallel connections browsers will do
- // so, if the machine has more CPUs, avoid using resources unnecessarily
- int def_thread_count = (processors > 6)?6:processors;
-
- static_threaded_workers_count = config_get_number(CONFIG_SECTION_WEB, "web server threads", def_thread_count);
- if(static_threaded_workers_count < 1) static_threaded_workers_count = 1;
-
- size_t max_sockets = (size_t)config_get_number(CONFIG_SECTION_WEB, "web server max sockets", (long long int)(rlimit_nofile.rlim_cur / 2));
-
- static_workers_private_data = callocz((size_t)static_threaded_workers_count, sizeof(struct web_server_static_threaded_worker));
-
- web_server_is_multithreaded = (static_threaded_workers_count > 1);
-
- int i;
- for(i = 1; i < static_threaded_workers_count; i++) {
- static_workers_private_data[i].id = i;
- static_workers_private_data[i].max_sockets = max_sockets / static_threaded_workers_count;
-
- char tag[50 + 1];
- snprintfz(tag, 50, "WEB_SERVER[static%d]", i+1);
-
- info("starting worker %d", i+1);
- netdata_thread_create(&static_workers_private_data[i].thread, tag, NETDATA_THREAD_OPTION_DEFAULT, socket_listen_main_static_threaded_worker, (void *)&static_workers_private_data[i]);
- }
-
- // and the main one
- static_workers_private_data[0].max_sockets = max_sockets / static_threaded_workers_count;
- socket_listen_main_static_threaded_worker((void *)&static_workers_private_data[0]);
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
diff --git a/src/web_server.h b/src/web_server.h
deleted file mode 100644
index 7492547ef..000000000
--- a/src/web_server.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef NETDATA_WEB_SERVER_H
-#define NETDATA_WEB_SERVER_H 1
-
-#define WEB_PATH_FILE "file"
-#define WEB_PATH_DATA "data"
-#define WEB_PATH_DATASOURCE "datasource"
-#define WEB_PATH_GRAPH "graph"
-
-#ifndef API_LISTEN_PORT
-#define API_LISTEN_PORT 19999
-#endif
-
-#ifndef API_LISTEN_BACKLOG
-#define API_LISTEN_BACKLOG 4096
-#endif
-
-typedef enum web_server_mode {
- WEB_SERVER_MODE_SINGLE_THREADED,
- WEB_SERVER_MODE_STATIC_THREADED,
- WEB_SERVER_MODE_MULTI_THREADED,
- WEB_SERVER_MODE_NONE
-} WEB_SERVER_MODE;
-
-extern SIMPLE_PATTERN *web_allow_connections_from;
-extern SIMPLE_PATTERN *web_allow_dashboard_from;
-extern SIMPLE_PATTERN *web_allow_registry_from;
-extern SIMPLE_PATTERN *web_allow_badges_from;
-extern SIMPLE_PATTERN *web_allow_streaming_from;
-extern SIMPLE_PATTERN *web_allow_netdataconf_from;
-
-extern WEB_SERVER_MODE web_server_mode;
-
-extern WEB_SERVER_MODE web_server_mode_id(const char *mode);
-extern const char *web_server_mode_name(WEB_SERVER_MODE id);
-
-extern void *socket_listen_main_multi_threaded(void *ptr);
-extern void *socket_listen_main_single_threaded(void *ptr);
-extern void *socket_listen_main_static_threaded(void *ptr);
-extern int api_listen_sockets_setup(void);
-
-#define DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST 60
-#define DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS 60
-extern int web_client_timeout;
-extern int web_client_first_request_timeout;
-
-#endif /* NETDATA_WEB_SERVER_H */
diff --git a/src/zfs_common.c b/src/zfs_common.c
deleted file mode 100644
index 05935dd0f..000000000
--- a/src/zfs_common.c
+++ /dev/null
@@ -1,713 +0,0 @@
-#include "common.h"
-#include "zfs_common.h"
-
-struct arcstats arcstats = { 0 };
-
-void generate_charts_arcstats(const char *plugin, int update_every) {
-
- // ARC reads
- unsigned long long aread = arcstats.hits + arcstats.misses;
-
- // Demand reads
- unsigned long long dhit = arcstats.demand_data_hits + arcstats.demand_metadata_hits;
- unsigned long long dmiss = arcstats.demand_data_misses + arcstats.demand_metadata_misses;
- unsigned long long dread = dhit + dmiss;
-
- // Prefetch reads
- unsigned long long phit = arcstats.prefetch_data_hits + arcstats.prefetch_metadata_hits;
- unsigned long long pmiss = arcstats.prefetch_data_misses + arcstats.prefetch_metadata_misses;
- unsigned long long pread = phit + pmiss;
-
- // Metadata reads
- unsigned long long mhit = arcstats.prefetch_metadata_hits + arcstats.demand_metadata_hits;
- unsigned long long mmiss = arcstats.prefetch_metadata_misses + arcstats.demand_metadata_misses;
- unsigned long long mread = mhit + mmiss;
-
- // l2 reads
- unsigned long long l2hit = arcstats.l2_hits;
- unsigned long long l2miss = arcstats.l2_misses;
- unsigned long long l2read = l2hit + l2miss;
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_arc_size = NULL;
- static RRDDIM *rd_arc_size = NULL;
- static RRDDIM *rd_arc_target_size = NULL;
- static RRDDIM *rd_arc_target_min_size = NULL;
- static RRDDIM *rd_arc_target_max_size = NULL;
-
- if (unlikely(!st_arc_size)) {
- st_arc_size = rrdset_create_localhost(
- "zfs"
- , "arc_size"
- , NULL
- , ZFS_FAMILY_SIZE
- , NULL
- , "ZFS ARC Size"
- , "MB"
- , plugin
- , "zfs"
- , 2500
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_arc_size = rrddim_add(st_arc_size, "size", "arcsz", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_arc_target_size = rrddim_add(st_arc_size, "target", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_arc_target_min_size = rrddim_add(st_arc_size, "min", "min (hard limit)", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_arc_target_max_size = rrddim_add(st_arc_size, "max", "max (high water)", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_arc_size);
-
- rrddim_set_by_pointer(st_arc_size, rd_arc_size, arcstats.size);
- rrddim_set_by_pointer(st_arc_size, rd_arc_target_size, arcstats.c);
- rrddim_set_by_pointer(st_arc_size, rd_arc_target_min_size, arcstats.c_min);
- rrddim_set_by_pointer(st_arc_size, rd_arc_target_max_size, arcstats.c_max);
- rrdset_done(st_arc_size);
- }
-
- // --------------------------------------------------------------------
-
- if(likely(arcstats.l2exist)) {
- static RRDSET *st_l2_size = NULL;
- static RRDDIM *rd_l2_size = NULL;
- static RRDDIM *rd_l2_asize = NULL;
-
- if (unlikely(!st_l2_size)) {
- st_l2_size = rrdset_create_localhost(
- "zfs"
- , "l2_size"
- , NULL
- , ZFS_FAMILY_SIZE
- , NULL
- , "ZFS L2 ARC Size"
- , "MB"
- , plugin
- , "zfs"
- , 2500
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_l2_asize = rrddim_add(st_l2_size, "actual", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- rd_l2_size = rrddim_add(st_l2_size, "size", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_l2_size);
-
- rrddim_set_by_pointer(st_l2_size, rd_l2_size, arcstats.l2_size);
- rrddim_set_by_pointer(st_l2_size, rd_l2_asize, arcstats.l2_asize);
- rrdset_done(st_l2_size);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_reads = NULL;
- static RRDDIM *rd_aread = NULL;
- static RRDDIM *rd_dread = NULL;
- static RRDDIM *rd_pread = NULL;
- static RRDDIM *rd_mread = NULL;
- static RRDDIM *rd_l2read = NULL;
-
- if (unlikely(!st_reads)) {
- st_reads = rrdset_create_localhost(
- "zfs"
- , "reads"
- , NULL
- , ZFS_FAMILY_ACCESSES
- , NULL
- , "ZFS Reads"
- , "reads/s"
- , plugin
- , "zfs"
- , 2510
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_aread = rrddim_add(st_reads, "areads", "arc", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_dread = rrddim_add(st_reads, "dreads", "demand", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_pread = rrddim_add(st_reads, "preads", "prefetch", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_mread = rrddim_add(st_reads, "mreads", "metadata", 1, 1, RRD_ALGORITHM_INCREMENTAL);
-
- if(arcstats.l2exist)
- rd_l2read = rrddim_add(st_reads, "l2reads", "l2", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_reads);
-
- rrddim_set_by_pointer(st_reads, rd_aread, aread);
- rrddim_set_by_pointer(st_reads, rd_dread, dread);
- rrddim_set_by_pointer(st_reads, rd_pread, pread);
- rrddim_set_by_pointer(st_reads, rd_mread, mread);
-
- if(arcstats.l2exist)
- rrddim_set_by_pointer(st_reads, rd_l2read, l2read);
-
- rrdset_done(st_reads);
- }
-
- // --------------------------------------------------------------------
-
- if(likely(arcstats.l2exist)) {
- static RRDSET *st_l2bytes = NULL;
- static RRDDIM *rd_l2_read_bytes = NULL;
- static RRDDIM *rd_l2_write_bytes = NULL;
-
- if (unlikely(!st_l2bytes)) {
- st_l2bytes = rrdset_create_localhost(
- "zfs"
- , "bytes"
- , NULL
- , ZFS_FAMILY_ACCESSES
- , NULL
- , "ZFS ARC L2 Read/Write Rate"
- , "kilobytes/s"
- , plugin
- , "zfs"
- , 2700
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_l2_read_bytes = rrddim_add(st_l2bytes, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
- rd_l2_write_bytes = rrddim_add(st_l2bytes, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_l2bytes);
-
- rrddim_set_by_pointer(st_l2bytes, rd_l2_read_bytes, arcstats.l2_read_bytes);
- rrddim_set_by_pointer(st_l2bytes, rd_l2_write_bytes, arcstats.l2_write_bytes);
- rrdset_done(st_l2bytes);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_ahits = NULL;
- static RRDDIM *rd_ahits = NULL;
- static RRDDIM *rd_amisses = NULL;
-
- if (unlikely(!st_ahits)) {
- st_ahits = rrdset_create_localhost(
- "zfs"
- , "hits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS ARC Hits"
- , "percentage"
- , plugin
- , "zfs"
- , 2520
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_ahits = rrddim_add(st_ahits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_amisses = rrddim_add(st_ahits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_ahits);
-
- rrddim_set_by_pointer(st_ahits, rd_ahits, arcstats.hits);
- rrddim_set_by_pointer(st_ahits, rd_amisses, arcstats.misses);
- rrdset_done(st_ahits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_dhits = NULL;
- static RRDDIM *rd_dhits = NULL;
- static RRDDIM *rd_dmisses = NULL;
-
- if (unlikely(!st_dhits)) {
- st_dhits = rrdset_create_localhost(
- "zfs"
- , "dhits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS Demand Hits"
- , "percentage"
- , plugin
- , "zfs"
- , 2530
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_dhits = rrddim_add(st_dhits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_dmisses = rrddim_add(st_dhits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_dhits);
-
- rrddim_set_by_pointer(st_dhits, rd_dhits, dhit);
- rrddim_set_by_pointer(st_dhits, rd_dmisses, dmiss);
- rrdset_done(st_dhits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_phits = NULL;
- static RRDDIM *rd_phits = NULL;
- static RRDDIM *rd_pmisses = NULL;
-
- if (unlikely(!st_phits)) {
- st_phits = rrdset_create_localhost(
- "zfs"
- , "phits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS Prefetch Hits"
- , "percentage"
- , plugin
- , "zfs"
- , 2540
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_phits = rrddim_add(st_phits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_pmisses = rrddim_add(st_phits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_phits);
-
- rrddim_set_by_pointer(st_phits, rd_phits, phit);
- rrddim_set_by_pointer(st_phits, rd_pmisses, pmiss);
- rrdset_done(st_phits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_mhits = NULL;
- static RRDDIM *rd_mhits = NULL;
- static RRDDIM *rd_mmisses = NULL;
-
- if (unlikely(!st_mhits)) {
- st_mhits = rrdset_create_localhost(
- "zfs"
- , "mhits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS Metadata Hits"
- , "percentage"
- , plugin
- , "zfs"
- , 2550
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_mhits = rrddim_add(st_mhits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_mmisses = rrddim_add(st_mhits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_mhits);
-
- rrddim_set_by_pointer(st_mhits, rd_mhits, mhit);
- rrddim_set_by_pointer(st_mhits, rd_mmisses, mmiss);
- rrdset_done(st_mhits);
- }
-
- // --------------------------------------------------------------------
-
- if(likely(arcstats.l2exist)) {
- static RRDSET *st_l2hits = NULL;
- static RRDDIM *rd_l2hits = NULL;
- static RRDDIM *rd_l2misses = NULL;
-
- if (unlikely(!st_l2hits)) {
- st_l2hits = rrdset_create_localhost(
- "zfs"
- , "l2hits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS L2 Hits"
- , "percentage"
- , plugin
- , "zfs"
- , 2560
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_l2hits = rrddim_add(st_l2hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_l2misses = rrddim_add(st_l2hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_l2hits);
-
- rrddim_set_by_pointer(st_l2hits, rd_l2hits, l2hit);
- rrddim_set_by_pointer(st_l2hits, rd_l2misses, l2miss);
- rrdset_done(st_l2hits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_list_hits = NULL;
- static RRDDIM *rd_mfu = NULL;
- static RRDDIM *rd_mru = NULL;
- static RRDDIM *rd_mfug = NULL;
- static RRDDIM *rd_mrug = NULL;
-
- if (unlikely(!st_list_hits)) {
- st_list_hits = rrdset_create_localhost(
- "zfs"
- , "list_hits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS List Hits"
- , "hits/s"
- , plugin
- , "zfs"
- , 2600
- , update_every
- , RRDSET_TYPE_AREA
- );
-
- rd_mfu = rrddim_add(st_list_hits, "mfu", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_mfug = rrddim_add(st_list_hits, "mfug", "mfu ghost", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_mru = rrddim_add(st_list_hits, "mru", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_mrug = rrddim_add(st_list_hits, "mrug", "mru ghost", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_list_hits);
-
- rrddim_set_by_pointer(st_list_hits, rd_mfu, arcstats.mfu_hits);
- rrddim_set_by_pointer(st_list_hits, rd_mru, arcstats.mru_hits);
- rrddim_set_by_pointer(st_list_hits, rd_mfug, arcstats.mfu_ghost_hits);
- rrddim_set_by_pointer(st_list_hits, rd_mrug, arcstats.mru_ghost_hits);
- rrdset_done(st_list_hits);
- }
-}
-
-void generate_charts_arc_summary(const char *plugin, int update_every) {
- unsigned long long arc_accesses_total = arcstats.hits + arcstats.misses;
- unsigned long long real_hits = arcstats.mfu_hits + arcstats.mru_hits;
- unsigned long long real_misses = arc_accesses_total - real_hits;
-
- //unsigned long long anon_hits = arcstats.hits - (arcstats.mfu_hits + arcstats.mru_hits + arcstats.mfu_ghost_hits + arcstats.mru_ghost_hits);
-
- unsigned long long arc_size = arcstats.size;
- unsigned long long mru_size = arcstats.p;
- //unsigned long long target_min_size = arcstats.c_min;
- //unsigned long long target_max_size = arcstats.c_max;
- unsigned long long target_size = arcstats.c;
- //unsigned long long target_size_ratio = (target_max_size / target_min_size);
-
- unsigned long long mfu_size;
- if(arc_size > target_size)
- mfu_size = arc_size - mru_size;
- else
- mfu_size = target_size - mru_size;
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_arc_size_breakdown = NULL;
- static RRDDIM *rd_most_recent = NULL;
- static RRDDIM *rd_most_frequent = NULL;
-
- if (unlikely(!st_arc_size_breakdown)) {
- st_arc_size_breakdown = rrdset_create_localhost(
- "zfs"
- , "arc_size_breakdown"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS ARC Size Breakdown"
- , "percentage"
- , plugin
- , "zfs"
- , 2520
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_most_recent = rrddim_add(st_arc_size_breakdown, "recent", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL);
- rd_most_frequent = rrddim_add(st_arc_size_breakdown, "frequent", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL);
- }
- else
- rrdset_next(st_arc_size_breakdown);
-
- rrddim_set_by_pointer(st_arc_size_breakdown, rd_most_recent, mru_size);
- rrddim_set_by_pointer(st_arc_size_breakdown, rd_most_frequent, mfu_size);
- rrdset_done(st_arc_size_breakdown);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_memory = NULL;
-#ifndef __FreeBSD__
- static RRDDIM *rd_direct = NULL;
-#endif
- static RRDDIM *rd_throttled = NULL;
-#ifndef __FreeBSD__
- static RRDDIM *rd_indirect = NULL;
-#endif
-
- if (unlikely(!st_memory)) {
- st_memory = rrdset_create_localhost(
- "zfs"
- , "memory_ops"
- , NULL
- , ZFS_FAMILY_OPERATIONS
- , NULL
- , "ZFS Memory Operations"
- , "operations/s"
- , plugin
- , "zfs"
- , 2523
- , update_every
- , RRDSET_TYPE_LINE
- );
-
-#ifndef __FreeBSD__
- rd_direct = rrddim_add(st_memory, "direct", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#endif
- rd_throttled = rrddim_add(st_memory, "throttled", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#ifndef __FreeBSD__
- rd_indirect = rrddim_add(st_memory, "indirect", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
-#endif
- }
- else
- rrdset_next(st_memory);
-
-#ifndef __FreeBSD__
- rrddim_set_by_pointer(st_memory, rd_direct, arcstats.memory_direct_count);
-#endif
- rrddim_set_by_pointer(st_memory, rd_throttled, arcstats.memory_throttle_count);
-#ifndef __FreeBSD__
- rrddim_set_by_pointer(st_memory, rd_indirect, arcstats.memory_indirect_count);
-#endif
- rrdset_done(st_memory);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_important_ops = NULL;
- static RRDDIM *rd_deleted = NULL;
- static RRDDIM *rd_mutex_misses = NULL;
- static RRDDIM *rd_evict_skips = NULL;
- static RRDDIM *rd_hash_collisions = NULL;
-
- if (unlikely(!st_important_ops)) {
- st_important_ops = rrdset_create_localhost(
- "zfs"
- , "important_ops"
- , NULL
- , ZFS_FAMILY_OPERATIONS
- , NULL
- , "ZFS Important Operations"
- , "operations/s"
- , plugin
- , "zfs"
- , 2522
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_evict_skips = rrddim_add(st_important_ops, "eskip", "evict skip", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_deleted = rrddim_add(st_important_ops, "deleted", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_mutex_misses = rrddim_add(st_important_ops, "mtxmis", "mutex miss", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- rd_hash_collisions = rrddim_add(st_important_ops, "hash_collisions", "hash collisions", 1, 1, RRD_ALGORITHM_INCREMENTAL);
- }
- else
- rrdset_next(st_important_ops);
-
- rrddim_set_by_pointer(st_important_ops, rd_deleted, arcstats.deleted);
- rrddim_set_by_pointer(st_important_ops, rd_evict_skips, arcstats.evict_skip);
- rrddim_set_by_pointer(st_important_ops, rd_mutex_misses, arcstats.mutex_miss);
- rrddim_set_by_pointer(st_important_ops, rd_hash_collisions, arcstats.hash_collisions);
- rrdset_done(st_important_ops);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_actual_hits = NULL;
- static RRDDIM *rd_actual_hits = NULL;
- static RRDDIM *rd_actual_misses = NULL;
-
- if (unlikely(!st_actual_hits)) {
- st_actual_hits = rrdset_create_localhost(
- "zfs"
- , "actual_hits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS Actual Cache Hits"
- , "percentage"
- , plugin
- , "zfs"
- , 2519
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_actual_hits = rrddim_add(st_actual_hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_actual_misses = rrddim_add(st_actual_hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_actual_hits);
-
- rrddim_set_by_pointer(st_actual_hits, rd_actual_hits, real_hits);
- rrddim_set_by_pointer(st_actual_hits, rd_actual_misses, real_misses);
- rrdset_done(st_actual_hits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_demand_data_hits = NULL;
- static RRDDIM *rd_demand_data_hits = NULL;
- static RRDDIM *rd_demand_data_misses = NULL;
-
- if (unlikely(!st_demand_data_hits)) {
- st_demand_data_hits = rrdset_create_localhost(
- "zfs"
- , "demand_data_hits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS Data Demand Efficiency"
- , "percentage"
- , plugin
- , "zfs"
- , 2531
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_demand_data_hits = rrddim_add(st_demand_data_hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_demand_data_misses = rrddim_add(st_demand_data_hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_demand_data_hits);
-
- rrddim_set_by_pointer(st_demand_data_hits, rd_demand_data_hits, arcstats.demand_data_hits);
- rrddim_set_by_pointer(st_demand_data_hits, rd_demand_data_misses, arcstats.demand_data_misses);
- rrdset_done(st_demand_data_hits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_prefetch_data_hits = NULL;
- static RRDDIM *rd_prefetch_data_hits = NULL;
- static RRDDIM *rd_prefetch_data_misses = NULL;
-
- if (unlikely(!st_prefetch_data_hits)) {
- st_prefetch_data_hits = rrdset_create_localhost(
- "zfs"
- , "prefetch_data_hits"
- , NULL
- , ZFS_FAMILY_EFFICIENCY
- , NULL
- , "ZFS Data Prefetch Efficiency"
- , "percentage"
- , plugin
- , "zfs"
- , 2532
- , update_every
- , RRDSET_TYPE_STACKED
- );
-
- rd_prefetch_data_hits = rrddim_add(st_prefetch_data_hits, "hits", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- rd_prefetch_data_misses = rrddim_add(st_prefetch_data_hits, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
- }
- else
- rrdset_next(st_prefetch_data_hits);
-
- rrddim_set_by_pointer(st_prefetch_data_hits, rd_prefetch_data_hits, arcstats.prefetch_data_hits);
- rrddim_set_by_pointer(st_prefetch_data_hits, rd_prefetch_data_misses, arcstats.prefetch_data_misses);
- rrdset_done(st_prefetch_data_hits);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_hash_elements = NULL;
- static RRDDIM *rd_hash_elements_current = NULL;
- static RRDDIM *rd_hash_elements_max = NULL;
-
- if (unlikely(!st_hash_elements)) {
- st_hash_elements = rrdset_create_localhost(
- "zfs"
- , "hash_elements"
- , NULL
- , ZFS_FAMILY_HASH
- , NULL
- , "ZFS ARC Hash Elements"
- , "elements"
- , plugin
- , "zfs"
- , 2800
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_hash_elements_current = rrddim_add(st_hash_elements, "current", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_hash_elements_max = rrddim_add(st_hash_elements, "max", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_hash_elements);
-
- rrddim_set_by_pointer(st_hash_elements, rd_hash_elements_current, arcstats.hash_elements);
- rrddim_set_by_pointer(st_hash_elements, rd_hash_elements_max, arcstats.hash_elements_max);
- rrdset_done(st_hash_elements);
- }
-
- // --------------------------------------------------------------------
-
- {
- static RRDSET *st_hash_chains = NULL;
- static RRDDIM *rd_hash_chains_current = NULL;
- static RRDDIM *rd_hash_chains_max = NULL;
-
- if (unlikely(!st_hash_chains)) {
- st_hash_chains = rrdset_create_localhost(
- "zfs"
- , "hash_chains"
- , NULL
- , ZFS_FAMILY_HASH
- , NULL
- , "ZFS ARC Hash Chains"
- , "chains"
- , plugin
- , "zfs"
- , 2810
- , update_every
- , RRDSET_TYPE_LINE
- );
-
- rd_hash_chains_current = rrddim_add(st_hash_chains, "current", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- rd_hash_chains_max = rrddim_add(st_hash_chains, "max", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- }
- else
- rrdset_next(st_hash_chains);
-
- rrddim_set_by_pointer(st_hash_chains, rd_hash_chains_current, arcstats.hash_chains);
- rrddim_set_by_pointer(st_hash_chains, rd_hash_chains_max, arcstats.hash_chain_max);
- rrdset_done(st_hash_chains);
- }
-
- // --------------------------------------------------------------------
-
-} \ No newline at end of file
diff --git a/src/zfs_common.h b/src/zfs_common.h
deleted file mode 100644
index 4494e70ca..000000000
--- a/src/zfs_common.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef NETDATA_ZFS_COMMON_H
-#define NETDATA_ZFS_COMMON_H
-
-#define ZFS_FAMILY_SIZE "size"
-#define ZFS_FAMILY_EFFICIENCY "efficiency"
-#define ZFS_FAMILY_ACCESSES "accesses"
-#define ZFS_FAMILY_OPERATIONS "operations"
-#define ZFS_FAMILY_HASH "hashes"
-
-struct arcstats {
- // values
- unsigned long long hits;
- unsigned long long misses;
- unsigned long long demand_data_hits;
- unsigned long long demand_data_misses;
- unsigned long long demand_metadata_hits;
- unsigned long long demand_metadata_misses;
- unsigned long long prefetch_data_hits;
- unsigned long long prefetch_data_misses;
- unsigned long long prefetch_metadata_hits;
- unsigned long long prefetch_metadata_misses;
- unsigned long long mru_hits;
- unsigned long long mru_ghost_hits;
- unsigned long long mfu_hits;
- unsigned long long mfu_ghost_hits;
- unsigned long long deleted;
- unsigned long long mutex_miss;
- unsigned long long evict_skip;
- unsigned long long evict_not_enough;
- unsigned long long evict_l2_cached;
- unsigned long long evict_l2_eligible;
- unsigned long long evict_l2_ineligible;
- unsigned long long evict_l2_skip;
- unsigned long long hash_elements;
- unsigned long long hash_elements_max;
- unsigned long long hash_collisions;
- unsigned long long hash_chains;
- unsigned long long hash_chain_max;
- unsigned long long p;
- unsigned long long c;
- unsigned long long c_min;
- unsigned long long c_max;
- unsigned long long size;
- unsigned long long hdr_size;
- unsigned long long data_size;
- unsigned long long metadata_size;
- unsigned long long other_size;
- unsigned long long anon_size;
- unsigned long long anon_evictable_data;
- unsigned long long anon_evictable_metadata;
- unsigned long long mru_size;
- unsigned long long mru_evictable_data;
- unsigned long long mru_evictable_metadata;
- unsigned long long mru_ghost_size;
- unsigned long long mru_ghost_evictable_data;
- unsigned long long mru_ghost_evictable_metadata;
- unsigned long long mfu_size;
- unsigned long long mfu_evictable_data;
- unsigned long long mfu_evictable_metadata;
- unsigned long long mfu_ghost_size;
- unsigned long long mfu_ghost_evictable_data;
- unsigned long long mfu_ghost_evictable_metadata;
- unsigned long long l2_hits;
- unsigned long long l2_misses;
- unsigned long long l2_feeds;
- unsigned long long l2_rw_clash;
- unsigned long long l2_read_bytes;
- unsigned long long l2_write_bytes;
- unsigned long long l2_writes_sent;
- unsigned long long l2_writes_done;
- unsigned long long l2_writes_error;
- unsigned long long l2_writes_lock_retry;
- unsigned long long l2_evict_lock_retry;
- unsigned long long l2_evict_reading;
- unsigned long long l2_evict_l1cached;
- unsigned long long l2_free_on_write;
- unsigned long long l2_cdata_free_on_write;
- unsigned long long l2_abort_lowmem;
- unsigned long long l2_cksum_bad;
- unsigned long long l2_io_error;
- unsigned long long l2_size;
- unsigned long long l2_asize;
- unsigned long long l2_hdr_size;
- unsigned long long l2_compress_successes;
- unsigned long long l2_compress_zeros;
- unsigned long long l2_compress_failures;
- unsigned long long memory_throttle_count;
- unsigned long long duplicate_buffers;
- unsigned long long duplicate_buffers_size;
- unsigned long long duplicate_reads;
- unsigned long long memory_direct_count;
- unsigned long long memory_indirect_count;
- unsigned long long arc_no_grow;
- unsigned long long arc_tempreserve;
- unsigned long long arc_loaned_bytes;
- unsigned long long arc_prune;
- unsigned long long arc_meta_used;
- unsigned long long arc_meta_limit;
- unsigned long long arc_meta_max;
- unsigned long long arc_meta_min;
- unsigned long long arc_need_free;
- unsigned long long arc_sys_free;
-
- // flags
- int l2exist;
-};
-
-void generate_charts_arcstats(const char *plugin, int update_every);
-void generate_charts_arc_summary(const char *plugin, int update_every);
-
-#endif //NETDATA_ZFS_COMMON_H