diff -Nru pcp-5.3.1/build/ci/platforms/ubuntu1804i386.yml pcp-5.3.2/build/ci/platforms/ubuntu1804i386.yml --- pcp-5.3.1/build/ci/platforms/ubuntu1804i386.yml 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/build/ci/platforms/ubuntu1804i386.yml 2021-07-30 04:05:06.000000000 +0000 @@ -47,7 +47,7 @@ if [ "$runner" = "container" ]; then DEFAULT_PCP_QA_ARGS="${DEFAULT_PCP_QA_ARGS} -x not_in_container" fi - sudo -i -u pcpqa ./check -TT ${PCP_QA_ARGS:-${DEFAULT_PCP_QA_ARGS}} |& tee ./artifacts/test/test.log + sudo -i -u pcpqa ./check -CI -TT ${PCP_QA_ARGS:-${DEFAULT_PCP_QA_ARGS}} |& tee ./artifacts/test/test.log copy_test_artifacts: | cp /var/lib/pcp/testsuite/check.timings ./artifacts/test [ $(awk 'END{print NF}' ./artifacts/test/check.timings) = 2 ] && date '+%s' >> ./artifacts/test/check.timings diff -Nru pcp-5.3.1/build/container/Dockerfile pcp-5.3.2/build/container/Dockerfile --- pcp-5.3.1/build/container/Dockerfile 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/build/container/Dockerfile 2021-06-15 01:03:49.000000000 +0000 @@ -1,5 +1,5 @@ # rpm build container -FROM registry.fedoraproject.org/fedora:33 +FROM registry.fedoraproject.org/fedora:34 COPY . /usr/src/pcp WORKDIR /usr/src/pcp @@ -30,7 +30,7 @@ /build # actual container -FROM registry.fedoraproject.org/fedora:33 +FROM registry.fedoraproject.org/fedora:34 COPY --from=0 /build/ /build/ ENV SUMMARY="Performance Co-Pilot" \ diff -Nru pcp-5.3.1/build/rpm/pcp.spec.in pcp-5.3.2/build/rpm/pcp.spec.in --- pcp-5.3.1/build/rpm/pcp.spec.in 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/build/rpm/pcp.spec.in 2021-07-30 04:05:06.000000000 +0000 @@ -369,9 +369,7 @@ %if "@pmda_postfix@" == "true" Requires: pcp-pmda-postfix %endif -%if "@have_python@" == "true" Requires: pcp-system-tools -%endif %if "@enable_qt@" == "true" Requires: pcp-gui %endif @@ -763,7 +761,6 @@ Metric Domain Agent (PMDA) collector tools written in Python3. %endif -%if "@have_python@" == "true" # # pcp-system-tools # @@ -771,23 +768,24 @@ License: GPLv2+ Summary: Performance Co-Pilot (PCP) System and Monitoring Tools URL: https://pcp.io +Requires: pcp = @package_version@ pcp-libs = @package_version@ +%if "@have_python@" == "true" %if "@enable_python3@" == "true" Requires: python3-pcp = @package_version@ %else Requires: %{__python2}-pcp = @package_version@ %endif -Requires: pcp = @package_version@ pcp-libs = @package_version@ %if "@enable_dstat@" == "true" # https://fedoraproject.org/wiki/Packaging:Guidelines "Renaming/Replacing Existing Packages" Provides: dstat = @package_version@ Provides: /usr/bin/dstat Obsoletes: dstat <= 0.8 %endif +%endif %description system-tools This PCP module contains additional system monitoring tools written in the Python language. -%endif %if "@enable_qt@" == "true" # @@ -862,6 +860,20 @@ %endif # +# pcp-pmda-denki +# +%package pmda-denki +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics dealing with electrical power +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +%description pmda-denki +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics related to the electrical power consumed by and inside +the system. +# end pcp-pmda-denki + +# # pcp-pmda-docker # %package pmda-docker @@ -2218,11 +2230,11 @@ basic_manifest | keep "$PCP_GUI|pcp-gui|applications|pixmaps|hicolor" | cull 'pmtime.h' >pcp-gui-files basic_manifest | keep 'selinux' | cull 'tmp|GNUselinuxdefs' >pcp-selinux-files basic_manifest | keep 'zeroconf|daily[-_]report|/sa$' >pcp-zeroconf-files -basic_manifest | grep -E -e 'pmiostat|pmrep|dstat|pcp2csv' \ +basic_manifest | grep -E -e 'pmiostat|pmrep|dstat|htop|pcp2csv' \ -e 'pcp-atop|pcp-dmcache|pcp-dstat|pcp-free|pcp-htop' \ -e 'pcp-ipcs|pcp-iostat|pcp-lvmcache|pcp-mpstat' \ -e 'pcp-numastat|pcp-pidstat|pcp-shping|pcp-tapestat' \ - -e 'pcp-uptime|pcp-verify' | \ + -e 'pcp-uptime|pcp-verify|pcp-ss' | \ cull 'selinux|pmlogconf|pmieconf|pmrepconf' >pcp-system-tools-files basic_manifest | keep 'sar2pcp' >pcp-import-sar2pcp-files basic_manifest | keep 'iostat2pcp' >pcp-import-iostat2pcp-files @@ -2249,6 +2261,7 @@ basic_manifest | keep '(etc/pcp|pmdas)/cifs(/|$)' >pcp-pmda-cifs-files basic_manifest | keep '(etc/pcp|pmdas)/cisco(/|$)' >pcp-pmda-cisco-files basic_manifest | keep '(etc/pcp|pmdas)/dbping(/|$)' >pcp-pmda-dbping-files +basic_manifest | keep '(etc/pcp|pmdas)/denki(/|$)' >pcp-pmda-denki-files basic_manifest | keep '(etc/pcp|pmdas|pmieconf)/dm(/|$)' >pcp-pmda-dm-files basic_manifest | keep '(etc/pcp|pmdas)/docker(/|$)' >pcp-pmda-docker-files basic_manifest | keep '(etc/pcp|pmdas)/ds389log(/|$)' >pcp-pmda-ds389log-files @@ -2316,7 +2329,7 @@ activemq apache \ bash bcc bind2 bonding bpftrace \ cifs cisco \ - dbping docker dm ds389 ds389log \ + dbping denki docker dm ds389 ds389log \ elasticsearch \ gfs2 gluster gpfs gpsd \ hacluster haproxy \ @@ -2775,6 +2788,9 @@ %preun pmda-weblog %{pmda_remove "$1" "weblog"} +%preun pmda-denki +%{pmda_remove "$1" "denki"} + %if "@enable_systemd@" == "true" %preun zeroconf if [ "$1" -eq 0 ] @@ -2927,6 +2943,8 @@ %files pmda-dbping -f pcp-pmda-dbping-files.rpm +%files pmda-denki -f pcp-pmda-denki-files.rpm + %files pmda-ds389log -f pcp-pmda-ds389log-files.rpm %files pmda-ds389 -f pcp-pmda-ds389-files.rpm @@ -3133,8 +3151,6 @@ %files -n python3-pcp -f python3-pcp.list.rpm %endif -%if "@have_python@" == "true" %files system-tools -f pcp-system-tools-files.rpm -%endif %files zeroconf -f pcp-zeroconf-files.rpm diff -Nru pcp-5.3.1/build/rpm/redhat.spec pcp-5.3.2/build/rpm/redhat.spec --- pcp-5.3.1/build/rpm/redhat.spec 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/build/rpm/redhat.spec 2021-07-30 04:05:06.000000000 +0000 @@ -1,5 +1,5 @@ Name: pcp -Version: 5.3.1 +Version: 5.3.2 Release: 1%{?dist} Summary: System-level performance monitoring and performance management License: GPLv2+ and LGPLv2+ and CC-BY @@ -501,7 +501,7 @@ Requires: pcp-pmda-dm pcp-pmda-apache Requires: pcp-pmda-bash pcp-pmda-cisco pcp-pmda-gfs2 pcp-pmda-mailq pcp-pmda-mounts Requires: pcp-pmda-nvidia-gpu pcp-pmda-roomtemp pcp-pmda-sendmail pcp-pmda-shping pcp-pmda-smart -Requires: pcp-pmda-hacluster pcp-pmda-lustrecomm pcp-pmda-logger pcp-pmda-docker pcp-pmda-bind2 +Requires: pcp-pmda-hacluster pcp-pmda-lustrecomm pcp-pmda-logger pcp-pmda-denki pcp-pmda-docker pcp-pmda-bind2 Requires: pcp-pmda-sockets %if !%{disable_podman} Requires: pcp-pmda-podman @@ -534,9 +534,7 @@ Requires: pcp-pmda-json %endif Requires: pcp-pmda-summary pcp-pmda-trace pcp-pmda-weblog -%if !%{disable_python2} || !%{disable_python3} Requires: pcp-system-tools -%endif %if !%{disable_qt} Requires: pcp-gui %endif @@ -1105,6 +1103,20 @@ #end pcp-pmda-gpsd # +# pcp-pmda-denki +# +%package pmda-denki +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics dealing with electrical power +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +%description pmda-denki +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics related to the electrical power consumed by and inside +the system. +# end pcp-pmda-denki + +# # pcp-pmda-docker # %package pmda-docker @@ -2118,7 +2130,6 @@ Metric Domain Agent (PMDA) collector tools written in Python3. %endif -%if !%{disable_python2} || !%{disable_python3} # # pcp-system-tools # @@ -2126,23 +2137,24 @@ License: GPLv2+ Summary: Performance Co-Pilot (PCP) System and Monitoring Tools URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +%if !%{disable_python2} || !%{disable_python3} %if !%{disable_python3} Requires: python3-pcp = %{version}-%{release} %else Requires: %{__python2}-pcp = %{version}-%{release} %endif -Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} %if !%{disable_dstat} # https://fedoraproject.org/wiki/Packaging:Guidelines "Renaming/Replacing Existing Packages" Provides: dstat = %{version}-%{release} Provides: /usr/bin/dstat Obsoletes: dstat <= 0.8 %endif +%endif %description system-tools This PCP module contains additional system monitoring tools written in the Python language. -%endif %if !%{disable_qt} # @@ -2254,9 +2266,11 @@ %if %{disable_mssql} # remove pmdamssql on platforms lacking MSODBC driver packages. +rm -fr $RPM_BUILD_ROOT/%{_confdir}/mssql +rm -fr $RPM_BUILD_ROOT/%{_confdir}/pmieconf/mssql +rm -fr $RPM_BUILD_ROOT/%{_ieconfdir}/mssql rm -fr $RPM_BUILD_ROOT/%{_pmdasdir}/mssql rm -fr $RPM_BUILD_ROOT/%{_pmdasexecdir}/mssql -rm -fr $RPM_BUILD_ROOT/%{_confdir}/mssql %endif %if !%{disable_qt} @@ -2357,11 +2371,11 @@ basic_manifest | keep "$PCP_GUI|pcp-gui|applications|pixmaps|hicolor" | cull 'pmtime.h' >pcp-gui-files basic_manifest | keep 'selinux' | cull 'tmp|GNUselinuxdefs' >pcp-selinux-files basic_manifest | keep 'zeroconf|daily[-_]report|/sa$' >pcp-zeroconf-files -basic_manifest | grep -E -e 'pmiostat|pmrep|dstat|pcp2csv' \ +basic_manifest | grep -E -e 'pmiostat|pmrep|dstat|htop|pcp2csv' \ -e 'pcp-atop|pcp-dmcache|pcp-dstat|pcp-free|pcp-htop' \ -e 'pcp-ipcs|pcp-iostat|pcp-lvmcache|pcp-mpstat' \ -e 'pcp-numastat|pcp-pidstat|pcp-shping|pcp-tapestat' \ - -e 'pcp-uptime|pcp-verify' | \ + -e 'pcp-uptime|pcp-verify|pcp-ss' | \ cull 'selinux|pmlogconf|pmieconf|pmrepconf' >pcp-system-tools-files basic_manifest | keep 'sar2pcp' >pcp-import-sar2pcp-files @@ -2390,6 +2404,7 @@ basic_manifest | keep '(etc/pcp|pmdas)/cisco(/|$)' >pcp-pmda-cisco-files basic_manifest | keep '(etc/pcp|pmdas)/dbping(/|$)' >pcp-pmda-dbping-files basic_manifest | keep '(etc/pcp|pmdas|pmieconf)/dm(/|$)' >pcp-pmda-dm-files +basic_manifest | keep '(etc/pcp|pmdas)/denki(/|$)' >pcp-pmda-denki-files basic_manifest | keep '(etc/pcp|pmdas)/docker(/|$)' >pcp-pmda-docker-files basic_manifest | keep '(etc/pcp|pmdas)/ds389log(/|$)' >pcp-pmda-ds389log-files basic_manifest | keep '(etc/pcp|pmdas)/ds389(/|$)' >pcp-pmda-ds389-files @@ -2457,7 +2472,7 @@ activemq apache \ bash bcc bind2 bonding bpftrace \ cifs cisco \ - dbping docker dm ds389 ds389log \ + dbping denki docker dm ds389 ds389log \ elasticsearch \ gfs2 gluster gpfs gpsd \ hacluster haproxy \ @@ -2699,6 +2714,9 @@ %preun pmda-dbping %{pmda_remove "$1" "dbping"} +%preun pmda-denki +%{pmda_remove "$1" "denki"} + %preun pmda-docker %{pmda_remove "$1" "docker"} @@ -3090,6 +3108,8 @@ %files pmda-zimbra -f pcp-pmda-zimbra-files.rpm %endif +%files pmda-denki -f pcp-pmda-denki-files.rpm + %files pmda-docker -f pcp-pmda-docker-files.rpm %files pmda-lustrecomm -f pcp-pmda-lustrecomm-files.rpm @@ -3261,13 +3281,14 @@ %files -n python3-pcp -f python3-pcp.list.rpm %endif -%if !%{disable_python2} || !%{disable_python3} %files system-tools -f pcp-system-tools-files.rpm -%endif %files zeroconf -f pcp-zeroconf-files.rpm %changelog +* Fri Jul 30 2021 Mark Goodwin - 5.3.2-1 +- https://github.com/performancecopilot/pcp/projects/1 + * Fri Jun 04 2021 Nathan Scott - 5.3.1-1 - Fix selinux violations for pmdakvm on debugfs (BZ 1929259) - Update to latest PCP sources. diff -Nru pcp-5.3.1/CHANGELOG pcp-5.3.2/CHANGELOG --- pcp-5.3.1/CHANGELOG 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/CHANGELOG 2021-07-30 04:05:06.000000000 +0000 @@ -1,3 +1,91 @@ +pcp-5.3.2 (30 July 2021) + - Client tools and utilities: + python: minimum supported python2 version is now 2.7 + pcp-ss: new socket statistics client tool + pcp-htop: add new "dynamic meters" feature + pcp-htop: use code vendoring and git subtree of htop.dev + pcp-htop: fix per-process user and system time conversions + pcp-htop: use the correct metric for shared memory calculations + pcp-htop: fix the color of PROC_COMM for PCP + pminfo: plug small memory leak on error paths for Coverity scan + pmdumplog: add -I option to report on-disk instance domains + pcp-{iostat,tapestat}.1: add --version description + pmrep/pmconfig.py: fix archive writing with scaled metrics + newhelp: reporting for empty or missing help text + pmlogger: add empty string help text + zsh completion: pmevent is an alias for pmval, fix command sorting + bash,zshc completions: update for pmdumplog -I + bash completions: add -P option for pmclient + - PMDA additions, enhancements and bug fixes: + pmdadenki: add new PMDA 'denki' for power metrics + pmdalinux: fix sign extension in buddyinfo total calculation + pmdalinux: use buddyinfo's order in calculating total size + pmdaproc: add proc.psinfo.cwd and proc.psinfo.exe metrics + pmdasockets: default to daemon and migrate from DSO to daemon + pmdasockets: add persistent filter, new metrics, parser fixes + pmdasockets: add missing help text for reord_seen and delivered + pmdasockets: fix #! for Install and Remove + pmdasockets: fix resource leak coverity CID371684 + pmdasockets: fix regex in Upgrade script + pmdahacluster: Remove un-needed pmdaCacheLookupName() calls + pmdahacluster: add support for labels on key metrics + pmdammv: add check for item uniqueness + pmdapmcd: add pmcd.zoneinfo metric + pmdabcc: drop defunct usdt_jvm_alloc module + pmdads389: add two additional cn attributes + pmdads389: automated discovery of replication agreements + - Server-side utilities and log management scripts: + dbpmda: add -flag to debug command + pmproxy: honour the secure.enabled config option + pmlogger: block SIGALRM before re-exec + pmlogger: tighten up "lost pmcd connection" logic + pmlogger: don't try to catch SIGSTOP + pmlogger_daily.sh: extra -VV diagnostics + pmcd: avoid mem leak on error path, Coverity issues + pmcd: small tweak to getzoneinfo_plan_b() + pmproxy: add mutex for client req lists, fix https/tls support + - libpcp, libpcp_pmda, libpcp_mmv, libpcp_web and language bindings + python api: guard against fetchgroup destructor race condition + libpcp_web: add generic timer API + libpcp_web: add generic server metrics + libpcp_web: improve discovery lock handling and scalability + libpcp_web: add mutex to struct webgroup protecting the context dict + libpcp_web: add new metric for metadata discovery partial reads + libpcp_web: fix many resource leaks, null checks from Coverity scan + libpcp_web: plug mem leak in redisMapInsert during daily log-rolling + libpcp_web: disable Redis connection if version check fails + libpcp_import: fix per-instance error handling in pmiWrite + libpcp: don't clobber help text buffer, fix "fallback" logic + libpcp: complete remaining libpcp.h internal struct renaming + libpcp: replace sighold() and sigrelse() with sigprocmask() + - Misc build, infrastructure and packaging updates: + build: optionally enable sanitizers in configure + build: conditionally enable gperftools (default is no) + build: mark python3-bpfcc dependency as architecture specific + build: bump Fedora version of the PCP container + build: do not install /var/tmp as part of PCP itself + build: add configure and makefile macros for libbpf, libelf + libpcp/pmapi.h/pmdbg: add -Ddev0,dev1,dev2 + - Security Enhanced Linux: + selinux QA: rework QA for other SELinux implementations + selinux QA: fix semodule -l output format, has changed in Fedora 34 + selinux QA: small fixup for semodule -l filter + selinux: small changes for CentOS Linux7.9.2009 + - Documentation and QA infrastructure: + docs: add "SELinux Considerations" section to pmdaopenmetrics(1) + docs: add man page for pmWebTimerRegister(3) and related functions + docs: document pmdasockets(1) filter config file + docs: add missing long-options in many man(1) pages + docs: move Grafana troubleshooting out of scaling doc + docs: document hostspec parameter for openmetrics endpoint + docs: update scaling doc with federated setup and troubleshooting + docs: pmdastatsd, update man page and Install instructions + docs: pmseries(1) man page fix ":" operator description + docs: drop the unused --profile output from pcp-dstat(1) + qa/common.avahi: be more careful with stderr from avahi-browse + qa/common.check: revise _service "stop" logic for pmlogger + qa/common.check: improve recovery of failed systemctl services + pcp-5.3.1 (4 June 2021) - Client tools and utilities: pcp-atop: fix threading options process-sort-order bug diff -Nru pcp-5.3.1/configure pcp-5.3.2/configure --- pcp-5.3.1/configure 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/configure 2021-07-30 04:05:06.000000000 +0000 @@ -778,6 +778,12 @@ HAVE_NCURSES ncurses_LIBS ncurses_CFLAGS +HAVE_LIBELF +libelf_LIBS +libelf_CFLAGS +HAVE_LIBBPF +libbpf_LIBS +libbpf_CFLAGS HAVE_LIBUV libuv_LIBS libuv_CFLAGS @@ -893,6 +899,9 @@ lib_for_avahi avahi_LIBS avahi_CFLAGS +sanitizer +gperftools_LIBS +gperftools_CFLAGS enable_probes CPP DTRACE @@ -1008,6 +1017,8 @@ enable_option_checking with_64bit with_optimization +with_gperftools +with_sanitizer with_threads with_secure_sockets with_static_probes @@ -1068,6 +1079,8 @@ YACC YFLAGS CPP +gperftools_CFLAGS +gperftools_LIBS avahi_CFLAGS avahi_LIBS SYSTEMD_TMPFILESDIR @@ -1076,6 +1089,10 @@ openssl_LIBS libuv_CFLAGS libuv_LIBS +libbpf_CFLAGS +libbpf_LIBS +libelf_CFLAGS +libelf_LIBS ncurses_CFLAGS ncurses_LIBS ncursesw_CFLAGS @@ -1727,6 +1744,10 @@ --with-64bit turn on 64 bit compilation mode (default is platform dependent) --with-optimization enable optimization for C/C++ code (default is yes) + --with-gperftools enable gperftools for CPU and heap profiling + (default is no) + --with-sanitizer enable sanitizers (default is no, common values are + 'address', 'thread' or 'leak') --with-threads enable support for multiple threads (default is on) --with-secure-sockets enable support for secure sockets (default is on) --with-static-probes enable support for static probes (default is on) @@ -1802,6 +1823,10 @@ This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. CPP C preprocessor + gperftools_CFLAGS + C compiler flags for gperftools, overriding pkg-config + gperftools_LIBS + linker flags for gperftools, overriding pkg-config avahi_CFLAGS C compiler flags for avahi, overriding pkg-config avahi_LIBS linker flags for avahi, overriding pkg-config @@ -1816,6 +1841,12 @@ libuv_CFLAGS C compiler flags for libuv, overriding pkg-config libuv_LIBS linker flags for libuv, overriding pkg-config + libbpf_CFLAGS + C compiler flags for libbpf, overriding pkg-config + libbpf_LIBS linker flags for libbpf, overriding pkg-config + libelf_CFLAGS + C compiler flags for libelf, overriding pkg-config + libelf_LIBS linker flags for libelf, overriding pkg-config ncurses_CFLAGS C compiler flags for ncurses, overriding pkg-config ncurses_LIBS @@ -2728,6 +2759,24 @@ +# Check whether --with-gperftools was given. +if test "${with_gperftools+set}" = set; then : + withval=$with_gperftools; use_gperftools=$withval; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --with-gperftools=$withval" +else + use_gperftools=no +fi + + + +# Check whether --with-sanitizer was given. +if test "${with_sanitizer+set}" = set; then : + withval=$with_sanitizer; use_sanitizer=$withval; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --with-sanitizer=$withval" +else + use_sanitizer=no +fi + + + # Check whether --with-threads was given. if test "${with_threads+set}" = set; then : withval=$with_threads; do_threads=$withval; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --with-threads=$withval" @@ -5671,6 +5720,108 @@ fi +if test "x$use_gperftools" != "xno"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gperftools" >&5 +$as_echo_n "checking for gperftools... " >&6; } + +if test -n "$gperftools_CFLAGS"; then + pkg_cv_gperftools_CFLAGS="$gperftools_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libprofiler, libtcmalloc\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libprofiler, libtcmalloc") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_gperftools_CFLAGS=`$PKG_CONFIG --cflags "libprofiler, libtcmalloc" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$gperftools_LIBS"; then + pkg_cv_gperftools_LIBS="$gperftools_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libprofiler, libtcmalloc\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libprofiler, libtcmalloc") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_gperftools_LIBS=`$PKG_CONFIG --libs "libprofiler, libtcmalloc" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + gperftools_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libprofiler, libtcmalloc" 2>&1` + else + gperftools_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libprofiler, libtcmalloc" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$gperftools_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (libprofiler, libtcmalloc) were not met: + +$gperftools_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables gperftools_CFLAGS +and gperftools_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables gperftools_CFLAGS +and gperftools_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + gperftools_CFLAGS=$pkg_cv_gperftools_CFLAGS + gperftools_LIBS=$pkg_cv_gperftools_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +fi + +sanitizer="" +if test "x$use_sanitizer" != "xno"; then + sanitizer="-fsanitize=$use_sanitizer" +fi + + if test "x$do_discovery" != "xno"; then : # on Mac OS X, dns_sd.h @@ -7470,12 +7621,12 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PY_MAJOR.$PY_MINOR.$PY_POINT" >&5 $as_echo "$PY_MAJOR.$PY_MINOR.$PY_POINT" >&6; } if test "$PY_MAJOR" -lt 2; then - echo WARNING: Python version 2.6 or later does not seem to be installed. + echo WARNING: Python version 2.7 or later does not seem to be installed. enable_python2=false else - if test "$PY_MAJOR" -eq 2 -a "$PY_MINOR" -lt 6 ; then + if test "$PY_MAJOR" -eq 2 -a "$PY_MINOR" -lt 7 ; then echo WARNING: Python version 2.$PY_MINOR is too old. - echo Python version 2.6 or later is required for Python builds. + echo Python version 2.7 or later is required for Python builds. enable_python2=false else PY_MAJOR="$PY_MAJOR" @@ -10762,6 +10913,154 @@ +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libbpf" >&5 +$as_echo_n "checking for libbpf... " >&6; } + +if test -n "$libbpf_CFLAGS"; then + pkg_cv_libbpf_CFLAGS="$libbpf_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libbpf\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libbpf") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libbpf_CFLAGS=`$PKG_CONFIG --cflags "libbpf" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$libbpf_LIBS"; then + pkg_cv_libbpf_LIBS="$libbpf_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libbpf\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libbpf") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libbpf_LIBS=`$PKG_CONFIG --libs "libbpf" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + libbpf_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libbpf" 2>&1` + else + libbpf_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libbpf" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$libbpf_PKG_ERRORS" >&5 + + have_libbpf=false +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_libbpf=false +else + libbpf_CFLAGS=$pkg_cv_libbpf_CFLAGS + libbpf_LIBS=$pkg_cv_libbpf_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_libbpf=true +fi +HAVE_LIBBPF=$have_libbpf + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libelf" >&5 +$as_echo_n "checking for libelf... " >&6; } + +if test -n "$libelf_CFLAGS"; then + pkg_cv_libelf_CFLAGS="$libelf_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libelf\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libelf") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libelf_CFLAGS=`$PKG_CONFIG --cflags "libelf" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$libelf_LIBS"; then + pkg_cv_libelf_LIBS="$libelf_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libelf\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libelf") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_libelf_LIBS=`$PKG_CONFIG --libs "libelf" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + libelf_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libelf" 2>&1` + else + libelf_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libelf" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$libelf_PKG_ERRORS" >&5 + + have_libelf=false +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_libelf=false +else + libelf_CFLAGS=$pkg_cv_libelf_CFLAGS + libelf_LIBS=$pkg_cv_libelf_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_libelf=true +fi +HAVE_LIBELF=$have_libelf + + + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ncurses" >&5 $as_echo_n "checking for ncurses... " >&6; } diff -Nru pcp-5.3.1/configure.ac pcp-5.3.2/configure.ac --- pcp-5.3.1/configure.ac 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/configure.ac 2021-07-30 04:05:06.000000000 +0000 @@ -31,6 +31,18 @@ [use_optimization=$withval; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --with-optimization=$withval"], [use_optimizaton=yes]) +AC_ARG_WITH([gperftools], + [AS_HELP_STRING([--with-gperftools], + [enable gperftools for CPU and heap profiling (default is no)])], + [use_gperftools=$withval; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --with-gperftools=$withval"], + [use_gperftools=no]) + +AC_ARG_WITH([sanitizer], + [AS_HELP_STRING([--with-sanitizer], + [enable sanitizers (default is no, common values are 'address', 'thread' or 'leak')])], + [use_sanitizer=$withval; PACKAGE_CONFIGURE="$PACKAGE_CONFIGURE --with-sanitizer=$withval"], + [use_sanitizer=no]) + AC_ARG_WITH([threads], [AC_HELP_STRING([--with-threads], [enable support for multiple threads (default is on)])], @@ -719,6 +731,18 @@ AC_SUBST(DTRACE) fi +dnl Check for gperftools +AS_IF([test "x$use_gperftools" != "xno"], [ + PKG_CHECK_MODULES([gperftools], [libprofiler, libtcmalloc]) +]) + +dnl Check for sanitizers +sanitizer="" +if test "x$use_sanitizer" != "xno"; then + sanitizer="-fsanitize=$use_sanitizer" +fi +AC_SUBST(sanitizer) + dnl Check for service discovery mechanisms (DNS-SD, Avahi) AS_IF([test "x$do_discovery" != "xno"], [ # on Mac OS X, dns_sd.h @@ -858,7 +882,7 @@ CFLAGS="$saved_CFLAGS" ]) -dnl check if python tools/packages wanted (need python >= 2.6) +dnl check if python tools/packages wanted (need python >= 2.7) enable_python2=false AS_IF([test "x$do_python" != "xno"], [ enable_python2=true @@ -902,12 +926,12 @@ eval `$PYTHON -V 2>&1 | awk '/^Python/ { ver=2; print $ver }' | awk -F. '{ major=1; minor=2; point=3; printf "export PY_MAJOR=%d PY_MINOR=%d PY_POINT=%d\n",$major,$minor,$point }'` AC_MSG_RESULT([$PY_MAJOR.$PY_MINOR.$PY_POINT]) if test "$PY_MAJOR" -lt 2; then - echo WARNING: Python version 2.6 or later does not seem to be installed. + echo WARNING: Python version 2.7 or later does not seem to be installed. enable_python2=false else - if test "$PY_MAJOR" -eq 2 -a "$PY_MINOR" -lt 6 ; then + if test "$PY_MAJOR" -eq 2 -a "$PY_MINOR" -lt 7 ; then echo WARNING: Python version 2.$PY_MINOR is too old. - echo Python version 2.6 or later is required for Python builds. + echo Python version 2.7 or later is required for Python builds. enable_python2=false else PCP_CHECK_PYTHON_HEADER([$PY_MAJOR], [$PY_MINOR]) @@ -1793,6 +1817,12 @@ have_uv_pipe_chmod=true, have_uv_pipe_chmod=false) +PKG_CHECK_MODULES([libbpf], [libbpf], [have_libbpf=true], [have_libbpf=false]) +AC_SUBST(HAVE_LIBBPF, [$have_libbpf]) + +PKG_CHECK_MODULES([libelf], [libelf], [have_libelf=true], [have_libelf=false]) +AC_SUBST(HAVE_LIBELF, [$have_libelf]) + PKG_CHECK_MODULES([ncurses], [ncurses], [have_ncurses=true], [have_ncurses=false]) AC_SUBST(HAVE_NCURSES, [$have_ncurses]) diff -Nru pcp-5.3.1/CONTRIBUTING.md pcp-5.3.2/CONTRIBUTING.md --- pcp-5.3.1/CONTRIBUTING.md 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/CONTRIBUTING.md 2021-06-15 01:03:49.000000000 +0000 @@ -109,8 +109,8 @@ # Vendoring -To keep track of the vendored libraries origin and code changes, it is advised -to use git subtrees when vendoring libraries. The advantage of using git +To keep track of the vendored code origin and changes, it is strongly advised +to use git subtrees when vendoring 3rd party code. The advantage of using git subtrees instead of git submodules is that with git subtree the vendored code is stored inside the PCP repository, instead of merely linking to a specific commit of the remote repository. @@ -134,8 +134,8 @@ ``` **Note:** All modifications of vendored code should be pushed upstream. The -goal is to be a good open source citizen and contribute changes back, and to keep -the differences minimal in order to ease future updates of vendored libraries. +goal is to be a good open source citizen and contribute changes back, and to +keep the differences minimal in order to ease future updates of vendored code. **All bugs and CVEs of a vendored library in turn become responsibilities of the PCP maintainers as well** (and fixes must be pushed upstream). diff -Nru pcp-5.3.1/debian/changelog pcp-5.3.2/debian/changelog --- pcp-5.3.1/debian/changelog 2021-06-26 07:13:35.000000000 +0000 +++ pcp-5.3.2/debian/changelog 2021-06-15 01:03:49.000000000 +0000 @@ -1,20 +1,8 @@ -pcp (5.3.1-1ubuntu2) impish; urgency=medium +pcp (5.3.2-1) unstable; urgency=low - * Build for riscv64 again - * Restrict Build-Depends and Suggests on python3-bpfcc to - architectures where libbpfcc is available - * Drop alternative Build-Depends and Suggests on python3-bcc which - is not in the archive + * New release (full details in CHANGELOG). - -- Graham Inggs Sat, 26 Jun 2021 07:13:35 +0000 - -pcp (5.3.1-1ubuntu1) impish; urgency=medium - - * d/control: Drop arch riscv64. A B-D for "python3-bpfcc | python3-bcc" - was added in 5.3.x, but the bpfcc package does not provide binaries - for riscv64, thus causing FTBFS. - - -- Bryce Harrington Wed, 23 Jun 2021 21:24:12 +0000 + -- Nathan Scott Fri, 30 Jul 2021 11:37:57 +1100 pcp (5.3.1-1) unstable; urgency=low diff -Nru pcp-5.3.1/debian/control pcp-5.3.2/debian/control --- pcp-5.3.1/debian/control 2021-06-26 07:13:35.000000000 +0000 +++ pcp-5.3.2/debian/control 2021-07-30 00:37:57.000000000 +0000 @@ -2,10 +2,9 @@ Section: utils Priority: extra Homepage: https://pcp.io -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: PCP Development Team +Maintainer: PCP Development Team Uploaders: Nathan Scott , Ken McDonell -Build-Depends: bison, flex, gawk, procps, pkg-config, debhelper (>= 5), perl (>= 5.6), libreadline-dev | libreadline5-dev | libreadline-gplv2-dev, chrpath, libbsd-dev [kfreebsd-any], libkvm-dev [kfreebsd-any], python3-dev, libnspr4-dev, libnss3-dev, libsasl2-dev, libuv1-dev, libssl-dev, libavahi-common-dev, qtbase5-dev, qtbase5-dev-tools, libqt5svg5-dev, qtchooser, autotools-dev, zlib1g-dev, autoconf, libclass-dbi-perl, libdbd-mysql-perl, python3-psycopg2, python3-openpyxl, dh-python, libpfm4-dev, libncurses5-dev, python3-six, python3-json-pointer, python3-requests, libextutils-autoinstall-perl, libxml-tokeparser-perl, librrds-perl, libjson-perl, libwww-perl, libnet-snmp-perl, libnss3-tools, liblzma-dev, systemd, libsystemd-dev, python3-bpfcc [amd64 arm64 armhf ppc64 ppc64el s390x], bpftrace (>= 0.9.2) [amd64 arm64 ppc64el], libibumad-dev, libibmad-dev, manpages +Build-Depends: bison, flex, gawk, procps, pkg-config, debhelper (>= 5), perl (>= 5.6), libreadline-dev | libreadline5-dev | libreadline-gplv2-dev, chrpath, libbsd-dev [kfreebsd-any], libkvm-dev [kfreebsd-any], python3-dev, libnspr4-dev, libnss3-dev, libsasl2-dev, libuv1-dev, libssl-dev, libavahi-common-dev, qtbase5-dev, qtbase5-dev-tools, libqt5svg5-dev, qtchooser, autotools-dev, zlib1g-dev, autoconf, libclass-dbi-perl, libdbd-mysql-perl, python3-psycopg2, python3-openpyxl, dh-python, libpfm4-dev, libncurses5-dev, python3-six, python3-json-pointer, python3-requests, libextutils-autoinstall-perl, libxml-tokeparser-perl, librrds-perl, libjson-perl, libwww-perl, libnet-snmp-perl, libnss3-tools, liblzma-dev, systemd, libsystemd-dev, python3-bpfcc [amd64 arm64 armhf ppc64el s390x ppc64], bpftrace (>= 0.9.2) [amd64 arm64 ppc64el], libibumad-dev, libibmad-dev, manpages Standards-Version: 3.9.3 X-Python3-Version: >= 3.3 @@ -13,7 +12,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, gawk, procps, python3-pcp, python3, libpcp-pmda3 (= ${binary:Version}), libpcp-mmv1 (= ${binary:Version}), libpcp-web1 (= ${binary:Version}), libpcp3 (= ${binary:Version}) Recommends: libpcp-pmda-perl Conflicts: pgpool2, dstat, pcp-webapi, pcp-manager -Suggests: pcp-gui, libpcp-import-perl, bpftrace (>= 0.9.2) [amd64 arm64 ppc64el], python3-bpfcc [amd64 arm64 armhf ppc64 ppc64el s390x], redis-server +Suggests: pcp-gui, libpcp-import-perl, bpftrace (>= 0.9.2) [amd64 arm64 ppc64el], python3-bpfcc [amd64 arm64 armhf ppc64el s390x ppc64], redis-server Provides: dstat, pcp-webapi, pcp-manager Replaces: dstat, pcp-webapi, pcp-manager Architecture: any diff -Nru pcp-5.3.1/debian/fixcontrol pcp-5.3.2/debian/fixcontrol --- pcp-5.3.1/debian/fixcontrol 2021-06-26 07:13:35.000000000 +0000 +++ pcp-5.3.2/debian/fixcontrol 2021-07-30 00:37:57.000000000 +0000 @@ -81,7 +81,7 @@ if $PMDA_BCC then - echo "s/?{python3-bpfcc}, /python3-bpfcc [amd64 arm64 armhf ppc64 ppc64el s390x], /" >>$tmp.sed + echo "s/?{python3-bpfcc}, /python3-bpfcc [amd64 arm64 armhf ppc64el s390x ppc64], /" >>$tmp.sed else echo "s/?{python3-bpfcc}, //" >>$tmp.sed fi diff -Nru pcp-5.3.1/debian/libpcp3-dev.install pcp-5.3.2/debian/libpcp3-dev.install --- pcp-5.3.1/debian/libpcp3-dev.install 2021-06-03 23:21:45.000000000 +0000 +++ pcp-5.3.2/debian/libpcp3-dev.install 2021-07-30 00:37:57.000000000 +0000 @@ -279,6 +279,9 @@ usr/share/man/man3/pmUseContext.3.gz usr/share/man/man3/pmUseZone.3.gz usr/share/man/man3/PMWEBAPI.3.gz +usr/share/man/man3/pmWebTimerRegister.3.gz +usr/share/man/man3/pmWebTimerRelease.3.gz +usr/share/man/man3/pmWebTimerSetMetricRegistry.3.gz usr/share/man/man3/pmWhichContext.3.gz usr/share/man/man3/pmWhichZone.3.gz usr/share/man/man3/QMC.3.gz diff -Nru pcp-5.3.1/docs/HowTos/scaling/index.rst pcp-5.3.2/docs/HowTos/scaling/index.rst --- pcp-5.3.1/docs/HowTos/scaling/index.rst 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/docs/HowTos/scaling/index.rst 2021-07-30 04:05:06.000000000 +0000 @@ -133,31 +133,75 @@ Results and Analysis ******************** -The following results were gathered on a `pmlogger Farm`_ deployment, with a default **pcp-zeroconf 5.3.0** installation, where each remote host is an identical container instance running `pmcd(1)`_ on a server with 64 CPU cores, 376 GB RAM and 1 disk attached (as mentioned above, 64 CPUs increases per-CPU metric volume). -The logging interval is 10s, ``proc`` metrics of remote nodes are *not* included, and the memory values refer to the RSS (Resident Set Size) value. +Centralized logging (pmlogger farm) +----------------------------------- + +The following results were gathered on a :ref:`pmlogger farm` deployment, +with a default **pcp-zeroconf 5.3.2** installation (version 5.3.1-3 on RHEL), where each remote host is an identical container instance +running `pmcd(1)`_ on a server with 64 CPU cores, 376 GB RAM and 1 disk attached (as mentioned above, 64 CPUs increases per-CPU metric volume). +The Redis server is co-located on the same host as pmlogger and pmproxy, and ``proc`` metrics of remote nodes are *not* included. +The memory values refer to the RSS (Resident Set Size) value. + +**10s logging interval:** + ++-----------+----------------+----------+------------------+---------+--------------+---------+-----------+-----------------+-------------+ +| Number of | PCP Archives | pmlogger | pmlogger Network | pmproxy | Redis Memory | pmproxy | Disk IOPS | Disk Throughput | Disk | +| | | | | | | | | | | +| Hosts | Storage p. Day | Memory | per Day (In) | Memory | per Day | CPU% | (write) | (write) | Utilization | ++===========+================+==========+==================+=========+==============+=========+===========+=================+=============+ +| 10 | 91 MB | 160 MB | 2 MB | 1.4 GB | 2.6 GB | 1% | 25 | 19 MB/s | 4% | ++-----------+----------------+----------+------------------+---------+--------------+---------+-----------+-----------------+-------------+ +| 50 | 522 MB | 580 MB | 9 MB | 6.3 GB | 12 GB | 5% | 70 | 52 MB/s | 10% | ++-----------+----------------+----------+------------------+---------+--------------+---------+-----------+-----------------+-------------+ + +**60s logging interval:** +-----------+----------------+----------+------------------+---------+--------------+ | Number of | PCP Archives | pmlogger | pmlogger Network | pmproxy | Redis Memory | | | | | | | | | Hosts | Storage p. Day | Memory | per Day (In) | Memory | per Day | +===========+================+==========+==================+=========+==============+ -| 10 | 91 MB | 160 MB | 2 MB | 1.4 GB | 2.6 GB | +| 10 | 20 MB | 104 MB | 0.38 MB | 2.67 GB | 0.54 GB | +-----------+----------------+----------+------------------+---------+--------------+ -| 50 | 522 MB | 580 MB | 9 MB | 6.3 GB | 12 GB | +| 50 | 120 MB | 524 MB | 1.75 MB | 5.5 GB | 2.65 GB | ++-----------+----------------+----------+------------------+---------+--------------+ +| 100 | 271 MB | 1049 MB | 3.48 MB | 9 GB | 5.3 GB | +-----------+----------------+----------+------------------+---------+--------------+ -Detailed Utilization Statistics -------------------------------- - -+-----------+---------+-----------+-----------------+-------------+ -| Number of | pmproxy | Disk IOPS | Disk Throughput | Disk | -| | | | | | -| Hosts | CPU% | (write) | (write) | Utilization | -+===========+=========+===========+=================+=============+ -| 10 | 1% | 25 | 19 MB/s | 4% | -+-----------+---------+-----------+-----------------+-------------+ -| 50 | 5% | 70 | 52 MB/s | 10% | -+-----------+---------+-----------+-----------------+-------------+ +**Note:** pmproxy queues Redis requests and employs Redis pipelining to speed up Redis queries. +This can result in bursts of high memory usage. +There are plans to optimize memory usage in future versions of PCP (`#1341 `_). +For further troubleshooting, please see the `High memory usage`_ section in the troubleshooting chapter. + +Federated setup (multiple pmlogger farms) +----------------------------------------- + +The following results were observed with a :ref:`federated setup` +consisting of three :ref:`pmlogger farms`, where each pmlogger farm +was monitoring 100 remote hosts, i.e. 300 hosts in total. +The setup of the pmlogger farms was identical to the configuration above (60s logging interval), except that the Redis servers were operating in cluster mode. + ++----------------+----------+-------------------+---------+--------------+ +| PCP Archives | pmlogger | Network | pmproxy | Redis Memory | +| | | | | | +| Storage p. Day | Memory | per Day (In/Out) | Memory | per Day | ++================+==========+===================+=========+==============+ +| 277 MB | 1058 MB | 15.6 MB / 12.3 MB | 6-8 GB | 5.5 GB | ++----------------+----------+-------------------+---------+--------------+ + +**Note:** All values are per host. + +The network bandwidth is higher due to the inter-node communication of the Redis cluster. + +Troubleshooting +*************** + +High memory usage +----------------- + +To troubleshoot high memory usage, please run ``pmrep :pmproxy`` and observe the *inflight* column. +This column shows how many Redis requests are in-flight, i.e. they are queued (or sent) and no reply was received so far. +A high number indicates that a) the pmproxy process is busy processing new PCP archives and doesn't have spare CPU cycles to process Redis requests and responses or b) the Redis node (or cluster) is overloaded and cannot process incoming requests on time. .. note:: diff -Nru pcp-5.3.1/GNUmakefile pcp-5.3.2/GNUmakefile --- pcp-5.3.1/GNUmakefile 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/GNUmakefile 2021-06-15 01:03:49.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012-2020 Red Hat. +# Copyright (c) 2012-2021 Red Hat. # Copyright (c) 2000,2003 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it @@ -76,9 +76,6 @@ $(INSTALL) -m 755 -d $(PCP_MAN_DIR)/man3 $(INSTALL) -m 755 -d $(PCP_MAN_DIR)/man5 endif -ifneq ($(TARGET_OS),mingw) - $(INSTALL) -m 1777 -d $(PCP_TMPFILE_DIR) -endif $(INSTALL) -m 775 -o $(PCP_USER) -g $(PCP_GROUP) -d $(PCP_TMP_DIR) ifeq (, $(filter debian suse, $(PACKAGE_DISTRIBUTION))) # PCP_RUN_DIR usually -> /var/run which may be a temporary filesystem diff -Nru pcp-5.3.1/man/man1/dbpmda.1 pcp-5.3.2/man/man1/dbpmda.1 --- pcp-5.3.1/man/man1/dbpmda.1 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/man/man1/dbpmda.1 2021-07-30 04:05:06.000000000 +0000 @@ -545,8 +545,10 @@ The .B debug command takes one or more debug options separated by whitespace or a comma. -This can be used to selectively enable or disable debugging output from various +This can be used to selectively enable debugging output from various modules of the PCP libraries that the PMDA will be linked with. +If the option is prefixed by a minus ``-'' the corresponding debugging option is +disabled. The options are the same debug names as reported by the .B \-l option to diff -Nru pcp-5.3.1/man/man1/pmcd_wait.1 pcp-5.3.2/man/man1/pmcd_wait.1 --- pcp-5.3.1/man/man1/pmcd_wait.1 2019-10-11 02:20:52.000000000 +0000 +++ pcp-5.3.2/man/man1/pmcd_wait.1 2021-07-30 04:05:06.000000000 +0000 @@ -18,7 +18,7 @@ \f3pmcd_wait\f1 \- wait for PMCD to accept client connections .SH SYNOPSIS \f3$PCP_BINADM_DIR/pmcd_wait\f1 -[\f3\-v\f1] +[\f3\-v?\f1] [\f3-h\f1 \f2host\f1] [\f3-t\f1 \f2timeout\f1] .SH DESCRIPTION @@ -73,6 +73,9 @@ (which is the default), no output will be generated. With verbose mode on, error messages will be output on .IR stderr . +.TP +\fB\-?\fR, \fB\-\-help\fR +Display usage message and exit. .SH DIAGNOSTICS Error messages will be output to .I stderr diff -Nru pcp-5.3.1/man/man1/pmchart.1 pcp-5.3.2/man/man1/pmchart.1 --- pcp-5.3.1/man/man1/pmchart.1 2020-05-28 23:27:15.000000000 +0000 +++ pcp-5.3.2/man/man1/pmchart.1 2021-07-30 04:05:06.000000000 +0000 @@ -22,11 +22,13 @@ [\f3\-CLVWz?\f1] [\f3\-a\f1 \f2archive\f1] [\f3\-A\f1 \f2align\f1] +[\fB\-\-archive\-folio\fP \fIfolio\fP] [\f3\-c\f1 \f2configfile\f1] [\f3\-f\f1 \f2fontfamily\f1] [\f3\-F\f1 \f2fontsize\f1] [\f3\-g\f1 \f2geometry\f1] [\f3\-h\f1 \f2host\f1] +[\f3\-n\f1 \f2pmnsfile\f1] [\f3\-o\f1 \f2outfile\f1] [\f3\-O\f1 \f2offset\f1] [\f3\-p\f1 \f2port\f1] @@ -105,6 +107,10 @@ for a complete description of the syntax for .IR align . .TP +\fB\-\-archive\-folio\fR=\fIfolio\fR +Read metric source archives from the PCP archive +.IR folio . +.TP \fB\-c\fR \fIconfigfile\fR, \fB\-\-view\fR=\fIconfigfile\fR .I configfile specifies an initial view to load, using the default source of metrics. @@ -204,6 +210,12 @@ See also .BR \-K . .TP +\fB\-n\fR \fIpmnsfile\fR, \fB\-\-namespace\fR=\fIpmnsfile\fR +Load an alternative Performance Metrics Name Space +.RB ( PMNS (5)) +from the file +.IR pmnsfile . +.TP \fB\-o\fR \fIoutfile\fR, \fB\-\-output\fR=\fIoutfile\fR Generate an image file named .IR outfile , @@ -229,7 +241,7 @@ for a complete description of the syntax for .IR origin . .TP -\fB\-p\fR \fIport\fR, \fB\-\-port\fR=\fIport\fR +\fB\-p\fR \fIport\fR, \fB\-\-guiport\fR=\fIport\fR .I port number for connection to an existing .B pmtime @@ -295,19 +307,6 @@ or .B \-a options. -.PP -The -.BR \-S , -.BR \-T , -.B \-O -and -.B \-A -options may be used to define a time window to -restrict the samples retrieved, set an initial origin within the time -window, or specify a "natural" alignment of the sample times; refer -to -.BR PCPIntro (1) -for a complete description of these options. .TP \fB\-Z\fR \fItimezone\fR, \fB\-\-timezone\fR=\fItimezone\fR By default, @@ -322,6 +321,9 @@ .I timezone in the format of the environment variable TZ as described in .BR environ (7). +.TP +\fB\-?\fR, \fB\-\-help\fR +Display usage message and exit. .SH VIEWS The primary .B pmchart @@ -730,16 +732,14 @@ .B pmchart application. .SH SEE ALSO -.BR pmtime (1), -.BR pmconfirm (1), -.BR pmdumptext (1), .BR PCPIntro (1), .BR pmafm (1), +.BR pmconfirm (1), +.BR pmdumptext (1), +.BR pminfo (1), .BR pmrep (1), +.BR pmtime (1), .BR pmval (1), -.BR pmcd (1), -.BR pminfo (1), -.BR pcp.conf (5), -.BR pcp.env (5) +.BR pcp.conf (5) and .BR PMNS (5). diff -Nru pcp-5.3.1/man/man1/pmdumplog.1 pcp-5.3.2/man/man1/pmdumplog.1 --- pcp-5.3.1/man/man1/pmdumplog.1 2019-11-28 22:40:45.000000000 +0000 +++ pcp-5.3.2/man/man1/pmdumplog.1 2021-07-30 04:05:06.000000000 +0000 @@ -18,7 +18,7 @@ \f3pmdumplog\f1 \- dump internal details of a performance metrics archive log .SH SYNOPSIS \f3pmdumplog\f1 -[\f3\-adehilLmMrstxzV?\f1] +[\f3\-adehIilLmMrstxzV?\f1] [\f3\-n\f1 \f2pmnsfile\f1] [\f3\-S\f1 \f2starttime\f1] [\f3\-T\f1 \f2endtime\f1] @@ -99,6 +99,16 @@ .BR pmGetInDom (3) for more details on instance domains. .TP +\fB\-I\fR, \fB\-\-on-disk-insts\fR +Display the on-disk instance domains, which may use a different format +and encoding than the one visible above the +Performance Metrics Programming Interface (PMAPI) +when using +.BR pmGetInDom (3) +and related routines. +The on-disk format is only of interest when investigating the internal +structure of PCP archives. +.TP \fB\-l\fR, \fB\-\-label\fR Dump the archive label, showing the log format version, the time and date for the start and (current) end of the archive, and @@ -161,6 +171,12 @@ time-series of metric values. .RE .TP +\fB\-n\fR \fIpmnsfile\fR, \fB\-\-namespace\fR=\fIpmnsfile\fR +Load an alternative Performance Metrics Name Space +.RB ( PMNS (5)) +from the file +.IR pmnsfile . +.TP \fB\-r\fR, \fB\-\-reverse\fR Process the archive in reverse order, from most recent to oldest recorded metric values. diff -Nru pcp-5.3.1/man/man1/pmdumptext.1 pcp-5.3.2/man/man1/pmdumptext.1 --- pcp-5.3.1/man/man1/pmdumptext.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/man/man1/pmdumptext.1 2021-07-30 04:05:06.000000000 +0000 @@ -174,16 +174,27 @@ etc. .SH OPTIONS The command line options -.BR \-A , -.BR \-O , +.hy 0 +.B \-A +(or +.BR \-\-align ), +.B \-O +(or +.BR \-\-origin ), .B \-S +(or +.BR \-\-start ) and .B \-T +(or +.BR \-\-finish ) control the alignment, offset, start and end time when visualizing metrics from archives. These options are common to most Performance Co-Pilot tools and are fully described in .BR PCPIntro (1). +.br +.hy .PP The other available options are: .TP 5 diff -Nru pcp-5.3.1/man/man1/pmlogextract.1 pcp-5.3.2/man/man1/pmlogextract.1 --- pcp-5.3.1/man/man1/pmlogextract.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/man/man1/pmlogextract.1 2021-07-30 04:05:06.000000000 +0000 @@ -258,7 +258,7 @@ Use the local timezone of the host from the input archive logs. The default is to initially use the timezone of the local host. .TP -\fB\-?\fR +\fB\-?\fR, \fB\-\-help\fR Display usage message and exit. .SH CONFIGURATION FILE SYNTAX The diff -Nru pcp-5.3.1/man/man1/pmlogger.1 pcp-5.3.2/man/man1/pmlogger.1 --- pcp-5.3.1/man/man1/pmlogger.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/man/man1/pmlogger.1 2021-07-30 04:05:06.000000000 +0000 @@ -821,7 +821,7 @@ .IR host , rather than from the default localhost. .TP -\fB\-H\fR \fIhostname\fR, \fB\-\-hostname\fR=\fIhostname\fR +\fB\-H\fR \fIhostname\fR, \fB\-\-labelhost\fR=\fIhostname\fR Specify the .I hostname to use instead of the one returned by diff -Nru pcp-5.3.1/man/man1/pmlogger_rewrite.1 pcp-5.3.2/man/man1/pmlogger_rewrite.1 --- pcp-5.3.1/man/man1/pmlogger_rewrite.1 2020-05-28 23:27:15.000000000 +0000 +++ pcp-5.3.2/man/man1/pmlogger_rewrite.1 2021-07-30 04:05:06.000000000 +0000 @@ -54,15 +54,28 @@ .SH OPTIONS The following options are passed through to .BR pmlogrewrite : -.BR \-c , -.BR \-d , -.BR \-s , -.BR \-v +.hy 0 +.B \-c +(or +.BR \-\-config ), +.B \-d +(or +.BR \-\-desperate ), +.B \-s +(or +.BR \-\-scale ), +.B \-v +(or +.B \-\-verbose) and -.BR \-w . +.B \-w +(or +.BR \-\-warnings ). Refer to .BR pmlogrewrite (1) for the meaning of these options. +.br +.hy .PP The remaining options are: .TP 5 diff -Nru pcp-5.3.1/man/man1/pmloglabel.1 pcp-5.3.2/man/man1/pmloglabel.1 --- pcp-5.3.1/man/man1/pmloglabel.1 2020-02-27 06:57:32.000000000 +0000 +++ pcp-5.3.2/man/man1/pmloglabel.1 2021-07-30 04:05:06.000000000 +0000 @@ -18,7 +18,7 @@ \f3pmloglabel\f1 \- check and repair a performance metrics archive label .SH SYNOPSIS \f3pmloglabel\f1 -[\f3\-lLsv\f1] +[\f3\-lLsv?\f1] [\f3\-h\f1 \f2hostname\f1] [\f3\-p\f1 \f2pid\f1] [\f3\-V\f1 \f2version\f1] @@ -97,6 +97,9 @@ .B TZ as described in .BR environ (7). +.TP +\fB\-?\fR, \fB\-\-help\fR +Display usage message and exit. .SH EXAMPLES The following demonstrates the use of .B pmloglabel diff -Nru pcp-5.3.1/man/man1/pmlogrewrite.1 pcp-5.3.2/man/man1/pmlogrewrite.1 --- pcp-5.3.1/man/man1/pmlogrewrite.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/man/man1/pmlogrewrite.1 2021-07-30 04:05:06.000000000 +0000 @@ -216,7 +216,7 @@ .B \-w flag forces warnings to be emitted for all of these cases. .TP -\fB\-?\fR +\fB\-?\fR, \fB\-\-help\fR Display usage message and exit. .PP The argument diff -Nru pcp-5.3.1/man/man1/pmproxy.1 pcp-5.3.2/man/man1/pmproxy.1 --- pcp-5.3.1/man/man1/pmproxy.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/man/man1/pmproxy.1 2021-07-30 04:05:06.000000000 +0000 @@ -19,8 +19,9 @@ \f3pmproxy\f1 \- proxy for performance metrics collector and querying .SH SYNOPSIS \f3pmproxy\f1 -[\f3\-AFft?\f1] -[\f3\-C\f1 \f2dirname\f1] +[\f3\-AdfFt?\f1] +[\f3\-c\f1 \f2conffile\f1] +[\f3\-C\f1 \f2certdb\f1] [\f3\-h\f1 \f2host\f1[,\f2host\f1 ...] [\f3\-i\f1 \f2ipaddress\f1] [\f3\-l\f1 \f2logfile\f1] @@ -29,8 +30,9 @@ [\f3\-p\f1 \f2port\f1[,\f2port\f1 ...] [\f3\-P\f1 \f2passfile\f1] [\f3\-r\f1 \f2port\f1[,\f2port\f1 ...] +[\f3\-s\f1 \f2sockname\f1] [\f3\-U\f1 \f2username\f1] -[\f3\-x\f1 \f2file\f1] +[\f3\-x\f1 \f2outfile\f1] .SH DESCRIPTION .B pmproxy acts as a protocol proxy, @@ -106,13 +108,13 @@ (such as Avahi/DNS-SD), assisting remote monitoring tools with finding it. These mechanisms are disabled with this option. .TP -\f3\-c\f1 \f2file\f1, \f3\-\-config\f1=\f2file\f1 +\f3\-c\f1 \f2conffile\f1, \f3\-\-config\f1=\f2conffile\f1 Specify the path to an optional configuration -.IR file , +.IR conffile , with format as described in the ``CONFIGURATION'' section. This option implies \f3pmproxy\f1 is running in \f3timeseries\f1 mode. .TP -\f3\-C\f1 \f2dirname\f1, \f3\-\-certpath\f1=\f2dirname\f1 +\f3\-C\f1 \f2certdb\f1, \f3\-\-certdb\f1=\f2certdb\f1 Specify the path to the Network Security Services certificate database, for (optional) secure connections. This option implies \f3pmproxy\f1 is running in \f3deprecated\f1 mode. @@ -120,7 +122,7 @@ .BR /etc/pki/nssdb . Refer also to the \f3\-P\f1 option. If it does not already exist, this database can be created using the -.B certutil +.BR certutil (1) utility. This process and other certificate database maintenance information is provided in the @@ -186,7 +188,7 @@ file settings. This option implies \f3pmproxy\f1 is running in \f3timeseries\f1 mode. .TP -\f3\-i\f1 \f2ipaddress\f1 +\f3\-i\f1 \f2ipaddress\f1, \f3\-\-interface\f1=\f2ipaddress\f1 This option is usually only used on hosts with more than one network interface (very common for firewall and ``head'' node hosts where .B pmproxy @@ -209,17 +211,17 @@ .B \-i options is specified, attempted connections made on any other IP addresses will be refused. .TP -\f3\-l\f1 \f2file\f1, \f3\-\-log\f1=\f2file\f1 +\f3\-l\f1 \f2logfile\f1, \f3\-\-log\f1=\f2logfile\f1 By default a log file named .I pmproxy.log is written in the current directory. The .B \-l option causes the log file to be written to a given -.I file +.I logfile instead of the default. If this -.I file +.I logfile cannot be created or is not writable, output is written to the standard error instead. .TP @@ -236,7 +238,7 @@ .I PDU size. .TP -\f3\-M\f1 \f2name\f1, \f3\-\-certname\f1=\f2name\f1 +\f3\-M\f1 \f2certname\f1, \f3\-\-certname\f1=\f2certname\f1 By default .B pmproxy will try to use a certificate called @@ -245,7 +247,7 @@ The .B \-M option allows this certificate -.I name +.I certname to be changed. This option implies \f3pmproxy\f1 is running in \f3deprecated\f1 mode. .TP @@ -255,9 +257,9 @@ number to listen on for client connections. The default value is 44322. .TP -\f3\-P\f1 \f2file\f1, \f3\-\-passfile\f1=\f2file\f1 +\f3\-P\f1 \f2passfile\f1, \f3\-\-passfile\f1=\f2passfile\f1 Specify the path to a -.I file +.I passfile containing the Network Security Services certificate database password for (optional) secure connections, and for databases that are password protected. @@ -294,12 +296,12 @@ automatically, for fast, scalable time series querying described in .BR pmseries (1). .TP -\f3\-U\f1 \f2user\f1, \f3\-\-username\f1=\f2user\f1 +\f3\-U\f1 \f2username\f1, \f3\-\-username\f1=\f2username\f1 Assume the identity of the given -.I user +.I username before starting to accept incoming packets from PCP monitoring clients. .TP -\f3\-x\f1 \f2file\f1 +\f3\-x\f1 \f2outfile\f1 Before the .B pmproxy .I logfile @@ -309,7 +311,7 @@ By default the output describing this error is sent to .B /dev/tty but it may redirected to -.IR file . +.IR outfile . .TP \fB\-?\fR, \fB\-\-help\fR Display usage message and exit. diff -Nru pcp-5.3.1/man/man1/pmseries.1 pcp-5.3.2/man/man1/pmseries.1 --- pcp-5.3.1/man/man1/pmseries.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/man/man1/pmseries.1 2021-07-30 04:05:06.000000000 +0000 @@ -194,8 +194,7 @@ Strings can be subject to pattern matching in the form of glob matching ("~~"), regular expression matching ("=~"), and regular expression non-matching ("!~"). -The ":" operator is equivalent to "~~" - i.e., regular expression -matching. +The ":" operator is equivalent to "~~" - i.e., glob matching. .SS Relational operators (numeric label values only) Numeric label values can be subject to the less than ("<"), greater than (">"), less than or equal ("<="), greater than diff -Nru pcp-5.3.1/man/man1/pmtime.1 pcp-5.3.2/man/man1/pmtime.1 --- pcp-5.3.1/man/man1/pmtime.1 2019-11-28 22:40:45.000000000 +0000 +++ pcp-5.3.2/man/man1/pmtime.1 2021-07-30 04:05:06.000000000 +0000 @@ -17,7 +17,7 @@ \f3pmtime\f1 \- time control server for Performance Co-Pilot .SH SYNOPSIS \f3pmtime\f1 -[\f3\-?\f1] +[\f3\-V?\f1] [\f3\-p\f1 \f2port\f1] .SH DESCRIPTION .B pmtime @@ -44,26 +44,29 @@ .B pmtime window contains the simpler time controls suitable for live monitoring. +.PP +Note that the +.B pmtime +window is only made visible when explicitly requested. +Multiple client applications can be connected to a single +.B pmtime +server \- when the final client application exits, +.B pmtime +will also exit. .SH OPTIONS The available command line options are: .TP 5 -\fB\-p\fR \fIport\fR, \fB\-\-port\fR=\fIport\fR +\fB\-p\fR \fIport\fR, \fB\-\-guiport\fR=\fIport\fR .I port is the port number which .B pmtime will use for communication with its clients (monitoring applications). .TP +\fB\-V\fR, \fB\-\-version\fR +Display version number and exit. +.TP \fB\-?\fR, \fB\-\-help\fR Display usage message and exit. -.PP -Note that the -.B pmtime -window is only made visible when explicitly requested. -Multiple client applications can be connected to a single -.B pmtime -server \- when the final client application exits, -.B pmtime -will also exit. .SH ENVIRONMENT When a port number is not explicitly requested on the command line via the @@ -75,7 +78,7 @@ .B pmtime is searching for a port number to use. .PP -The default starting port number is 43334. +The default starting port number is \fB43334\fP. .SH SEE ALSO .BR PCPIntro (1), .BR pmchart (1), diff -Nru pcp-5.3.1/man/man3/pmwebapi.3 pcp-5.3.2/man/man3/pmwebapi.3 --- pcp-5.3.1/man/man3/pmwebapi.3 2020-12-17 22:46:06.000000000 +0000 +++ pcp-5.3.2/man/man3/pmwebapi.3 2021-07-30 04:05:06.000000000 +0000 @@ -83,6 +83,11 @@ and popularized by the .I https://prometheus.io project) is available. +.PP +All requests are performed on the web server host by default, +unless a +.I hostspec +parameter is provided. .SS GET /metrics .TS box; @@ -92,6 +97,8 @@ _ names string Comma-separated list of metric names times boolean Append sample times (milliseconds since epoch) +_ +hostspec string Host specification as described in \f(CBPCPIntro\fR(1) .TE .P Fetches current values and metadata for all metrics, or only diff -Nru pcp-5.3.1/man/man3/pmwebtimerregister.3 pcp-5.3.2/man/man3/pmwebtimerregister.3 --- pcp-5.3.1/man/man3/pmwebtimerregister.3 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/man/man3/pmwebtimerregister.3 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,103 @@ +'\"macro stdmacro +.\" +.\" Copyright (c) 2021 Red Hat. +.\" +.\" This program is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License as published by the +.\" Free Software Foundation; either version 2 of the License, or (at your +.\" option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +.\" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +.\" for more details. +.\" +.\" +.TH PMWEBTIMERREGISTER 3 "PCP" "Performance Co-Pilot" +.SH NAME +\f3pmWebTimerRegister\f1, +\f3pmWebTimerRelease\f1, +\f3pmWebTimerSetMetricRegistry\f1 \- thread-safe timer list management +.SH "C SYNOPSIS" +.ft 3 +#include +.sp +.ad l +.hy 0 +.in +8n +.ti -8n +typedef void (*pmWebTimerCallBack)(void *\fIdata\fP); +.ti -8n +int pmWebTimerRegister(pmWebTimerCallBack \fIcallback\fP, void *\fIdata\fP); +.sp +.ti -8n +int pmWebTimerRelease(int \fIseq\fP); +.br +.ti -8n +int pmWebTimerSetMetricRegistry(struct mmv_registry *\fIregistry\fP); +.in +.hy +.ad +cc ... \-lpcp_web +.ft 1 +.SH DESCRIPTION +The +.B pmWebTimerRegister +and related API functions provide a convenient thread-safe API for +applications to manage a list of timer driven callbacks. +On the first call to +.B pmWebTimerRegister +or +.BR pmWebTimerSetMetricRegistry , +an internal timer is set up and initialized to fire every 1.0 seconds. +Each time the timer fires, all currently registered \fIcallback\fP functions +will be called serially with the opaque \fIdata\fP pointer that was supplied +when each function was registered. +The \fIpmWebTimerCallBack\fP typedef provides a suitable callback function prototype. +.PP +All registered \fIcallback\fP functions should be non-blocking +and execute quickly and synchronously. +Typical \fIcallback\fP functions include refreshing instrumentation, +calculating and updating performance metric values, periodic garbage +collection and any other local function that requires regular execution. +.PP +The +.B pmWebTimerSetMetricRegistry +function provides a convenient way for an application to pass in a pointer to an +.BR libpcp_mmv (3) +\fIregistry\fP that has been suitably initialized by the calling application. +This \fIregistry\fP will be used to dynamically create six server resource metrics named +\fINAME\fP\fB.mem.datasz\fP, \fINAME\fP\fB.mem.maxrss\fP, \fINAME\fP\fB.cpu.total\fP, +\fINAME\fP\fB.cpu.sys\fP, \fINAME\fP\fB.cpu.user\fP and \fINAME\fP\fB.pid\fP, +where +.I NAME +is the root PCP +.BR PMNS(5) +name set up by the calling application. +These metrics should be reasonably self explanatory; they provide resource usage metrics +from the calling application / server and use +.BR getrusage (2), +.BR times (2) +and +.BR getpid(2). +.SH RETURN VALUE +The +.B pmWebTimerRegister +function returns a positive integer handle that may be subsequently used +in a call to +.B pmWebTimerRelease +to remove a timer from the internal timer list. +When a timer is removed with a call to +.BR pmWebTimerRelease , +the internal data structures are freed. +The caller however, is responsible for freeing the associated +.B data +(since it may or may not be dynamically allocated). +.SH DIAGNOSTICS +On failure a negative PMAPI error code is returned in all cases. +.SH SEE ALSO +.BR pmproxy (1), +.BR mmv_stats_registry (3), +.BR PMAPI (3) +and +.BR PMWEBAPI (3). diff -Nru pcp-5.3.1/qa/022 pcp-5.3.2/qa/022 --- pcp-5.3.1/qa/022 2017-06-30 04:20:44.000000000 +0000 +++ pcp-5.3.2/qa/022 2021-07-30 04:05:06.000000000 +0000 @@ -133,16 +133,31 @@ fi # -# fetch all instances for one metric in each cluster +# fetch all instances for one metric in each cluster, +# provided the metric is expected to have > 1 value # if new clusters are added, add more here # echo "" echo "All instances for selected metrics ..." -for metric in proc.nprocs proc.psinfo.sname proc.memory.textrss proc.runq.sleeping +cat <$tmp.err $metric \ | sed \ -e '/Error: proc_instance: unknown pid:/d' \ + -e '/Error: Metric not supported by this version of monitored application/d' \ -e '/^ *value /d' \ | $PCP_AWK_PROG ' / [i]nst \[/ { skip = 1 } diff -Nru pcp-5.3.1/qa/022.out.linux pcp-5.3.2/qa/022.out.linux --- pcp-5.3.1/qa/022.out.linux 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/022.out.linux 2021-07-30 04:05:06.000000000 +0000 @@ -65,11 +65,13 @@ proc.psinfo.cpusallowed proc.psinfo.cstime proc.psinfo.cutime +proc.psinfo.cwd proc.psinfo.delayacct_blkio_time proc.psinfo.eip proc.psinfo.end_code proc.psinfo.environ proc.psinfo.esp +proc.psinfo.exe proc.psinfo.exit_signal proc.psinfo.flags proc.psinfo.guest_time @@ -240,4 +242,14 @@ proc.memory.textrss +proc.psinfo.labels + proc.runq.sleeping + +proc.id.euid_nm + +proc.schedstat.cpu_time + +proc.io.read_bytes + +proc.smaps.anonymous diff -Nru pcp-5.3.1/qa/025 pcp-5.3.2/qa/025 --- pcp-5.3.1/qa/025 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/025 2021-07-30 04:05:06.000000000 +0000 @@ -40,17 +40,18 @@ *.timer) ;; *) - sudo systemctl disable $svc >>$seq.full 2>&1 + $sudo systemctl disable $svc >>$seq.full 2>&1 ;; esac - sudo systemctl stop $svc >>$seq.full 2>&1 + $sudo systemctl stop $svc >>$seq.full 2>&1 echo "+ after stop $svc ..." >>$seq.full _get_pids_by_name pmlogger >>$seq.full 2>&1 $PCP_PS_PROG $PCP_PS_ALL_FLAGS | grep '[p]mlogger' >>$seq.full done # and now get a clean pmlogger without the other hangers-on # - sudo systemctl restart pmlogger + $sudo systemctl restart pmlogger + _wait_for_pmlogger fi fi echo "Using system? \"$use_systemd\" (-s => yes)" >>$seq.full @@ -66,8 +67,8 @@ pmlogger_daily.service \ pmlogger_daily-poll.service do - sudo systemctl enable $svc >>$seq.full 2>&1 - sudo systemctl start $svc >>$seq.full 2>&1 + $sudo systemctl enable $svc >>$seq.full 2>&1 + $sudo systemctl start $svc >>$seq.full 2>&1 done fi # these come from src/pmcdgone running _wait_for_pmlogger w/out $tmp diff -Nru pcp-5.3.1/qa/031.out.darwin pcp-5.3.2/qa/031.out.darwin --- pcp-5.3.1/qa/031.out.darwin 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/031.out.darwin 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: PM_ID_NULL name: kernel.all.pswitch pmGetChildren: Unknown metric name diff -Nru pcp-5.3.1/qa/031.out.freebsd pcp-5.3.2/qa/031.out.freebsd --- pcp-5.3.1/qa/031.out.freebsd 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/031.out.freebsd 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 85.0.22 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/031.out.linux pcp-5.3.2/qa/031.out.linux --- pcp-5.3.1/qa/031.out.linux 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/031.out.linux 2021-06-15 01:03:49.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 60.0.13 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/031.out.netbsd pcp-5.3.2/qa/031.out.netbsd --- pcp-5.3.1/qa/031.out.netbsd 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/031.out.netbsd 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 116.5.1 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/031.out.openbsd pcp-5.3.2/qa/031.out.openbsd --- pcp-5.3.1/qa/031.out.openbsd 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/031.out.openbsd 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 139.5.1 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/031.out.solaris pcp-5.3.2/qa/031.out.solaris --- pcp-5.3.1/qa/031.out.solaris 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/031.out.solaris 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 75.0.23 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/036 pcp-5.3.2/qa/036 --- pcp-5.3.1/qa/036 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/036 2021-06-15 01:03:49.000000000 +0000 @@ -87,7 +87,13 @@ echo echo "=== error and failure cases ===" -src/exectest -Dexec -- /a/b/c -f oo bar 2>&1 | _filter +# need sort here because -Dexec output on stderr is for both parent and +# child (after fork()) and order is not deterministic +# +src/exectest -Dexec -- /a/b/c -f oo bar 2>&1 \ +| tee -a $seq.full \ +| _filter \ +| LC_COLLATE=POSIX sort # success, all done status=0 diff -Nru pcp-5.3.1/qa/036.out pcp-5.3.2/qa/036.out --- pcp-5.3.1/qa/036.out 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/036.out 2021-06-15 01:03:49.000000000 +0000 @@ -60,8 +60,8 @@ __pmProcessPipeClose() -> 0 === error and failure cases === +__pmProcessExec -> 127 exit=127 __pmProcessExec: argc=4 toss=0 "/a/b/c" "-f" "oo" "bar" __pmProcessExec: child pid=PID __pmProcessExec: child pid=PID execvp(/a/b/c, ...) failed __pmProcessExec: child pid=PID wait_pid=PID exit=127 -__pmProcessExec -> 127 exit=127 diff -Nru pcp-5.3.1/qa/083 pcp-5.3.2/qa/083 --- pcp-5.3.1/qa/083 2019-06-28 04:43:13.000000000 +0000 +++ pcp-5.3.2/qa/083 2021-07-30 04:05:06.000000000 +0000 @@ -38,11 +38,11 @@ _filter() { - # for Linux sometimes see "Connection reset by peer" ... this is believed - # to be a timing issue, and the results are semantically equivalent for - # the purposes of this test, so ... - # and the "receiving response from pmlogger" part of the no permission - # error message may not be there for older pmlc versions, so ... + # For Linux sometimes see "Connection reset by peer" or "Connection + # refused" ... this is believed to be a timing issue, and the + # results are semantically equivalent for the purposes of this test. + # And the "receiving response from pmlogger" part of the no permission + # error message may not be there for older pmlc versions. # tee -a $here/$seq.full \ | sed -e "s/$me/ME/" \ @@ -51,6 +51,7 @@ -e "s/$other1/OTHER1/" \ -e "s/$other2/OTHER2/" \ -e 's/Connection reset by peer/Address already in use/' \ + -e 's/Connection refused/Address already in use/' \ -e '/No permission to perform/s/ receiving response from pmlogger//' } diff -Nru pcp-5.3.1/qa/1041 pcp-5.3.2/qa/1041 --- pcp-5.3.1/qa/1041 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1041 2021-07-30 04:05:06.000000000 +0000 @@ -76,11 +76,8 @@ -e '/^Waiting for pmcd/s/\.\.\.[. ]*$/DOTS/' \ -e "\\;Error: pmdaCacheOp: \$PCP_VAR_DIR/config/pmda/.*: empty file?;d" \ | $PCP_AWK_PROG ' -/Check libvirt metrics have appeared/ { if ($7 >= 67 && $7 <= 250) $7 = "X" - if ($10 >= 8 && $10 <= 5000) $10 = "Y" - } -/ warnings, / { if ($9 >= 67 && $9 <= 250) $9 = "X" - if ($12 >= 14 && $12 <= 50) $12 = "Y" +/Check libvirt metrics have appeared/ { if ($7 >= 120) $7 = "X" + if ($10 >= 4) $10 = "Y" } { print }' } diff -Nru pcp-5.3.1/qa/1049 pcp-5.3.2/qa/1049 --- pcp-5.3.1/qa/1049 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/1049 2021-07-30 04:05:06.000000000 +0000 @@ -25,13 +25,22 @@ # Some metrics unavailable by default, so skip the associated rules # -cat >$tmp.cmd <$tmp.cmd +for group in shping cisco dmthin mssql +do + # most have group == dir, but some do not + # + case $group + in + dmthin) + dir=dm + ;; + *) + dir=$group + ;; + esac + [ -d $PCP_ETC_DIR/pcp/pmieconf/$dir ] && echo "modify $group enabled no" >>$tmp.cmd +done # real QA test starts here echo "running pmieconf with default rules..." diff -Nru pcp-5.3.1/qa/1057 pcp-5.3.2/qa/1057 --- pcp-5.3.1/qa/1057 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1057 2021-06-15 01:03:49.000000000 +0000 @@ -13,6 +13,9 @@ . ./common.filter . ./common.check +config=$PCP_VAR_DIR/config/pmlogrewrite/nfsclient_migrate.conf +[ -f "$config" ] || _notrun "no $config file" + status=1 # failure is the default! $sudo rm -rf $tmp $tmp.* $seq.full trap "cd $here; $sudo rm -rf $tmp $tmp.*; exit \$status" 0 1 2 3 15 @@ -33,7 +36,6 @@ } # real QA test starts here -config=$PCP_VAR_DIR/config/pmlogrewrite/nfsclient_migrate.conf sed -e '/^#/d' $config > $tmp.config for size in 32 64 diff -Nru pcp-5.3.1/qa/1072 pcp-5.3.2/qa/1072 --- pcp-5.3.1/qa/1072 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1072 2021-07-30 04:05:06.000000000 +0000 @@ -88,6 +88,12 @@ pmrep -u -a $tmp.new_archive4 -z hinv.machine mem.util.used pmdumplog -z -dim $tmp.new_archive4 +echo "=== pmrep archive creation with scaled values" +pmrep -u -s 5 -o archive -F $tmp.new_archive5 -z $log2 -i sda,sdc disk.dev.write_bytes,,,MB | _pid_filter +# Using -r to display the unit in the archive +pmrep -u -a $tmp.new_archive5 -z -r disk.dev.write_bytes +pmdumplog -z -dim $tmp.new_archive5 + rm -f $tmp.a1-out* $tmp.a2-out* $tmp.new_archive* # success, all done diff -Nru pcp-5.3.1/qa/1072.out pcp-5.3.2/qa/1072.out --- pcp-5.3.1/qa/1072.out 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1072.out 2021-07-30 04:05:06.000000000 +0000 @@ -93,4 +93,53 @@ 14:39:17.882326 1 metric 60.1.1 (mem.util.used): value 13573800 +=== pmrep archive creation with scaled values +Recording 1 metrics to TMP.new_archive5: +5 samples(s) with 1.0 sec interval ~ 4 sec duration. + d.d.write_bytes d.d.write_bytes + sda sdc + Kbyte Kbyte + 369846691 948239088 + 369847163 948239160 + 369847575 948239236 + 369848903 948239408 + 369849315 948239540 +Note: timezone set to local timezone of host "billing02" from archive + + +Descriptions for Metrics in the Log ... +PMID: 60.0.39 (disk.dev.write_bytes) + Data Type: 32-bit unsigned int InDom: 60.1 0xf000001 + Semantics: counter Units: Kbyte + +Instance Domains in the Log ... +InDom: 60.1 +00:28:01.923022 2 instances + 0 or "sda" + 2 or "sdc" + +00:28:01.923022 1 metric + 60.0.39 (disk.dev.write_bytes): + inst [0 or "sda"] value 369846691 + inst [2 or "sdc"] value 948239088 + +00:29:01.925641 1 metric + 60.0.39 (disk.dev.write_bytes): + inst [0 or "sda"] value 369847163 + inst [2 or "sdc"] value 948239160 + +00:30:01.923324 1 metric + 60.0.39 (disk.dev.write_bytes): + inst [0 or "sda"] value 369847575 + inst [2 or "sdc"] value 948239236 + +00:31:01.922091 1 metric + 60.0.39 (disk.dev.write_bytes): + inst [0 or "sda"] value 369848903 + inst [2 or "sdc"] value 948239408 + +00:32:01.922742 1 metric + 60.0.39 (disk.dev.write_bytes): + inst [0 or "sda"] value 369849315 + inst [2 or "sdc"] value 948239540 == done diff -Nru pcp-5.3.1/qa/1083 pcp-5.3.2/qa/1083 --- pcp-5.3.1/qa/1083 2020-04-24 00:15:07.000000000 +0000 +++ pcp-5.3.2/qa/1083 2021-07-30 04:05:06.000000000 +0000 @@ -20,7 +20,6 @@ { cd $here _service pmcd stop >>$here/$seq.full 2>&1 - $restore_pcpqa_systemd && export PCPQA_SYSTEMD=$save_pcpqa_systemd _restore_auto_restart pmcd _service pmcd restart 2>&1 | _filter_pcp_start _wait_for_pmcd @@ -37,14 +36,6 @@ $sudo rm -rf $tmp $tmp.* $seq.full trap "_cleanup; exit \$status" 0 1 2 3 15 -if [ "$PCPQA_SYSTEMD" = x -o "${PCPQA_SYSTEMD-x}" != x ] -then - # $PCPQA_SYSTEMD is already set ... - save_pcpqa_systemd="$PCPQA_SYSTEMD" - restore_pcpqa_systemd=true -fi -unset PCPQA_SYSTEMD - _stop_auto_restart pmcd _stop_auto_restart pmlogger diff -Nru pcp-5.3.1/qa/1118 pcp-5.3.2/qa/1118 --- pcp-5.3.1/qa/1118 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/1118 2021-07-30 04:05:06.000000000 +0000 @@ -12,16 +12,6 @@ _pmdabcc_check -# The bcc PMDA with runqlat module kills a F34 machine, hard ... -# DO NOT RUN THIS TEST ON Fedora 34 -# -case `admin/whatami` -in - *Fedora\ 34*) - _notrun "bcc PMDA runqlat module may lock up the machine on Fedora 34" - ;; -esac - status=1 # failure is the default! signal=$PCP_BINADM_DIR/pmsignal $sudo rm -rf $tmp.* $seq.full diff -Nru pcp-5.3.1/qa/1147 pcp-5.3.2/qa/1147 --- pcp-5.3.1/qa/1147 2020-04-24 00:15:07.000000000 +0000 +++ pcp-5.3.2/qa/1147 2021-07-30 04:05:06.000000000 +0000 @@ -21,8 +21,6 @@ _notrun no systemctl executable fi -unset PCPQA_SYSTEMD - _cleanup() { cd $here @@ -38,11 +36,18 @@ # make sure systemctl thinks pmlogger is running # -_service pmlogger restart >>$here/$seq.full 2>&1 +_service -v pmlogger restart >>$here/$seq.full 2>&1 _wait_for_pmlogger pid=`_get_primary_logger_pid` echo "+++ at the start primary pmlogger pid = $pid" >>$here/$seq.full +if [ -z "$pid" ] +then + echo "Arrgh ... no primary pmlogger?" + echo "Likely looking processes ..." + $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '([p]m)|([P]ID)' + exit +fi _stop_auto_restart pmlogger _service pmlogger stop | _filter_pcp_stop _wait_pmlogger_end $pid diff -Nru pcp-5.3.1/qa/1155 pcp-5.3.2/qa/1155 --- pcp-5.3.1/qa/1155 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1155 2021-07-30 04:05:06.000000000 +0000 @@ -21,46 +21,40 @@ ;; esac -if [ -f /etc/lsb-release ] -then - . /etc/lsb-release - if [ "$DISTRIB_ID" = Ubuntu ] - then - # This test fails for Ubuntu 19.10 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$DISTRIB_RELEASE" - in - 19.10) - _notrun "bcc does not work for this test on Ubuntu $DISTRIB_RELEASE" - ;; - esac - fi -fi - -if [ -f /etc/os-release ] -then - . /etc/os-release - if [ "$NAME" = "openSUSE Leap" ] - then - # This test fails for openSUSE 15.1 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$VERSION" - in - 15.1) - _notrun "bcc does not work for this test on openSUSE $VERSION" - ;; - esac - fi -fi - target_ip=1.1.1.1 status=1 # failure is the default! signal=$PCP_BINADM_DIR/pmsignal $sudo rm -rf $tmp.* $seq.full +# Some combinations of distro and kernel are known to be "bad" +# for some BPF modules +# +kernel=`uname -r` +echo "$kernel" >>$seq.full +case `admin/whatami` +in + *Fedora\ 32\ *) + _notrun "bcc tcplife module will not compile on Fedora 32" + ;; + *Ubuntu\ 19.10\ *) + _notrun "bcc tcplife module will not compile on Ubuntu 19.10" + ;; + *Ubuntu\ 20.04\ *) + # works on 5.4 kernel, not on 5.8.0-1033-azure + # + case "$kernel" + in + 5.8.0-*-azure) + _notrun "bcc tcplife module will not compile on Ubuntu kernel $kernel" + ;; + esac + ;; + *openSUSE\ Leap\ 15.1\ *) + _notrun "bcc tcplife module will not compile on openSUSE 15.1" + ;; +esac + _install_filter() { sed \ diff -Nru pcp-5.3.1/qa/1157 pcp-5.3.2/qa/1157 --- pcp-5.3.1/qa/1157 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1157 2021-07-30 04:05:06.000000000 +0000 @@ -19,23 +19,6 @@ ;; esac -if [ -f /etc/lsb-release ] -then - . /etc/lsb-release - if [ "$DISTRIB_ID" = Ubuntu ] - then - # This test fails for Ubuntu 19.10 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$DISTRIB_RELEASE" - in - 19.10) - _notrun "bcc does not work for this test on Ubuntu $DISTRIB_RELEASE" - ;; - esac - fi -fi - # sch_netem is part of optional kernel-modules-extra on Fedora $sudo modprobe sch_netem lsmod | grep sch_netem >/dev/null 2>&1 \ @@ -49,6 +32,28 @@ signal=$PCP_BINADM_DIR/pmsignal $sudo rm -rf $tmp.* $seq.full +# Some combinations of distro and kernel are known to be "bad" +# for some BPF modules +# +kernel=`uname -r` +echo "$kernel" >>$seq.full +case `admin/whatami` +in + *Ubuntu\ 19.10\ *) + _notrun "bcc tcpretrans module will not compile on Ubuntu 19.10" + ;; + *Ubuntu\ 20.04\ *) + # works on 5.4 kernel, not on 5.8.0-1033-azure + # + case "$kernel" + in + 5.8.0-*-azure) + _notrun "bcc tcpretrans module will not compile on Ubuntu kernel $kernel" + ;; + esac + ;; +esac + _simulate_network_troubles() { echo Simulate packet loss diff -Nru pcp-5.3.1/qa/1170 pcp-5.3.2/qa/1170 --- pcp-5.3.1/qa/1170 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1170 2021-07-30 04:05:06.000000000 +0000 @@ -21,46 +21,40 @@ ;; esac -if [ -f /etc/lsb-release ] -then - . /etc/lsb-release - if [ "$DISTRIB_ID" = Ubuntu ] - then - # This test fails for Ubuntu 19.10 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$DISTRIB_RELEASE" - in - 19.10) - _notrun "bcc does not work for this test on Ubuntu $DISTRIB_RELEASE" - ;; - esac - fi -fi - -if [ -f /etc/os-release ] -then - . /etc/os-release - if [ "$NAME" = "openSUSE Leap" ] - then - # This test fails for openSUSE 15.1 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$VERSION" - in - 15.1) - _notrun "bcc does not work for this test on openSUSE $VERSION" - ;; - esac - fi -fi - target_ip=1.1.1.1 status=1 # failure is the default! signal=$PCP_BINADM_DIR/pmsignal $sudo rm -rf $tmp.* $seq.full +# Some combinations of distro and kernel are known to be "bad" +# for some BPF modules +# +kernel=`uname -r` +echo "$kernel" >>$seq.full +case `admin/whatami` +in + *Fedora\ 32\ *) + _notrun "bcc tcptop module will not compile on Fedora 32" + ;; + *Ubuntu\ 19.10\ *) + _notrun "bcc tcptop module will not compile on Ubuntu 19.10" + ;; + *Ubuntu\ 20.04\ *) + # works on 5.4 kernel, not on 5.8.0-1033-azure + # + case "$kernel" + in + 5.8.0-*-azure) + _notrun "bcc tcptop module will not compile on Ubuntu kernel $kernel" + ;; + esac + ;; + *openSUSE\ Leap\ 15.1\ *) + _notrun "bcc tcptop module will not compile on openSUSE 15.1" + ;; +esac + _prepare_pmda bcc trap "_pmdabcc_cleanup; exit \$status" 0 1 2 3 15 _stop_auto_restart pmcd diff -Nru pcp-5.3.1/qa/1178 pcp-5.3.2/qa/1178 --- pcp-5.3.1/qa/1178 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1178 2021-07-30 04:05:06.000000000 +0000 @@ -21,46 +21,40 @@ ;; esac -if [ -f /etc/lsb-release ] -then - . /etc/lsb-release - if [ "$DISTRIB_ID" = Ubuntu ] - then - # This test fails for Ubuntu 19.10 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$DISTRIB_RELEASE" - in - 19.10) - _notrun "bcc does not work for this test on Ubuntu $DISTRIB_RELEASE" - ;; - esac - fi -fi - -if [ -f /etc/os-release ] -then - . /etc/os-release - if [ "$NAME" = "openSUSE Leap" ] - then - # This test fails for openSUSE 15.1 because the linux headers used - # by the BPF compiler appear to be knackered. - # - case "$VERSION" - in - 15.1) - _notrun "bcc does not work for this test on openSUSE $VERSION" - ;; - esac - fi -fi - target_ip=1.1.1.1 status=1 # failure is the default! signal=$PCP_BINADM_DIR/pmsignal $sudo rm -rf $tmp.* $seq.full +# Some combinations of distro and kernel are known to be "bad" +# for some BPF modules +# +kernel=`uname -r` +echo "$kernel" >>$seq.full +case `admin/whatami` +in + *Fedora\ 32\ *) + _notrun "bcc tcpperpid module will not compile on Fedora 32" + ;; + *Ubuntu\ 19.10\ *) + _notrun "bcc tcpperpid module will not compile on Ubuntu 19.10" + ;; + *Ubuntu\ 20.04\ *) + # works on 5.4 kernel, not on 5.8.0-1033-azure + # + case "$kernel" + in + 5.8.0-*-azure) + _notrun "bcc tcpperpid module will not compile on Ubuntu kernel $kernel" + ;; + esac + ;; + *openSUSE\ Leap\ 15.1\ *) + _notrun "bcc tcpperpid module will not compile on openSUSE 15.1" + ;; +esac + _install_filter() { sed \ diff -Nru pcp-5.3.1/qa/1190 pcp-5.3.2/qa/1190 --- pcp-5.3.1/qa/1190 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/1190 2021-07-30 04:05:06.000000000 +0000 @@ -49,9 +49,9 @@ # if [ -r "$1" ] then - grep -i QA "$1" >$tmp.out + grep -i QA "$1" >$tmp.out 2>>$here/$seq.full else - $sudo grep -i QA "$1" >$tmp.out + $sudo grep -i QA "$1" >$tmp.out 2>>$here/$seq.full fi # some of these are indeed expected and OK, so handle the exceptions # here ... @@ -153,6 +153,7 @@ sed -e 's/^/ /' <$tmp.pids $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mcd |[p]mcd$' \ | sed -e 's/^/ /' + _systemctl_status pmcd status=1 fi @@ -164,6 +165,7 @@ else echo "Count of primary pmlogger's ... BAD ($n not 1)" cat $tmp.out | sed -e 's/^/ /' + _systemctl_status pmlogger status=1 fi diff -Nru pcp-5.3.1/qa/1222.out pcp-5.3.2/qa/1222.out --- pcp-5.3.1/qa/1222.out 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/1222.out 2021-07-30 04:05:06.000000000 +0000 @@ -13,6 +13,8 @@ === check number of values === === std out === proc.nprocs: 1 value +proc.psinfo.cwd: >10 values +proc.psinfo.exe: >10 values proc.psinfo.oom_score: >10 values proc.psinfo.tgid: >10 values proc.psinfo.cpusallowed: >10 values diff -Nru pcp-5.3.1/qa/1243 pcp-5.3.2/qa/1243 --- pcp-5.3.1/qa/1243 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1243 2021-06-15 01:03:49.000000000 +0000 @@ -16,6 +16,13 @@ _get_libpcp_config $service_discovery || _notrun "No support for service discovery" +case `admin/whatami` +in + *Fedora\ 32\ *) + _notrun "helgrind broken for this test on Fedora 32" + ;; +esac + if sed -e 's/$/ /' /etc/hosts | grep '::1[ ].*localhost ' >/dev/null then : diff -Nru pcp-5.3.1/qa/1250 pcp-5.3.2/qa/1250 --- pcp-5.3.1/qa/1250 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1250 2021-06-15 01:03:49.000000000 +0000 @@ -37,6 +37,7 @@ else _notrun "audit2allow -w is broken" fi +[ -f $PCP_INC_DIR/builddefs ] || _notrun "No $PCP_INC_DIR/builddefs" _cleanup() { @@ -54,9 +55,15 @@ # _audit() { - echo "$1" \ + echo "---" >>$seq.full + cat $1 >>$seq.full + cat $1 \ | audit2allow -w 2>&1 \ + | tee -a $seq.full \ | sed \ + -e '/^type=AVC/d' \ + -e '/^type=USER_AVC/d' \ + -e '/^audit: /d' \ -e 's/^[ ]*//' \ -e 's/ */ /g' \ | $PCP_AWK_PROG ' @@ -69,204 +76,250 @@ -e '/^Possible mismatch between current in-memory boolean /d' \ -e '/The boolean domain_can_write_kmsg was set incorrectly./d' \ -e '/The boolean nis_enabled was set incorrectly./d' \ - | tr -s '\n' + | tr -s '\n' \ + | sed -e '/^$/d' } # real QA test starts here +echo "Silence is golden ... all AVC's are allowed by active policy" +echo + echo "============= bogus AVC ... expect output ==============" -_audit "type=AVC msg=audit(1484681301.812:174751): avc: denied { rmdir } for pid=21999 comm=\"foobar\" name=\"foobar\" dev=\"foobar\" ino=1 scontext=system_u:object_r:etc_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=dir permissive=0" +rm -f $tmp.avc +echo "type=AVC msg=audit(1484681301.812:174751): avc: denied { rmdir } for pid=21999 comm=\"foobar\" name=\"foobar\" dev=\"foobar\" ino=1 scontext=system_u:object_r:etc_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=dir permissive=0" >>$tmp.avc + +_audit $tmp.avc echo "============= init_t ==============" -_audit "type=AVC msg=audit(1484681301.812:174751): avc: denied { read } for pid=21999 comm=\"pmcd\" name=\"pmcd\" dev=\"dm-1\" ino=936441 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_log_t:s0 tclass=dir permissive=0" +rm -f $tmp.avc +echo "type=AVC msg=audit(1484681301.812:174751): avc: denied { read } for pid=21999 comm=\"pmcd\" name=\"pmcd\" dev=\"dm-1\" ino=936441 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_log_t:s0 tclass=dir permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1484681301.810:174749): avc: denied { getattr } for pid=21999 comm=\"pmcd\" path=\"/var/lib/pcp/pmns/root\" dev=\"dm-1\" ino=945382 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1484681301.810:174749): avc: denied { getattr } for pid=21999 comm=\"pmcd\" path=\"/var/lib/pcp/pmns/root\" dev=\"dm-1\" ino=945382 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1484681301.810:174750): avc: denied { execute } for pid=21999 comm=\"pmcd\" name=\"Rebuild\" dev=\"dm-1\" ino=937158 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1484681301.810:174750): avc: denied { execute } for pid=21999 comm=\"pmcd\" name=\"Rebuild\" dev=\"dm-1\" ino=937158 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1484681301.369:174692): avc: denied { open } for pid=21901 comm=\"pmcd\" path=\"/var/tmp/pcp.sQReBLg6R/pcp.env.path\" dev=\"dm-1\" ino=930323 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1484681301.369:174692): avc: denied { open } for pid=21901 comm=\"pmcd\" path=\"/var/tmp/pcp.sQReBLg6R/pcp.env.path\" dev=\"dm-1\" ino=930323 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=USER_AVC msg=audit(1535947021.608:238558): pid=775 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: denied { send_msg } for msgtype=method_return dest=:1.14778 spid=1 tpid=19555 scontext=system_u:system_r:init_t:s0 tcontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tclass=dbus permissive=0 exe=\"/usr/bin/dbus-daemon\" sauid=81 hostname=? addr=? terminal=?" +echo "type=USER_AVC msg=audit(1535947021.608:238558): pid=775 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: denied { send_msg } for msgtype=method_return dest=:1.14778 spid=1 tpid=19555 scontext=system_u:system_r:init_t:s0 tcontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tclass=dbus permissive=0 exe=\"/usr/bin/dbus-daemon\" sauid=81 hostname=? addr=? terminal=?" >>$tmp.avc + +_audit $tmp.avc echo "============= pcp_pmcd_t ==============" -_audit "type=AVC msg=audit(1463754714.313:316): avc: denied { net_admin } for pid=2335 comm=\"pmcd\" capability=12 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1" +rm -f $tmp.avc +echo "type=AVC msg=audit(1463754714.313:316): avc: denied { net_admin } for pid=2335 comm=\"pmcd\" capability=12 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1491576442.619:1738169): avc: denied { sys_ptrace } for pid=15205 comm=\"pmdaproc\" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0" +echo "type=AVC msg=audit(1491576442.619:1738169): avc: denied { sys_ptrace } for pid=15205 comm=\"pmdaproc\" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498833776.957:2094): avc: denied { ipc_owner } for pid=21341 comm=\"pmdalinux\" capability=15 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0" +echo "type=AVC msg=audit(1498833776.957:2094): avc: denied { ipc_owner } for pid=21341 comm=\"pmdalinux\" capability=15 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1491581538.561:10949): avc: denied { getattr } for pid=9375 comm=\"pmdaproc\" path=\"/run/systemd/initctl/fifo\" dev=\"tmpfs\" ino=13290 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:initctl_t:s0 tclass=fifo_file permissive=1" +echo "type=AVC msg=audit(1491581538.561:10949): avc: denied { getattr } for pid=9375 comm=\"pmdaproc\" path=\"/run/systemd/initctl/fifo\" dev=\"tmpfs\" ino=13290 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:initctl_t:s0 tclass=fifo_file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1491581538.587:10952): avc: denied { sys_ptrace } for pid=9375 comm=\"pmdaproc\" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=cap_userns permissive=1" +echo "type=AVC msg=audit(1491581538.587:10952): avc: denied { sys_ptrace } for pid=9375 comm=\"pmdaproc\" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=cap_userns permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1485899863.032:3024): avc: denied { sys_chroot } for pid=25873 comm=\"pmdalinux\" capability=18 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability" +echo "type=AVC msg=audit(1485899863.032:3024): avc: denied { sys_chroot } for pid=25873 comm=\"pmdalinux\" capability=18 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability" >>$tmp.avc -_audit "type=AVC msg=audit(1485899838.438:13213): avc: denied { read } for pid=29112 comm=\"pmdalinux\" dev=\"nsfs\" ino=4026532454 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:nsfs_t:s0 tclass=file permissive=1" +if grep 'PCP_SELINUX_NSFS[ ]*=[ ]*true' $PCP_INC_DIR/builddefs >/dev/null 2>&1 +then + echo "type=AVC msg=audit(1485899838.438:13213): avc: denied { read } for pid=29112 comm=\"pmdalinux\" dev=\"nsfs\" ino=4026532454 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:nsfs_t:s0 tclass=file permissive=1" >>$tmp.avc +fi -_audit "type=AVC msg=audit(1498835003.745:8276): avc: denied { name_bind } for pid=7079 comm=\"pmdasimple\" src=5650 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0" +if grep 'PCP_SELINUX_UNRESERVED_PORT[ ]*=[ ]*true' $PCP_INC_DIR/builddefs >/dev/null 2>&1 +then + echo "type=AVC msg=audit(1498835003.745:8276): avc: denied { name_bind } for pid=7079 comm=\"pmdasimple\" src=5650 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498835005.744:8277): avc: denied { name_connect } for pid=29238 comm=\"pmcd\" dest=5650 scontex =system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0" + echo "type=AVC msg=audit(1498835005.744:8277): avc: denied { name_connect } for pid=29238 comm=\"pmcd\" dest=5650 scontex =system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0" >>$tmp.avc +fi -_audit "type=AVC msg=audit(1499709840.120:5028): avc: denied { name_connect } for pid=13816 comm=\"python3\" dest=9090 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:websm_port_t:s0 tclass=tcp_socket permissive=0" +echo "type=AVC msg=audit(1499709840.120:5028): avc: denied { name_connect } for pid=13816 comm=\"python3\" dest=9090 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:websm_port_t:s0 tclass=tcp_socket permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498835613.883:11808): avc: denied { unix_read } for pid=14552 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=shm permissive=0" +echo "type=AVC msg=audit(1498835613.883:11808): avc: denied { unix_read } for pid=14552 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=shm permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498846768.313:12024): avc: denied { getattr associate } for pid=8128 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=shm permissive=0" +echo "type=AVC msg=audit(1498846768.313:12024): avc: denied { getattr associate } for pid=8128 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=shm permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498843308.799:418): avc: denied { read } for pid=16668 comm=\"pmdalogger\" name=\"458-16195.fifo\" dev=\"tmpfs\" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0" +echo "type=AVC msg=audit(1498843308.799:418): avc: denied { read } for pid=16668 comm=\"pmdalogger\" name=\"458-16195.fifo\" dev=\"tmpfs\" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498843308.800:420): avc: denied { getattr } for pid=16668 comm=\"pmdalogger\" path=\"/tmp/458-16195.fifo\" dev=\"tmpfs\" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0" +echo "type=AVC msg=audit(1498843308.800:420): avc: denied { getattr } for pid=16668 comm=\"pmdalogger\" path=\"/tmp/458-16195.fifo\" dev=\"tmpfs\" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498843308.800:419): avc: denied { open } for pid=16668 comm=\"pmdalogger\" path=\"/tmp/458-16195.fifo\" dev=\"tmpfs\" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0" +echo "type=AVC msg=audit(1498843308.800:419): avc: denied { open } for pid=16668 comm=\"pmdalogger\" path=\"/tmp/458-16195.fifo\" dev=\"tmpfs\" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.316:3557): avc: denied { execute } for pid=8648 comm=\"sh\" name=\"8641\" dev=\"tmpfs\" ino=246964 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.316:3557): avc: denied { execute } for pid=8648 comm=\"sh\" name=\"8641\" dev=\"tmpfs\" ino=246964 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.316:3558): avc: denied { execute_no_trans } for pid=8648 comm=\"sh\" path=\"/tmp/8641\" dev=\"tmpfs\" ino=246964 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.316:3558): avc: denied { execute_no_trans } for pid=8648 comm=\"sh\" path=\"/tmp/8641\" dev=\"tmpfs\" ino=246964 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.327:3559): avc: denied { getattr } for pid=8656 comm=\"sh\" path=\"/usr/bin/hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.327:3559): avc: denied { getattr } for pid=8656 comm=\"sh\" path=\"/usr/bin/hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.327:3560): avc: denied { execute } for pid=8656 comm=\"sh\" name=\"hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.327:3560): avc: denied { execute } for pid=8656 comm=\"sh\" name=\"hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.327:3561): avc: denied { read } for pid=8656 comm=\"sh\" name=\"hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.327:3561): avc: denied { read } for pid=8656 comm=\"sh\" name=\"hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.327:3562): avc: denied { open } for pid=8657 comm=\"sh\" path=\"/usr/bin/hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.327:3562): avc: denied { open } for pid=8657 comm=\"sh\" path=\"/usr/bin/hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498844147.327:3563): avc: denied { execute_no_trans } for pid=8657 comm=\"sh\" path=\"/usr/bin/hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1498844147.327:3563): avc: denied { execute_no_trans } for pid=8657 comm=\"sh\" path=\"/usr/bin/hostname\" dev=\"dm-1\" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498845911.359:7642): avc: denied { mount } for pid=22090 comm=\"pmdaperfevent\" name=\"/\" dev=\"tracefs\" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=filesystem permissive=0" +if seinfo -t | grep '^[ ]*tracefs_t$' >/dev/null +then + echo "type=AVC msg=audit(1498845911.359:7642): avc: denied { mount } for pid=22090 comm=\"pmdaperfevent\" name=\"/\" dev=\"tracefs\" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=filesystem permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498845911.360:7643): avc: denied { search } for pid=22090 comm=\"pmdaperfevent\" name=\"/\" dev=\"tracefs\" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0" + echo "type=AVC msg=audit(1498845911.360:7643): avc: denied { search } for pid=22090 comm=\"pmdaperfevent\" name=\"/\" dev=\"tracefs\" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498845911.360:7644): avc: denied { read } for pid=22090 comm=\"pmdaperfevent\" name=\"events\" dev=\"tracefs\" ino=176 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0" + echo "type=AVC msg=audit(1498845911.360:7644): avc: denied { read } for pid=22090 comm=\"pmdaperfevent\" name=\"events\" dev=\"tracefs\" ino=176 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498845911.360:7645): avc: denied { open } for pid=22090 comm=\"pmdaperfevent\" path=\"/sys/kernel/debug/tracing/events\" dev=\"tracefs\" ino=176 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0" + echo "type=AVC msg=audit(1498845911.360:7645): avc: denied { open } for pid=22090 comm=\"pmdaperfevent\" path=\"/sys/kernel/debug/tracing/events\" dev=\"tracefs\" ino=176 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498845911.360:7646): avc: denied { read } for pid=22090 comm=\"pmdaperfevent\" name=\"id\" dev=\"tracefs\" ino=321619 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0" + echo "type=AVC msg=audit(1498845911.360:7646): avc: denied { read } for pid=22090 comm=\"pmdaperfevent\" name=\"id\" dev=\"tracefs\" ino=321619 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1498845911.360:7647): avc: denied { open } for pid=22090 comm=\"pmdaperfevent\" path=\"/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_state_change/id\" dev=\"tracefs\" ino=321619 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0" + echo "type=AVC msg=audit(1498845911.360:7647): avc: denied { open } for pid=22090 comm=\"pmdaperfevent\" path=\"/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_state_change/id\" dev=\"tracefs\" ino=321619 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0" >>$tmp.avc +fi echo "RHBZ1505888" -_audit "type=AVC msg=audit(1508779244.425:386): avc: denied { write } for pid=2967 comm=\"pmdaxfs\" name=\"stats_clear\" dev=\"proc\" ino=87731 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sysctl_fs_t:s0 tclass=file" +echo "type=AVC msg=audit(1508779244.425:386): avc: denied { write } for pid=2967 comm=\"pmdaxfs\" name=\"stats_clear\" dev=\"proc\" ino=87731 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sysctl_fs_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(...): avc: denied { getattr } for pid=NNN comm=\"pmdalinux\" path=\"/var/lib/mock\" dev=\"dm-1\" ino=917749 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:mock_var_lib_t:s0 tclass=dir permissive=1" +if seinfo -t | grep '^[ ]*mock_var_lib_t$' >/dev/null +then + echo "type=AVC msg=audit(...): avc: denied { getattr } for pid=NNN comm=\"pmdalinux\" path=\"/var/lib/mock\" dev=\"dm-1\" ino=917749 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:mock_var_lib_t:s0 tclass=dir permissive=1" >>$tmp.avc +fi -_audit "type=AVC msg=audit(...): avc: denied { map } for pid=NNN comm=\"ldconfig\" path=\"/usr/sbin/ldconfig\" dev=\"dm-1\" ino=1052382 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:ldconfig_exec_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(...): avc: denied { map } for pid=NNN comm=\"ldconfig\" path=\"/usr/sbin/ldconfig\" dev=\"dm-1\" ino=1052382 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:ldconfig_exec_t:s0 tclass=file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1519670939.873:2012): avc: denied { unix_read } for pid=1423 comm=\"pmdalinux\" key=-559038737 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0" +echo "type=AVC msg=audit(1519670939.873:2012): avc: denied { unix_read } for pid=1423 comm=\"pmdalinux\" key=-559038737 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1519670949.871:2013): avc: denied { unix_read } for pid=1423 comm=\"pmdalinux\" key=-559038737 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0" +echo "type=AVC msg=audit(1519670949.871:2013): avc: denied { unix_read } for pid=1423 comm=\"pmdalinux\" key=-559038737 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1530448398.992:231): avc: denied { read } for pid=16334 comm=\"python3\" name=\"kallsyms\" dev=\"proc\" ino=4026532064 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:system_map_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(1530448398.992:231): avc: denied { read } for pid=16334 comm=\"python3\" name=\"kallsyms\" dev=\"proc\" ino=4026532064 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:system_map_t:s0 tclass=file permissive=1" >>$tmp.avc echo "RHBZ1622253" -_audit "type=AVC msg=audit(1532540174.341:22480): avc: denied { search } for pid=25668 comm=\"perl\" name=\"named\" dev=\"dm-3\" ino=2128175 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:named_zone_t:s0 tclass=dir" +echo "type=AVC msg=audit(1532540174.341:22480): avc: denied { search } for pid=25668 comm=\"perl\" name=\"named\" dev=\"dm-3\" ino=2128175 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:named_zone_t:s0 tclass=dir" >>$tmp.avc echo "RHBZ1619381" -_audit "type=AVC msg=audit(1534774142.552:48731): avc: denied { unix_read } for pid=1726 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:xdm_t:s0-s0:c0.c1023 tclass=shm permissive=0" +echo "type=AVC msg=audit(1534774142.552:48731): avc: denied { unix_read } for pid=1726 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:xdm_t:s0-s0:c0.c1023 tclass=shm permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(...): avc: denied { connectto } for pid=NNN comm=\"python\" path=\"/run/postgresql/.s.PGSQL.5432\" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:postgresql_t:s0 tclass=unix_stream_socket" +echo "type=AVC msg=audit(...): avc: denied { connectto } for pid=NNN comm=\"python\" path=\"/run/postgresql/.s.PGSQL.5432\" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:postgresql_t:s0 tclass=unix_stream_socket" >>$tmp.avc echo "RHBZ1535522" -_audit "type=AVC msg=audit(1538550792.679:11735): avc: denied { search } for pid=21371 comm=\"pmdalinux\" name=\".cache\" dev=\"dm-0\" ino=11796488 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:cache_home_t:s0 tclass=dir permissive=0" +echo "type=AVC msg=audit(1538550792.679:11735): avc: denied { search } for pid=21371 comm=\"pmdalinux\" name=\".cache\" dev=\"dm-0\" ino=11796488 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:cache_home_t:s0 tclass=dir permissive=0" >>$tmp.avc echo "RHBZ1601721" -_audit "type=AVC msg=audit(1531806277.341:312): avc: denied { unix_read } for pid=2349 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:iscsid_t:s0 tclass=shm permissive=0" +echo "type=AVC msg=audit(1531806277.341:312): avc: denied { unix_read } for pid=2349 comm=\"pmdalinux\" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:iscsid_t:s0 tclass=shm permissive=0" >>$tmp.avc + +_audit $tmp.avc echo "============= pcp_pmlogger_t ==============" -_audit "type=AVC msg=audit(1494326424.876:88): avc: denied { write } for pid=18266 comm=\"logger\" name=\"log\" dev=\"devtmpfs\" ino=1413 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:devlog_t:s0 tclass=sock_file" +rm -f $tmp.avc +echo "type=AVC msg=audit(1494326424.876:88): avc: denied { write } for pid=18266 comm=\"logger\" name=\"log\" dev=\"devtmpfs\" ino=1413 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:devlog_t:s0 tclass=sock_file" >>$tmp.avc -_audit "type=AVC msg=audit(1498833990.644:5974): avc: denied { read } for pid=26849 comm=\"logger\" name=\"log\" dev=\"devtmpfs\" ino=1389 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:devlog_t:s0 tclass=lnk_file permissive=0" +echo "type=AVC msg=audit(1498833990.644:5974): avc: denied { read } for pid=26849 comm=\"logger\" name=\"log\" dev=\"devtmpfs\" ino=1389 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:devlog_t:s0 tclass=lnk_file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1484681301.380:174695): avc: denied { sys_ptrace } for pid=21962 comm=\"ps\" capability=19 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:system_r:pcp_pmlogger_t:s0 tclass=capability" +echo "type=AVC msg=audit(1484681301.380:174695): avc: denied { sys_ptrace } for pid=21962 comm=\"ps\" capability=19 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:system_r:pcp_pmlogger_t:s0 tclass=capability" >>$tmp.avc -_audit "type=AVC msg=audit(04/19/2017 16:57:40.120:11020) : avc: denied { signal } for pid=28414 comm=pmsignal scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process" +echo "type=AVC msg=audit(04/19/2017 16:57:40.120:11020) : avc: denied { signal } for pid=28414 comm=pmsignal scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process" >>$tmp.avc -_audit "type=AVC msg=audit(1503321970.417:261): avc: denied { execute_no_trans } for pid=6760 comm=\"pmlogger_check\" path=\"/usr/bin/pmlogger\" dev=\"dm-1\" ino=1051023 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:pcp_pmlogger_exec_t:s0 tclass=file permissive=0" +echo "type=AVC msg=audit(1503321970.417:261): avc: denied { execute_no_trans } for pid=6760 comm=\"pmlogger_check\" path=\"/usr/bin/pmlogger\" dev=\"dm-1\" ino=1051023 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:pcp_pmlogger_exec_t:s0 tclass=file permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(1493690261.688:262): avc: denied { name_connect } for pid=17604 comm=\"pmlc\" dest=4330 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:dey_sapi_port_t:s0 tclass=tcp_socket" +echo "type=AVC msg=audit(1493690261.688:262): avc: denied { name_connect } for pid=17604 comm=\"pmlc\" dest=4330 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:dey_sapi_port_t:s0 tclass=tcp_socket" >>$tmp.avc -_audit "type=AVC msg=audit(1533291591.092:495620): avc: denied { connectto } for pid=18025 comm=\"pmprobe\" path=\"/run/pcp/pmcd.socket\" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0" +echo "type=AVC msg=audit(1533291591.092:495620): avc: denied { connectto } for pid=18025 comm=\"pmprobe\" path=\"/run/pcp/pmcd.socket\" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0" >>$tmp.avc echo "RHBZ1488116" -_audit "type=AVC msg=audit(1504516526.487:431): avc: denied { search } for pid=18056 comm=\"ps\" name=\"testuser\" dev=\"dm-0\" ino=539096275 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir" +echo "type=AVC msg=audit(1504516526.487:431): avc: denied { search } for pid=18056 comm=\"ps\" name=\"testuser\" dev=\"dm-0\" ino=539096275 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir" >>$tmp.avc echo "RHBZ1634205" -_audit "type=AVC msg=audit(1538179769.540:285): avc: denied { search } for pid=8613 comm=\"ps\" name=\".cache\" dev=\"dm-0\" ino=1277884 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:cache_home_t:s0 tclass=dir permissive=0" +echo "type=AVC msg=audit(1538179769.540:285): avc: denied { search } for pid=8613 comm=\"ps\" name=\".cache\" dev=\"dm-0\" ino=1277884 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:cache_home_t:s0 tclass=dir permissive=0" >>$tmp.avc echo "RHBZ1648602" -_audit "type=AVC msg=audit(1541890175.206:269): avc: denied { search } for pid=7835 comm=\"ps\" name=\"lightdm\" dev=\"sda1\" ino=3145740 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:xserver_log_t:s0 tclass=dir permissive=0" +echo "type=AVC msg=audit(1541890175.206:269): avc: denied { search } for pid=7835 comm=\"ps\" name=\"lightdm\" dev=\"sda1\" ino=3145740 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:xserver_log_t:s0 tclass=dir permissive=0" >>$tmp.avc + +_audit $tmp.avc echo "============= pcp_pmie_t ==============" -_audit "type=AVC msg=audit(1498847682.537:15753): avc: denied { sys_ptrace } for pid=30881 comm=\"ps\" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=capability permissive=0" +rm -f $tmp.avc +echo "type=AVC msg=audit(1498847682.537:15753): avc: denied { sys_ptrace } for pid=30881 comm=\"ps\" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=capability permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.084:351) : avc: denied { connectto } for pid=8941 comm=systemctl path=/run/systemd/private scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=unix_stream_socket" +echo "type=AVC msg=audit(04/05/2017 10:24:45.084:351) : avc: denied { connectto } for pid=8941 comm=systemctl path=/run/systemd/private scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=unix_stream_socket" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.081:348) : avc: denied { open } for pid=8939 comm=runlevel path=/run/utmp dev=\"tmpfs\" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file" +echo "type=AVC msg=audit(04/05/2017 10:24:45.081:348) : avc: denied { open } for pid=8939 comm=runlevel path=/run/utmp dev=\"tmpfs\" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.081:348) : avc: denied { read } for pid=8939 comm=runlevel name=utmp dev=\"tmpfs\" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file" +echo "type=AVC msg=audit(04/05/2017 10:24:45.081:348) : avc: denied { read } for pid=8939 comm=runlevel name=utmp dev=\"tmpfs\" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.081:349) : avc: denied { lock } for pid=8939 comm=runlevel path=/run/utmp dev=\"tmpfs\" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file" +echo "type=AVC msg=audit(04/05/2017 10:24:45.081:349) : avc: denied { lock } for pid=8939 comm=runlevel path=/run/utmp dev=\"tmpfs\" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.082:350) : avc: denied { getattr } for pid=8870 comm=pmie path=/usr/lib/systemd/system/pmie.service dev=\"dm-1\" ino=4203 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=file" +if seinfo -t | grep '^[ ]*systemd_unit_file_t$' >/dev/null +then + echo "type=AVC msg=audit(04/05/2017 10:24:45.082:350) : avc: denied { getattr } for pid=8870 comm=pmie path=/usr/lib/systemd/system/pmie.service dev=\"dm-1\" ino=4203 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(1498847677.050:15587): avc: denied { search } for pid=30181 comm=\"pmie\" name=\"system\" dev=\"dm-1\" ino=1182241 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=dir permissive=0" + echo "type=AVC msg=audit(1498847677.050:15587): avc: denied { search } for pid=30181 comm=\"pmie\" name=\"system\" dev=\"dm-1\" ino=1182241 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=dir permissive=0" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 09:58:27.740:304) : avc: denied { read } for pid=7073 comm=pmie name=systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" + echo "type=AVC msg=audit(04/05/2017 09:58:27.742:305) : avc: denied { getattr } for pid=7004 comm=pmie path=/usr/lib/systemd/system/pmie.service dev=\"dm-1\" ino=4203 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=file" >>$tmp.avc +fi -_audit "type=AVC msg=audit(04/05/2017 09:58:27.740:303) : avc: denied { execute } for pid=7073 comm=pmie name=systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" +if seinfo -t | grep '^[ ]*systemd_systemctl_exec_t$' >/dev/null +then + echo "type=AVC msg=audit(04/05/2017 09:58:27.740:304) : avc: denied { read } for pid=7073 comm=pmie name=systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 09:58:27.742:305) : avc: denied { getattr } for pid=7004 comm=pmie path=/usr/lib/systemd/system/pmie.service dev=\"dm-1\" ino=4203 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=file" + echo "type=AVC msg=audit(04/05/2017 09:58:27.740:303) : avc: denied { execute } for pid=7073 comm=pmie name=systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.080:347) : avc: denied { execute_no_trans } for pid=8939 comm=pmie path=/usr/bin/systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" + echo "type=AVC msg=audit(04/05/2017 10:24:45.080:347) : avc: denied { execute_no_trans } for pid=8939 comm=pmie path=/usr/bin/systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.080:347) : avc: denied { open } for pid=8939 comm=pmie path=/usr/bin/systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" + echo "type=AVC msg=audit(04/05/2017 10:24:45.080:347) : avc: denied { open } for pid=8939 comm=pmie path=/usr/bin/systemctl dev=\"dm-1\" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(1498843991.020:2708): avc: denied { getattr } for pid=13079 comm=\"which\" path=\"/usr/bin/systemctl\" dev=\"dm-1\" ino=1078205 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file permissive=0" + echo "type=AVC msg=audit(1498843991.020:2708): avc: denied { getattr } for pid=13079 comm=\"which\" path=\"/usr/bin/systemctl\" dev=\"dm-1\" ino=1078205 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file permissive=0" >>$tmp.avc +fi -_audit "type=AVC msg=audit(1498836881.729:16279): avc: denied { connectto } for pid=12589 comm=\"pmie\" path=\"/run/pcp/pmcd.socket\" scontext=system_u:system_r:pcp_pmie_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0" +echo "type=AVC msg=audit(1498836881.729:16279): avc: denied { connectto } for pid=12589 comm=\"pmie\" path=\"/run/pcp/pmcd.socket\" scontext=system_u:system_r:pcp_pmie_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0" >>$tmp.avc -_audit "audit: type=1400 audit(1504924094.677:197): avc: denied { execute_no_trans } for pid=3703 comm=pmie_check path=/usr/bin/pmie dev=dm-0 ino=2506240 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:pcp_pmie_exec_t:s0 tclass=file permissive=0" +echo "audit: type=1400 audit(1504924094.677:197): avc: denied { execute_no_trans } for pid=3703 comm=pmie_check path=/usr/bin/pmie dev=dm-0 ino=2506240 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:pcp_pmie_exec_t:s0 tclass=file permissive=0" >>$tmp.avc echo "RHBZ1533080" -_audit "type=AVC msg=audit(...): avc: denied { open } for pid=NNN comm=\"runlevel\" path=\"/dev/kmsg\" dev=\"devtmpfs\" ino=1043 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:kmsg_device_t:s0 tclass=chr_file permissive=1" +echo "type=AVC msg=audit(...): avc: denied { open } for pid=NNN comm=\"runlevel\" path=\"/dev/kmsg\" dev=\"devtmpfs\" ino=1043 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:kmsg_device_t:s0 tclass=chr_file permissive=1" >>$tmp.avc echo "RHBZ1623988" -_audit "type=AVC msg=audit(1535642748.855:3214): avc: denied { signal } for pid=3106 comm=\"pmsignal\" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process permissive=1" +echo "type=AVC msg=audit(1535642748.855:3214): avc: denied { signal } for pid=3106 comm=\"pmsignal\" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process permissive=1" >>$tmp.avc echo "RHBZ1635394" -_audit "type=AVC msg=audit(1538509480.147:87573): avc: denied { sys_ptrace } for pid=15683 comm=\"ps\" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=cap_userns permissive=0" +echo "type=AVC msg=audit(1538509480.147:87573): avc: denied { sys_ptrace } for pid=15683 comm=\"ps\" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=cap_userns permissive=0" >>$tmp.avc + +_audit $tmp.avc echo "============= pcp_pmproxy_t ==============" -_audit "type=AVC msg=audit(04/05/2017 09:54:13.548:281) : avc: denied { net_admin } for pid=6669 comm=pmproxy capability=net_admin scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:system_r:pcp_pmproxy_t:s0 tclass=capability" +rm -f $tmp.avc +echo "type=AVC msg=audit(04/05/2017 09:54:13.548:281) : avc: denied { net_admin } for pid=6669 comm=pmproxy capability=net_admin scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:system_r:pcp_pmproxy_t:s0 tclass=capability" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 09:54:13.548:281) : avc: denied { read } for pid=6669 comm=pmproxy name=disable_ipv6 dev=\"proc\" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file" +echo "type=AVC msg=audit(04/05/2017 09:54:13.548:281) : avc: denied { read } for pid=6669 comm=pmproxy name=disable_ipv6 dev=\"proc\" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.771:356) : avc: denied { open } for pid=9669 comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev=\"proc\" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file" +echo "type=AVC msg=audit(04/05/2017 10:24:45.771:356) : avc: denied { open } for pid=9669 comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev=\"proc\" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(04/05/2017 10:24:45.771:357) : avc: denied { getattr } for pid=9669 comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev=\"proc\" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file" +echo "type=AVC msg=audit(04/05/2017 10:24:45.771:357) : avc: denied { getattr } for pid=9669 comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev=\"proc\" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file" >>$tmp.avc -_audit "type=AVC msg=audit(1498837089.845:16693): avc: denied { search } for pid=14446 comm=\"pmproxy\" name=\"net\" dev=\"proc\" ino=1168 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=dir permissive=0" +echo "type=AVC msg=audit(1498837089.845:16693): avc: denied { search } for pid=14446 comm=\"pmproxy\" name=\"net\" dev=\"proc\" ino=1168 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=dir permissive=0" >>$tmp.avc echo "RHBZ1517656" -_audit "type=AVC msg=audit(1511771694.686:575): avc: denied { read } for pid=28833 comm=\"pmproxy\" name=\"unix\" dev=\"proc\" ino=4026532015 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:proc_net_t:s0 tclass=file" +echo "type=AVC msg=audit(1511771694.686:575): avc: denied { read } for pid=28833 comm=\"pmproxy\" name=\"unix\" dev=\"proc\" ino=4026532015 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:proc_net_t:s0 tclass=file" >>$tmp.avc + +_audit $tmp.avc echo "============= pmda-smart ==============" -_audit "type=AVC msg=audit(1525420698.415:327): avc: denied { read } for pid=8678 comm=\"sh\" name=\"smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" +rm -f $tmp.avc +echo "type=AVC msg=audit(1525420698.415:327): avc: denied { read } for pid=8678 comm=\"sh\" name=\"smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" >>$tmp.avc + +echo "type=AVC msg=audit(1525420698.415:328): avc: denied { open } for pid=8678 comm=\"sh\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1525420698.415:328): avc: denied { open } for pid=8678 comm=\"sh\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(1525420698.415:329): avc: denied { execute_no_trans } for pid=8678 comm=\"sh\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1525420698.415:329): avc: denied { execute_no_trans } for pid=8678 comm=\"sh\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(1525420698.415:326): avc: denied { execute } for pid=8678 comm=\"sh\" name=\"smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1525420698.415:326): avc: denied { execute } for pid=8678 comm=\"sh\" name=\"smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(1525375355.243:3382): avc: denied { getattr } for pid=4770 comm=\"sh\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1525375355.243:3382): avc: denied { getattr } for pid=4770 comm=\"sh\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(1525420698.417:330): avc: denied { map } for pid=8678 comm=\"smartctl\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1525420698.417:330): avc: denied { map } for pid=8678 comm=\"smartctl\" path=\"/usr/sbin/smartctl\" dev=\"dm-1\" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1" +echo "type=AVC msg=audit(1525420698.433:331): avc: denied { sys_rawio } for pid=8678 comm=\"smartctl\" capability=17 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1" >>$tmp.avc -_audit "type=AVC msg=audit(1525420698.433:331): avc: denied { sys_rawio } for pid=8678 comm=\"smartctl\" capability=17 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1" +_audit $tmp.avc echo "============= pmda-redis ==============" -_audit "type=AVC msg=audit(1533183330.416:362367): avc: denied { name_connect } for pid=15299 comm=\"pmdaredis\" dest=6379 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:redis_port_t:s0 tclass=tcp_socket permissive=0" +rm -f $tmp.avc +echo "type=AVC msg=audit(1533183330.416:362367): avc: denied { name_connect } for pid=15299 comm=\"pmdaredis\" dest=6379 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:redis_port_t:s0 tclass=tcp_socket permissive=0" >>$tmp.avc + +_audit $tmp.avc # success, all done exit diff -Nru pcp-5.3.1/qa/1250.out pcp-5.3.2/qa/1250.out --- pcp-5.3.1/qa/1250.out 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1250.out 2021-06-15 01:03:49.000000000 +0000 @@ -1,109 +1,25 @@ QA output created by 1250 +Silence is golden ... all AVC's are allowed by active policy + ============= bogus AVC ... expect output ============== -type=AVC msg=audit(1484681301.812:174751): avc: denied { rmdir } for pid=21999 comm="foobar" name="foobar" dev="foobar" ino=1 scontext=system_u:object_r:etc_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=dir permissive=0 Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access. ============= init_t ============== -type=AVC msg=audit(1484681301.812:174751): avc: denied { read } for pid=21999 comm="pmcd" name="pmcd" dev="dm-1" ino=936441 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_log_t:s0 tclass=dir permissive=0 -type=AVC msg=audit(1484681301.810:174749): avc: denied { getattr } for pid=21999 comm="pmcd" path="/var/lib/pcp/pmns/root" dev="dm-1" ino=945382 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1484681301.810:174750): avc: denied { execute } for pid=21999 comm="pmcd" name="Rebuild" dev="dm-1" ino=937158 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1484681301.369:174692): avc: denied { open } for pid=21901 comm="pmcd" path="/var/tmp/pcp.sQReBLg6R/pcp.env.path" dev="dm-1" ino=930323 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0 -type=USER_AVC msg=audit(1535947021.608:238558): pid=775 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: denied { send_msg } for msgtype=method_return dest=:1.14778 spid=1 tpid=19555 scontext=system_u:system_r:init_t:s0 tcontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=81 hostname=? addr=? terminal=? ============= pcp_pmcd_t ============== -type=AVC msg=audit(1463754714.313:316): avc: denied { net_admin } for pid=2335 comm="pmcd" capability=12 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1 -type=AVC msg=audit(1491576442.619:1738169): avc: denied { sys_ptrace } for pid=15205 comm="pmdaproc" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0 -type=AVC msg=audit(1498833776.957:2094): avc: denied { ipc_owner } for pid=21341 comm="pmdalinux" capability=15 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0 -type=AVC msg=audit(1491581538.561:10949): avc: denied { getattr } for pid=9375 comm="pmdaproc" path="/run/systemd/initctl/fifo" dev="tmpfs" ino=13290 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:initctl_t:s0 tclass=fifo_file permissive=1 -type=AVC msg=audit(1491581538.587:10952): avc: denied { sys_ptrace } for pid=9375 comm="pmdaproc" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=cap_userns permissive=1 -type=AVC msg=audit(1485899863.032:3024): avc: denied { sys_chroot } for pid=25873 comm="pmdalinux" capability=18 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability -type=AVC msg=audit(1485899838.438:13213): avc: denied { read } for pid=29112 comm="pmdalinux" dev="nsfs" ino=4026532454 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:nsfs_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1498835003.745:8276): avc: denied { name_bind } for pid=7079 comm="pmdasimple" src=5650 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0 -type=AVC msg=audit(1499709840.120:5028): avc: denied { name_connect } for pid=13816 comm="python3" dest=9090 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:websm_port_t:s0 tclass=tcp_socket permissive=0 -type=AVC msg=audit(1498835613.883:11808): avc: denied { unix_read } for pid=14552 comm="pmdalinux" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=shm permissive=0 -type=AVC msg=audit(1498846768.313:12024): avc: denied { getattr associate } for pid=8128 comm="pmdalinux" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=shm permissive=0 -type=AVC msg=audit(1498843308.799:418): avc: denied { read } for pid=16668 comm="pmdalogger" name="458-16195.fifo" dev="tmpfs" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0 -type=AVC msg=audit(1498843308.800:420): avc: denied { getattr } for pid=16668 comm="pmdalogger" path="/tmp/458-16195.fifo" dev="tmpfs" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0 -type=AVC msg=audit(1498843308.800:419): avc: denied { open } for pid=16668 comm="pmdalogger" path="/tmp/458-16195.fifo" dev="tmpfs" ino=56008 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=fifo_file permissive=0 -type=AVC msg=audit(1498844147.316:3557): avc: denied { execute } for pid=8648 comm="sh" name="8641" dev="tmpfs" ino=246964 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498844147.316:3558): avc: denied { execute_no_trans } for pid=8648 comm="sh" path="/tmp/8641" dev="tmpfs" ino=246964 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498844147.327:3559): avc: denied { getattr } for pid=8656 comm="sh" path="/usr/bin/hostname" dev="dm-1" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498844147.327:3560): avc: denied { execute } for pid=8656 comm="sh" name="hostname" dev="dm-1" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498844147.327:3561): avc: denied { read } for pid=8656 comm="sh" name="hostname" dev="dm-1" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498844147.327:3562): avc: denied { open } for pid=8657 comm="sh" path="/usr/bin/hostname" dev="dm-1" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498844147.327:3563): avc: denied { execute_no_trans } for pid=8657 comm="sh" path="/usr/bin/hostname" dev="dm-1" ino=1051243 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498845911.359:7642): avc: denied { mount } for pid=22090 comm="pmdaperfevent" name="/" dev="tracefs" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=filesystem permissive=0 -type=AVC msg=audit(1498845911.360:7643): avc: denied { search } for pid=22090 comm="pmdaperfevent" name="/" dev="tracefs" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 -type=AVC msg=audit(1498845911.360:7644): avc: denied { read } for pid=22090 comm="pmdaperfevent" name="events" dev="tracefs" ino=176 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 -type=AVC msg=audit(1498845911.360:7645): avc: denied { open } for pid=22090 comm="pmdaperfevent" path="/sys/kernel/debug/tracing/events" dev="tracefs" ino=176 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 -type=AVC msg=audit(1498845911.360:7646): avc: denied { read } for pid=22090 comm="pmdaperfevent" name="id" dev="tracefs" ino=321619 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498845911.360:7647): avc: denied { open } for pid=22090 comm="pmdaperfevent" path="/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_state_change/id" dev="tracefs" ino=321619 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0 RHBZ1505888 -type=AVC msg=audit(1508779244.425:386): avc: denied { write } for pid=2967 comm="pmdaxfs" name="stats_clear" dev="proc" ino=87731 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sysctl_fs_t:s0 tclass=file -type=AVC msg=audit(...): avc: denied { getattr } for pid=NNN comm="pmdalinux" path="/var/lib/mock" dev="dm-1" ino=917749 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:mock_var_lib_t:s0 tclass=dir permissive=1 -type=AVC msg=audit(...): avc: denied { map } for pid=NNN comm="ldconfig" path="/usr/sbin/ldconfig" dev="dm-1" ino=1052382 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:ldconfig_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1519670939.873:2012): avc: denied { unix_read } for pid=1423 comm="pmdalinux" key=-559038737 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0 -type=AVC msg=audit(1519670949.871:2013): avc: denied { unix_read } for pid=1423 comm="pmdalinux" key=-559038737 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0 -type=AVC msg=audit(1530448398.992:231): avc: denied { read } for pid=16334 comm="python3" name="kallsyms" dev="proc" ino=4026532064 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:system_map_t:s0 tclass=file permissive=1 RHBZ1622253 -type=AVC msg=audit(1532540174.341:22480): avc: denied { search } for pid=25668 comm="perl" name="named" dev="dm-3" ino=2128175 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:named_zone_t:s0 tclass=dir RHBZ1619381 -type=AVC msg=audit(1534774142.552:48731): avc: denied { unix_read } for pid=1726 comm="pmdalinux" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:xdm_t:s0-s0:c0.c1023 tclass=shm permissive=0 -type=AVC msg=audit(...): avc: denied { connectto } for pid=NNN comm="python" path="/run/postgresql/.s.PGSQL.5432" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:postgresql_t:s0 tclass=unix_stream_socket RHBZ1535522 -type=AVC msg=audit(1538550792.679:11735): avc: denied { search } for pid=21371 comm="pmdalinux" name=".cache" dev="dm-0" ino=11796488 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:cache_home_t:s0 tclass=dir permissive=0 RHBZ1601721 -type=AVC msg=audit(1531806277.341:312): avc: denied { unix_read } for pid=2349 comm="pmdalinux" key=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:iscsid_t:s0 tclass=shm permissive=0 ============= pcp_pmlogger_t ============== -type=AVC msg=audit(1494326424.876:88): avc: denied { write } for pid=18266 comm="logger" name="log" dev="devtmpfs" ino=1413 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:devlog_t:s0 tclass=sock_file -type=AVC msg=audit(1498833990.644:5974): avc: denied { read } for pid=26849 comm="logger" name="log" dev="devtmpfs" ino=1389 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:devlog_t:s0 tclass=lnk_file permissive=0 -type=AVC msg=audit(1484681301.380:174695): avc: denied { sys_ptrace } for pid=21962 comm="ps" capability=19 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:system_r:pcp_pmlogger_t:s0 tclass=capability -type=AVC msg=audit(04/19/2017 16:57:40.120:11020) : avc: denied { signal } for pid=28414 comm=pmsignal scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process -type=AVC msg=audit(1503321970.417:261): avc: denied { execute_no_trans } for pid=6760 comm="pmlogger_check" path="/usr/bin/pmlogger" dev="dm-1" ino=1051023 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:pcp_pmlogger_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1493690261.688:262): avc: denied { name_connect } for pid=17604 comm="pmlc" dest=4330 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:dey_sapi_port_t:s0 tclass=tcp_socket -type=AVC msg=audit(1533291591.092:495620): avc: denied { connectto } for pid=18025 comm="pmprobe" path="/run/pcp/pmcd.socket" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 RHBZ1488116 -type=AVC msg=audit(1504516526.487:431): avc: denied { search } for pid=18056 comm="ps" name="testuser" dev="dm-0" ino=539096275 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir RHBZ1634205 -type=AVC msg=audit(1538179769.540:285): avc: denied { search } for pid=8613 comm="ps" name=".cache" dev="dm-0" ino=1277884 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:cache_home_t:s0 tclass=dir permissive=0 RHBZ1648602 -type=AVC msg=audit(1541890175.206:269): avc: denied { search } for pid=7835 comm="ps" name="lightdm" dev="sda1" ino=3145740 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:xserver_log_t:s0 tclass=dir permissive=0 ============= pcp_pmie_t ============== -type=AVC msg=audit(1498847682.537:15753): avc: denied { sys_ptrace } for pid=30881 comm="ps" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=capability permissive=0 -type=AVC msg=audit(04/05/2017 10:24:45.084:351) : avc: denied { connectto } for pid=8941 comm=systemctl path=/run/systemd/private scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=unix_stream_socket -type=AVC msg=audit(04/05/2017 10:24:45.081:348) : avc: denied { open } for pid=8939 comm=runlevel path=/run/utmp dev="tmpfs" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.081:348) : avc: denied { read } for pid=8939 comm=runlevel name=utmp dev="tmpfs" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.081:349) : avc: denied { lock } for pid=8939 comm=runlevel path=/run/utmp dev="tmpfs" ino=12392 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.082:350) : avc: denied { getattr } for pid=8870 comm=pmie path=/usr/lib/systemd/system/pmie.service dev="dm-1" ino=4203 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=file -type=AVC msg=audit(1498847677.050:15587): avc: denied { search } for pid=30181 comm="pmie" name="system" dev="dm-1" ino=1182241 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=dir permissive=0 -type=AVC msg=audit(04/05/2017 09:58:27.740:304) : avc: denied { read } for pid=7073 comm=pmie name=systemctl dev="dm-1" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 09:58:27.740:303) : avc: denied { execute } for pid=7073 comm=pmie name=systemctl dev="dm-1" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 09:58:27.742:305) : avc: denied { getattr } for pid=7004 comm=pmie path=/usr/lib/systemd/system/pmie.service dev="dm-1" ino=4203 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_unit_file_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.080:347) : avc: denied { execute_no_trans } for pid=8939 comm=pmie path=/usr/bin/systemctl dev="dm-1" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.080:347) : avc: denied { open } for pid=8939 comm=pmie path=/usr/bin/systemctl dev="dm-1" ino=3402 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file -type=AVC msg=audit(1498843991.020:2708): avc: denied { getattr } for pid=13079 comm="which" path="/usr/bin/systemctl" dev="dm-1" ino=1078205 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:systemd_systemctl_exec_t:s0 tclass=file permissive=0 -type=AVC msg=audit(1498836881.729:16279): avc: denied { connectto } for pid=12589 comm="pmie" path="/run/pcp/pmcd.socket" scontext=system_u:system_r:pcp_pmie_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 -audit: type=1400 audit(1504924094.677:197): avc: denied { execute_no_trans } for pid=3703 comm=pmie_check path=/usr/bin/pmie dev=dm-0 ino=2506240 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:pcp_pmie_exec_t:s0 tclass=file permissive=0 RHBZ1533080 -type=AVC msg=audit(...): avc: denied { open } for pid=NNN comm="runlevel" path="/dev/kmsg" dev="devtmpfs" ino=1043 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:kmsg_device_t:s0 tclass=chr_file permissive=1 RHBZ1623988 -type=AVC msg=audit(1535642748.855:3214): avc: denied { signal } for pid=3106 comm="pmsignal" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process permissive=1 RHBZ1635394 -type=AVC msg=audit(1538509480.147:87573): avc: denied { sys_ptrace } for pid=15683 comm="ps" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=cap_userns permissive=0 ============= pcp_pmproxy_t ============== -type=AVC msg=audit(04/05/2017 09:54:13.548:281) : avc: denied { net_admin } for pid=6669 comm=pmproxy capability=net_admin scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:system_r:pcp_pmproxy_t:s0 tclass=capability -type=AVC msg=audit(04/05/2017 09:54:13.548:281) : avc: denied { read } for pid=6669 comm=pmproxy name=disable_ipv6 dev="proc" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.771:356) : avc: denied { open } for pid=9669 comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev="proc" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file -type=AVC msg=audit(04/05/2017 10:24:45.771:357) : avc: denied { getattr } for pid=9669 comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev="proc" ino=9994 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file -type=AVC msg=audit(1498837089.845:16693): avc: denied { search } for pid=14446 comm="pmproxy" name="net" dev="proc" ino=1168 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=dir permissive=0 RHBZ1517656 -type=AVC msg=audit(1511771694.686:575): avc: denied { read } for pid=28833 comm="pmproxy" name="unix" dev="proc" ino=4026532015 scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:proc_net_t:s0 tclass=file ============= pmda-smart ============== -type=AVC msg=audit(1525420698.415:327): avc: denied { read } for pid=8678 comm="sh" name="smartctl" dev="dm-1" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1525420698.415:328): avc: denied { open } for pid=8678 comm="sh" path="/usr/sbin/smartctl" dev="dm-1" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1525420698.415:329): avc: denied { execute_no_trans } for pid=8678 comm="sh" path="/usr/sbin/smartctl" dev="dm-1" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1525420698.415:326): avc: denied { execute } for pid=8678 comm="sh" name="smartctl" dev="dm-1" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1525375355.243:3382): avc: denied { getattr } for pid=4770 comm="sh" path="/usr/sbin/smartctl" dev="dm-1" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1525420698.417:330): avc: denied { map } for pid=8678 comm="smartctl" path="/usr/sbin/smartctl" dev="dm-1" ino=2249815 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 -type=AVC msg=audit(1525420698.433:331): avc: denied { sys_rawio } for pid=8678 comm="smartctl" capability=17 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1 ============= pmda-redis ============== -type=AVC msg=audit(1533183330.416:362367): avc: denied { name_connect } for pid=15299 comm="pmdaredis" dest=6379 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:redis_port_t:s0 tclass=tcp_socket permissive=0 diff -Nru pcp-5.3.1/qa/1277 pcp-5.3.2/qa/1277 --- pcp-5.3.1/qa/1277 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1277 2021-07-30 04:05:06.000000000 +0000 @@ -49,11 +49,20 @@ } # real QA test starts here +# turn them on in pmdbg -l order pmdbg -l \ +| sed -e 1,2d \ | $PCP_AWK_PROG >$tmp.in ' -NR <= 2 { next} # skip 2 heading lines { print "debug " $1 print "status" + }' +# turn then off in reverse pmdbg -l order +pmdbg -l \ +| sed -e 1,2d \ +| tac \ +| $PCP_AWK_PROG >>$tmp.in ' + { print "debug -" $1 + print "status" all = all " " $1 } END { print "debug none" # clear all the flags diff -Nru pcp-5.3.1/qa/1277.out pcp-5.3.2/qa/1277.out --- pcp-5.3.1/qa/1277.out 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/1277.out 2021-07-30 04:05:06.000000000 +0000 @@ -173,13 +173,213 @@ Getiname: off dbpmda> debug compress dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress +Getiname: off +dbpmda> debug dev0 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 +Getiname: off +dbpmda> debug dev1 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 dev1 +Getiname: off +dbpmda> debug dev2 +dbpmda> status Debug options: (all) Getiname: off +dbpmda> debug -dev2 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 dev1 +Getiname: off +dbpmda> debug -dev1 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 +Getiname: off +dbpmda> debug -dev0 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress +Getiname: off +dbpmda> debug -compress +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query +Getiname: off +dbpmda> debug -query +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search +Getiname: off +dbpmda> debug -search +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa +Getiname: off +dbpmda> debug -qa +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access +Getiname: off +dbpmda> debug -access +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 +Getiname: off +dbpmda> debug -appl5 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 +Getiname: off +dbpmda> debug -appl4 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 +Getiname: off +dbpmda> debug -appl3 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services +Getiname: off +dbpmda> debug -services +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc +Getiname: off +dbpmda> debug -alloc +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb +Getiname: off +dbpmda> debug -libweb +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series +Getiname: off +dbpmda> debug -series +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels +Getiname: off +dbpmda> debug -labels +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec +Getiname: off +dbpmda> debug -exec +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated +Getiname: off +dbpmda> debug -deprecated +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate +Getiname: off +dbpmda> debug -desperate +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http +Getiname: off +dbpmda> debug -http +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr +Getiname: off +dbpmda> debug -attr +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery +Getiname: off +dbpmda> debug -discovery +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth +Getiname: off +dbpmda> debug -auth +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault +Getiname: off +dbpmda> debug -fault +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi +Getiname: off +dbpmda> debug -pmapi +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config +Getiname: off +dbpmda> debug -config +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp +Getiname: off +dbpmda> debug -interp +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock +Getiname: off +dbpmda> debug -lock +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive +Getiname: off +dbpmda> debug -derive +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc +Getiname: off +dbpmda> debug -pmc +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol +Getiname: off +dbpmda> debug -timecontrol +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda +Getiname: off +dbpmda> debug -libpmda +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns +Getiname: off +dbpmda> debug -pmns +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 +Getiname: off +dbpmda> debug -appl2 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 +Getiname: off +dbpmda> debug -appl1 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 +Getiname: off +dbpmda> debug -appl0 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af +Getiname: off +dbpmda> debug -af +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch +Getiname: off +dbpmda> debug -optfetch +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta +Getiname: off +dbpmda> debug -logmeta +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log +Getiname: off +dbpmda> debug -log +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf +Getiname: off +dbpmda> debug -pdubuf +dbpmda> status +Debug options: pdu fetch profile value context indom +Getiname: off +dbpmda> debug -indom +dbpmda> status +Debug options: pdu fetch profile value context +Getiname: off +dbpmda> debug -context +dbpmda> status +Debug options: pdu fetch profile value +Getiname: off +dbpmda> debug -value +dbpmda> status +Debug options: pdu fetch profile +Getiname: off +dbpmda> debug -profile +dbpmda> status +Debug options: pdu fetch +Getiname: off +dbpmda> debug -fetch +dbpmda> status +Debug options: pdu +Getiname: off +dbpmda> debug -pdu +dbpmda> status +Debug options: (none) +Getiname: off dbpmda> debug none dbpmda> status Debug options: (none) Getiname: off -dbpmda> debug pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress +dbpmda> debug dev2 dev1 dev0 compress query search qa access appl5 appl4 appl3 services alloc libweb series labels exec deprecated desperate http attr discovery auth fault pmapi config interp lock derive pmc timecontrol libpmda pmns appl2 appl1 appl0 af optfetch logmeta log pdubuf indom context value profile fetch pdu dbpmda> status Debug options: (all) Getiname: off diff -Nru pcp-5.3.1/qa/1278 pcp-5.3.2/qa/1278 --- pcp-5.3.1/qa/1278 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1278 2021-07-30 04:05:06.000000000 +0000 @@ -6,6 +6,7 @@ # # Copyright (c) 2020 Ken McDonell. All Rights Reserved. # +# check-group-include: dbpmda seq=`basename $0` echo "QA output created by $seq" diff -Nru pcp-5.3.1/qa/1278.out pcp-5.3.2/qa/1278.out --- pcp-5.3.1/qa/1278.out 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/1278.out 2021-07-30 04:05:06.000000000 +0000 @@ -175,13 +175,213 @@ Getiname: off dbpmda> debug compress dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress +Getiname: off +dbpmda> debug dev0 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 +Getiname: off +dbpmda> debug dev1 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 dev1 +Getiname: off +dbpmda> debug dev2 +dbpmda> status Debug options: (all) Getiname: off +dbpmda> debug -dev2 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 dev1 +Getiname: off +dbpmda> debug -dev1 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress dev0 +Getiname: off +dbpmda> debug -dev0 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress +Getiname: off +dbpmda> debug -compress +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query +Getiname: off +dbpmda> debug -query +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search +Getiname: off +dbpmda> debug -search +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa +Getiname: off +dbpmda> debug -qa +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access +Getiname: off +dbpmda> debug -access +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 +Getiname: off +dbpmda> debug -appl5 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 +Getiname: off +dbpmda> debug -appl4 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 +Getiname: off +dbpmda> debug -appl3 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services +Getiname: off +dbpmda> debug -services +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc +Getiname: off +dbpmda> debug -alloc +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb +Getiname: off +dbpmda> debug -libweb +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series +Getiname: off +dbpmda> debug -series +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels +Getiname: off +dbpmda> debug -labels +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec +Getiname: off +dbpmda> debug -exec +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated +Getiname: off +dbpmda> debug -deprecated +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate +Getiname: off +dbpmda> debug -desperate +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http +Getiname: off +dbpmda> debug -http +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr +Getiname: off +dbpmda> debug -attr +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery +Getiname: off +dbpmda> debug -discovery +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth +Getiname: off +dbpmda> debug -auth +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault +Getiname: off +dbpmda> debug -fault +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi +Getiname: off +dbpmda> debug -pmapi +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config +Getiname: off +dbpmda> debug -config +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp +Getiname: off +dbpmda> debug -interp +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock +Getiname: off +dbpmda> debug -lock +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive +Getiname: off +dbpmda> debug -derive +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc +Getiname: off +dbpmda> debug -pmc +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol +Getiname: off +dbpmda> debug -timecontrol +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda +Getiname: off +dbpmda> debug -libpmda +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns +Getiname: off +dbpmda> debug -pmns +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 +Getiname: off +dbpmda> debug -appl2 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 +Getiname: off +dbpmda> debug -appl1 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 +Getiname: off +dbpmda> debug -appl0 +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch af +Getiname: off +dbpmda> debug -af +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta optfetch +Getiname: off +dbpmda> debug -optfetch +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log logmeta +Getiname: off +dbpmda> debug -logmeta +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf log +Getiname: off +dbpmda> debug -log +dbpmda> status +Debug options: pdu fetch profile value context indom pdubuf +Getiname: off +dbpmda> debug -pdubuf +dbpmda> status +Debug options: pdu fetch profile value context indom +Getiname: off +dbpmda> debug -indom +dbpmda> status +Debug options: pdu fetch profile value context +Getiname: off +dbpmda> debug -context +dbpmda> status +Debug options: pdu fetch profile value +Getiname: off +dbpmda> debug -value +dbpmda> status +Debug options: pdu fetch profile +Getiname: off +dbpmda> debug -profile +dbpmda> status +Debug options: pdu fetch +Getiname: off +dbpmda> debug -fetch +dbpmda> status +Debug options: pdu +Getiname: off +dbpmda> debug -pdu +dbpmda> status +Debug options: (none) +Getiname: off dbpmda> debug none dbpmda> status Debug options: (none) Getiname: off -dbpmda> debug pdu fetch profile value context indom pdubuf log logmeta optfetch af appl0 appl1 appl2 pmns libpmda timecontrol pmc derive lock interp config pmapi fault auth discovery attr http desperate deprecated exec labels series libweb alloc services appl3 appl4 appl5 access qa search query compress +dbpmda> debug dev2 dev1 dev0 compress query search qa access appl5 appl4 appl3 services alloc libweb series labels exec deprecated desperate http attr discovery auth fault pmapi config interp lock derive pmc timecontrol libpmda pmns appl2 appl1 appl0 af optfetch logmeta log pdubuf indom context value profile fetch pdu dbpmda> status Debug options: (all) Getiname: off diff -Nru pcp-5.3.1/qa/1279 pcp-5.3.2/qa/1279 --- pcp-5.3.1/qa/1279 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1279 2021-07-30 04:05:06.000000000 +0000 @@ -6,6 +6,7 @@ # # Copyright (c) 2020 Ken McDonell. All Rights Reserved. # +# check-group-include: dbpmda seq=`basename $0` echo "QA output created by $seq" diff -Nru pcp-5.3.1/qa/1279.out pcp-5.3.2/qa/1279.out --- pcp-5.3.1/qa/1279.out 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/1279.out 2021-07-30 04:05:06.000000000 +0000 @@ -9,7 +9,7 @@ children metric-name close debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) desc metric fetch metric [ metric ... ] getdesc on | off @@ -56,11 +56,11 @@ dbpmda> #test the debug and status commands dbpmda> debug# a command with a trailing comment debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) dbpmda> help debug debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) Specify which debugging options should be active (see pmdbg(1)). Options may be specified by name (or number for the old bit-field options), with diff -Nru pcp-5.3.1/qa/1284 pcp-5.3.2/qa/1284 --- pcp-5.3.1/qa/1284 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1284 2021-06-15 01:03:49.000000000 +0000 @@ -21,6 +21,7 @@ . ./common.check [ $PCP_PLATFORM = linux ] || _notrun "Linux PMDA waitio testing" +which pmrep >/dev/null 2>&1 || _notrun "no pmrep executable" _cleanup() { diff -Nru pcp-5.3.1/qa/1286 pcp-5.3.2/qa/1286 --- pcp-5.3.1/qa/1286 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1286 2021-07-30 04:05:06.000000000 +0000 @@ -18,6 +18,28 @@ signal=$PCP_BINADM_DIR/pmsignal $sudo rm -rf $tmp.* $seq.full +# Some combinations of distro and kernel are known to be "bad" +# for some BPF modules +# +kernel=`uname -r` +echo "$kernel" >>$seq.full +case `admin/whatami` +in + *Fedora\ 32\ *) + _notrun "bcc netproc module will not compile on Fedora 32" + ;; + *Ubuntu\ 20.04\ *) + # works on 5.4 kernel, not on 5.8.0-1033-azure + # + case "$kernel" + in + 5.8.0-*-azure) + _notrun "bcc netproc module will not compile on Ubuntu kernel $kernel" + ;; + esac + ;; +esac + # The netproc BCC module uses the lookup_or_try_init() method that was # introduced in bcc v0.12.0 (released 11 Dec 2019), so determine the # bcc version and _notrun as appropriate. diff -Nru pcp-5.3.1/qa/1304 pcp-5.3.2/qa/1304 --- pcp-5.3.1/qa/1304 2018-05-11 02:15:55.000000000 +0000 +++ pcp-5.3.2/qa/1304 2021-07-30 04:05:06.000000000 +0000 @@ -17,6 +17,7 @@ { cd $here _service pmcd restart 2>&1 | _filter_pcp_start + _wait_for_pmcd _restore_auto_restart pmcd $sudo rm -rf $tmp $tmp.* } @@ -28,6 +29,7 @@ # real QA test starts here _stop_auto_restart pmcd _service pmcd stop 2>&1 | _filter_pcp_stop +_wait_pmcd_end echo "Running pmstat in local context fallback mode" pmstat --interval 0.2 --samples 3 >$tmp.out 2>$tmp.err diff -Nru pcp-5.3.1/qa/1308 pcp-5.3.2/qa/1308 --- pcp-5.3.1/qa/1308 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/1308 2021-07-30 04:05:06.000000000 +0000 @@ -6,6 +6,7 @@ # # Copyright (c) 2021 Ken McDonell. All Rights Reserved. # +# check-group-include: dbpmda if [ $# -eq 0 ] then diff -Nru pcp-5.3.1/qa/1328 pcp-5.3.2/qa/1328 --- pcp-5.3.1/qa/1328 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1328 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,64 @@ +#!/bin/sh +# PCP QA Test No. 1328 +# Exercise pmcd.zoneinfo +# +# Copyright (c) 2021 Ken McDonell. All Rights Reserved. +# + +if [ $# -eq 0 ] +then + seq=`basename $0` + echo "QA output created by $seq" +else + # use $seq from caller, unless not set + [ -n "$seq" ] || seq=`basename $0` + echo "QA output created by `basename $0` $*" +fi + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# real QA test starts here +zoneinfo=`pminfo -f pmcd.zoneinfo | sed -n -e '/^ *value /{ +s/// +s/"//g +p +}'` +if [ -z "$zoneinfo" ] +then + echo "no value for pmcd.zoneinfo ..." + pminfo -f pmcd.zoneinfo +fi + +# need to be careful of clock ticking over, so try up to 3 times with +# 100 msec delay between each try +# +for try in 1 2 3 +do + raw=`date '+%y/%m/%d %H:%M:%S'` + cooked=`TZ=$zoneinfo date '+%y/%m/%d %H:%M:%S'` + echo "raw=$raw" >>$seq.full + echo "cooked=$cooked (TZ=$zoneinfo)" >>$seq.full + if [ "$raw" = "$cooked" ] + then + echo "Dates match." + # success + exit + fi + pmsleep 0.1 +done + +echo "Failed to match $raw vs (TZ=$zoneinfo) $cooked" +exit diff -Nru pcp-5.3.1/qa/1328.out pcp-5.3.2/qa/1328.out --- pcp-5.3.1/qa/1328.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1328.out 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,2 @@ +QA output created by 1328 +Dates match. diff -Nru pcp-5.3.1/qa/1329 pcp-5.3.2/qa/1329 --- pcp-5.3.1/qa/1329 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1329 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,63 @@ +#!/bin/sh +# PCP QA Test No. 1329 +# Check all code paths for help text where only one-line is available +# using the mmv PMDA (this one is "special" because the help text +# comes from the mmv file, not a newhelp(1) file. +# +# Copyright (c) 2021 Ken McDonell. All Rights Reserved. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* + $sudo rm -f "$PCP_TMP_DIR"/mmv/qa +} + +if [ -f "$PCP_TMP_DIR"/mmv/qa ] +then + _notrun "$PCP_TMP_DIR/mmv/qa already exists" +fi + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +export PCP_DERIVED_CONFIG= +export LC_COLLATE=POSIX + +$sudo src/mmv_help qa + +# real QA test starts here +echo "=== live PMDA case ===" +for metric in `pminfo mmv.qa | sort` +do + pminfo -tT "$metric" +done + +echo +echo "=== archive case ===" +for metric in `pminfo mmv.qa | sort` +do + pminfo -tT -a archives/mmv.help "$metric" +done + +echo +echo "=== local context case ===" +domain=70 +pmda=$PCP_PMDAS_DIR/mmv/pmda_mmv.so,mmv_init +for metric in `pminfo mmv.qa | sort` +do + pminfo -tT -L -K clear -K add,$domain,$pmda "$metric" +done + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1329.out pcp-5.3.2/qa/1329.out --- pcp-5.3.1/qa/1329.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1329.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,96 @@ +QA output created by 1329 +=== live PMDA case === + +mmv.qa.both [foo] +Help: +bar + +mmv.qa.both_empty [] +Help: + +mmv.qa.help_empty [foobar] +Help: +foobar + +mmv.qa.nohelp One-line Help: Error: One-line or help text is not available +Full Help: Error: One-line or help text is not available + +mmv.qa.oneline [oneline] +Help: +oneline + +mmv.qa.verbose [wordy] +Help: +One, two, three, four, five, +Once I caught a fish alive, +Six, seven, eight, nine, ten, +Then I let go again. + +Why did you let it go? +Because it bit my finger so. +Which finger did it bite? +This little finger on the right + +=== archive case === + +mmv.qa.both [foo] +Help: +bar + +mmv.qa.both_empty [] +Help: + +mmv.qa.help_empty [foobar] +Help: +foobar + +mmv.qa.nohelp One-line Help: Error: One-line or help text is not available +Full Help: Error: One-line or help text is not available + +mmv.qa.oneline [oneline] +Help: +oneline + +mmv.qa.verbose [wordy] +Help: +One, two, three, four, five, +Once I caught a fish alive, +Six, seven, eight, nine, ten, +Then I let go again. + +Why did you let it go? +Because it bit my finger so. +Which finger did it bite? +This little finger on the right + +=== local context case === + +mmv.qa.both [foo] +Help: +bar + +mmv.qa.both_empty [] +Help: + +mmv.qa.help_empty [foobar] +Help: +foobar + +mmv.qa.nohelp One-line Help: Error: One-line or help text is not available +Full Help: Error: One-line or help text is not available + +mmv.qa.oneline [oneline] +Help: +oneline + +mmv.qa.verbose [wordy] +Help: +One, two, three, four, five, +Once I caught a fish alive, +Six, seven, eight, nine, ten, +Then I let go again. + +Why did you let it go? +Because it bit my finger so. +Which finger did it bite? +This little finger on the right diff -Nru pcp-5.3.1/qa/1332 pcp-5.3.2/qa/1332 --- pcp-5.3.1/qa/1332 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1332 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,72 @@ +#!/bin/sh +# PCP QA Test No. 1332 +# pmdumplog -I/--on-disk-insts +# non-valgrind variant, see qa/1333 for the valgrind variant +# +# Copyright (c) 2021 Ken McDonell. All Rights Reserved. +# + +if [ $# -eq 0 ] +then + seq=`basename $0` + echo "QA output created by $seq" +else + # use $seq from caller, unless not set + [ -n "$seq" ] || seq=`basename $0` + echo "QA output created by `basename $0` $*" +fi + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +do_valgrind=false +if [ "$1" = "--valgrind" ] +then + _check_valgrind + do_valgrind=true +fi + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_filter() +{ + sed \ + -e "s@$tmp@TMP@g" \ + # end +} + +# real QA test starts here +pmdumplog -z --insts archives/ok-foo >$tmp.loaded + +if $do_valgrind +then + _run_valgrind pmdumplog -z -I archives/ok-foo 2>&1 +else + pmdumplog -z --on-disk-insts archives/ok-foo 2>&1 +fi \ +| $PCP_AWK_PROG ' +BEGIN { state = 1 } +/^=== filtered/ { state = 0 } +/^=== std out/ { print; state = 1; next } +/^=== std err/ { print; next } +state == 0 { print } +state == 1 { print >"'$tmp.tmp'" }' +mv $tmp.tmp $tmp.ondisk + +export LC_COLLATE=POSIX +sort $tmp.loaded >$tmp.loaded.sort +sort $tmp.ondisk >$tmp.ondisk.sort +diff $tmp.loaded.sort $tmp.ondisk.sort | _filter + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1332.out pcp-5.3.2/qa/1332.out --- pcp-5.3.1/qa/1332.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1332.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,14 @@ +QA output created by 1332 +16,22c16,19 +< 04:34:32.257504 1 instances +< 04:34:33.248687 3 instances +< 04:34:33.248687 9 instances +< InDom: 2.1 +< InDom: 29.1 +< InDom: 29.2 +< Instance Domains in the Log ... +--- +> 04:34:32.257504 InDom: 2.1 1 instances +> 04:34:33.248687 InDom: 29.1 3 instances +> 04:34:33.248687 InDom: 29.2 9 instances +> Instance Domains on-disk ... diff -Nru pcp-5.3.1/qa/1333 pcp-5.3.2/qa/1333 --- pcp-5.3.1/qa/1333 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1333 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,38 @@ +#!/bin/sh +# PCP QA Test No. 1333 +# pmdumplog -I +# valgrind variant, see qa/1332 for the non-valgrind variant +# +# Copyright (c) 2021 Ken McDonell. All Rights Reserved. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +_check_valgrind + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# real QA test starts here +export seq +./1332 --valgrind | $PCP_AWK_PROG ' +skip == 1 && $1 == "===" { skip = 0 } +/^=== std err ===/ { skip = 1 } +skip == 0 { print } +skip == 1 { print >>"'$here/$seq.full'" }' + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1333.out pcp-5.3.2/qa/1333.out --- pcp-5.3.1/qa/1333.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1333.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,23 @@ +QA output created by 1333 +QA output created by 1332 --valgrind +=== std out === +=== filtered valgrind report === +Memcheck, a memory error detector +Command: pmdumplog -z -I archives/ok-foo +LEAK SUMMARY: +definitely lost: 0 bytes in 0 blocks +indirectly lost: 0 bytes in 0 blocks +ERROR SUMMARY: 0 errors from 0 contexts ... +16,22c16,19 +< 04:34:32.257504 1 instances +< 04:34:33.248687 3 instances +< 04:34:33.248687 9 instances +< InDom: 2.1 +< InDom: 29.1 +< InDom: 29.2 +< Instance Domains in the Log ... +--- +> 04:34:32.257504 InDom: 2.1 1 instances +> 04:34:33.248687 InDom: 29.1 3 instances +> 04:34:33.248687 InDom: 29.2 9 instances +> Instance Domains on-disk ... diff -Nru pcp-5.3.1/qa/134 pcp-5.3.2/qa/134 --- pcp-5.3.1/qa/134 2018-02-13 04:56:52.000000000 +0000 +++ pcp-5.3.2/qa/134 2021-07-30 04:05:06.000000000 +0000 @@ -36,9 +36,15 @@ else { # change is not deterministic, due to epilogue # record size + # was truncated to 100 byte boundaries, but + # hostnames like + # fv-az121-446.xhy4bhhdincepo0av04agjzkjc.cx.internal.cloudapp.net + # in CI broke that, so go to 400 byte boundary + # truncation # - h = int(($2 - l1) / 100) - print $1,"incr",h*100 "-" (h+1)*100,"bytes" + chunk = 400 + h = int(($2 - l1) / chunk) + print $1,"incr",h*chunk "-" (h+1)*chunk,"bytes" } l1=$2 next diff -Nru pcp-5.3.1/qa/134.out pcp-5.3.2/qa/134.out --- pcp-5.3.1/qa/134.out 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/134.out 2021-07-30 04:05:06.000000000 +0000 @@ -59,7 +59,7 @@ === second volume, one result === MYLOG.0 unchanged -MYLOG.1 incr 0-100 bytes +MYLOG.1 incr 0-400 bytes Log Label (Log Format Version 2) Performance metrics from host LOCALHOST commencing month-day TIMESTAMP-0 year @@ -81,7 +81,7 @@ === second volume, second + third result === MYLOG.0 unchanged -MYLOG.1 incr 100-200 bytes +MYLOG.1 incr 0-400 bytes Log Label (Log Format Version 2) Performance metrics from host LOCALHOST commencing month-day TIMESTAMP-0 year @@ -108,7 +108,7 @@ === logger done === MYLOG.0 unchanged -MYLOG.1 incr 100-200 bytes +MYLOG.1 incr 0-400 bytes Log Label (Log Format Version 2) Performance metrics from host LOCALHOST commencing month-day TIMESTAMP-0 year diff -Nru pcp-5.3.1/qa/1359.out pcp-5.3.2/qa/1359.out --- pcp-5.3.1/qa/1359.out 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/1359.out 2021-07-30 04:05:06.000000000 +0000 @@ -59,14 +59,14 @@ arg: all pmSetDebug("all") ... pmDebug: pdu,fetch,profile,value,context,indom,pdubuf,log,logmeta,optfetch,af,appl0,appl1,appl2,pmns,libpmda,timecontrol,pmc,derive,lock,interp,config,pmapi,fault,auth,discovery,attr,http,desperate -pmDebugOptions: pdu,fetch,profile,value,context,indom,pdubuf,log,logmeta,optfetch,af,appl0,appl1,appl2,pmns,libpmda,timecontrol,pmc,derive,lock,interp,config,pmapi,fault,auth,discovery,attr,http,desperate,deprecated,exec,labels,series,libweb,alloc,services,appl3,appl4,appl5,access,qa,search,query,compress +pmDebugOptions: pdu,fetch,profile,value,context,indom,pdubuf,log,logmeta,optfetch,af,appl0,appl1,appl2,pmns,libpmda,timecontrol,pmc,derive,lock,interp,config,pmapi,fault,auth,discovery,attr,http,desperate,deprecated,exec,labels,series,libweb,alloc,services,appl3,appl4,appl5,access,qa,search,query,compress,dev0,dev1,dev2 pmClearDebug("all") ... pmDebug: Nothing set pmDebugOptions: Nothing set __pmParseDebug("all") ... __pmParseDebug -> 2147483647 pmDebug: pdu,fetch,profile,value,context,indom,pdubuf,log,logmeta,optfetch,af,appl0,appl1,appl2,pmns,libpmda,timecontrol,pmc,derive,lock,interp,config,pmapi,fault,auth,discovery,attr,http,desperate -pmDebugOptions: pdu,fetch,profile,value,context,indom,pdubuf,log,logmeta,optfetch,af,appl0,appl1,appl2,pmns,libpmda,timecontrol,pmc,derive,lock,interp,config,pmapi,fault,auth,discovery,attr,http,desperate,deprecated,exec,labels,series,libweb,alloc,services,appl3,appl4,appl5,access,qa,search,query,compress +pmDebugOptions: pdu,fetch,profile,value,context,indom,pdubuf,log,logmeta,optfetch,af,appl0,appl1,appl2,pmns,libpmda,timecontrol,pmc,derive,lock,interp,config,pmapi,fault,auth,discovery,attr,http,desperate,deprecated,exec,labels,series,libweb,alloc,services,appl3,appl4,appl5,access,qa,search,query,compress,dev0,dev1,dev2 pmClearDebug("all") ... pmDebug: Nothing set pmDebugOptions: Nothing set diff -Nru pcp-5.3.1/qa/1370 pcp-5.3.2/qa/1370 --- pcp-5.3.1/qa/1370 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/1370 2021-07-30 04:05:06.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/sh +#!/bin/sh # PCP QA Test No. 1370 # Check long-options in manual pages. # @@ -13,9 +13,6 @@ . ./common.filter . ./common.check -[ -f /etc/os-release ] || _notrun "Tested only on Fedora" -grep -q ^NAME=Fedora /etc/os-release || _notrun "Tested only on Fedora" - which man > /dev/null 2>&1 || _notrun "No man(1) command?" man pmrep | grep -q pmrep || _notrun "No man pages installed?" @@ -26,28 +23,121 @@ # real QA test starts here echo "collecting commands" -rpm -qa | grep pcp | xargs rpm -ql | grep bin/ | sort > $tmp.cmds.txt - -echo "removing problematic commands from test" +export LC_COLLATE=POSIX +# need to check dpkg first, because if it is there, it is likely the +# one, as opposed to rpm which may be present, even on Debian machines +# +if which dpkg >/dev/null 2>&1 +then + dpkg -l | $PCP_AWK_PROG '$1 = "ii" && $2 ~ /pcp/ { print $2 }' | xargs dpkg -L | grep bin/ | sort | uniq > $tmp.cmds.txt +elif which rpm >/dev/null 2>&1 +then + rpm -qa | grep pcp | xargs rpm -ql | grep bin/ | grep -v 'debug$' | sort > $tmp.cmds.txt +else + _notrun "no recipe for your packaging command" +fi + +# don't bother for some commands, either they don't support --help +# (e.g. no options to describe) and/or are not intended for general +# use by a human end user +# for cmd in pcp-htop pcp-python pcp2csv pcp2xlsx pmafm pmgenmap \ pmie_dump_stats pmiestatus pmlock pmpause pmpython \ - pmsleep pmwtf telnet-probe; do + pmsleep pmwtf telnet-probe pmpost pcp-kube-pods +do sed -i "/$cmd/d" $tmp.cmds.txt done -echo "display commands to be tested" -cat $tmp.cmds.txt +ncmd=`wc -l <$tmp.cmds.txt | sed -e 's/ *//'` +if [ "$ncmd" -lt 100 ] +then + echo "Warning: only found $ncmd candidate installed commands, expecting at least 100" +fi + +# borrowed from _check_display() +# if we can't talk to an X server, there is no point running +# --help for the GUI apps +# +X11=true +if [ -z "$PCPQA_CLOSE_X_SERVER" ] +then + X11=false +fi +which xdpyinfo >/dev/null 2>&1 +if [ $? -eq 0 ] +then + DISPLAY=$PCPQA_CLOSE_X_SERVER xdpyinfo >/dev/null 2>&1 || \ + X11=false +fi + +export PCP_STDERR=$tmp.popup echo "run checks" for cmd in $(cat $tmp.cmds.txt); do rm -f $tmp.test bn=$(basename $cmd) - $cmd --help 2>&1 | grep -Eo -- '--.* ' | sed -e 's/=.*//g' -e 's/ .*//g' -e 's/]//g' | grep -e '-[A-Za-z]' > $tmp.test + rm -f $tmp.popup + if ! $X11 + then + case $cmd + in + */pmchart|*/pmtime|*/pmconfirm|*/pmquery|*/pmclient_fg|*/pmmessage) + # for these ones --help will try to open a GUI popup or + # at least start an X11 client setup and without an X11 + # server that ain't going to work + # + continue + ;; + esac + fi + $cmd --help >$tmp.out 2>$tmp.err + [ -f $tmp.popup ] && cat $tmp.popup >>$tmp.err + # if --help is not understood, usually get the "unrecognized + # option" message, followed by the usage message + # + cat $tmp.out $tmp.err | grep 'unrecognized option' + cat $tmp.out $tmp.err \ + | grep -Eo -- '--.*( | |$)' \ + | sed \ + -e '/unrecognized option/d' \ + -e 's/=.*//g' \ + -e 's/[ ].*//g' \ + -e 's/]//g' \ + -e 's/)//g' \ + | LC_COLLATE=POSIX sort \ + | uniq \ + | grep -e '-[A-Za-z]' > $tmp.test if ! grep -q -- -- $tmp.test; then continue fi + echo "=== $cmd ===" >>$seq.full + cat $tmp.test >>$seq.full + # run man(1) once, then grep away + man $bn >$tmp.man for opt in $(cat $tmp.test); do - man $bn | grep -q -- "$opt" || echo "$bn.1 missing $opt" + # some --help text is misleading, not really options following + # -- ... skip 'em + case "$bn" + in + pcp-atop) + [ X"$opt" = X--pcp-flags ] && continue + ;; + pcp) + # all these long options are documented in PCPIntro(1) + # and pcp(1) points there, rather than repeating them + # + [ X"$opt" = X--align ] && continue + [ X"$opt" = X--finish ] && continue + [ X"$opt" = X--guimode ] && continue + [ X"$opt" = X--guiport ] && continue + [ X"$opt" = X--hostzone ] && continue + [ X"$opt" = X--interval ] && continue + [ X"$opt" = X--samples ] && continue + [ X"$opt" = X--start ] && continue + [ X"$opt" = X--timezone ] && continue + ;; + esac + grep -q -- "$opt" <$tmp.man || echo "$bn.1 missing $opt" done rm -f $tmp.test done diff -Nru pcp-5.3.1/qa/1370.out pcp-5.3.2/qa/1370.out --- pcp-5.3.1/qa/1370.out 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1370.out 2021-07-30 04:05:06.000000000 +0000 @@ -1,140 +1,4 @@ QA output created by 1370 collecting commands -removing problematic commands from test -display commands to be tested -/usr/bin/dbpmda -/usr/bin/dstat -/usr/bin/genpmda -/usr/bin/pcp -/usr/bin/pcp2elasticsearch -/usr/bin/pcp2graphite -/usr/bin/pcp2influxdb -/usr/bin/pcp2json -/usr/bin/pcp2spark -/usr/bin/pcp2xml -/usr/bin/pcp2zabbix -/usr/bin/pmclient -/usr/bin/pmclient_fg -/usr/bin/pmdate -/usr/bin/pmdbg -/usr/bin/pmdiff -/usr/bin/pmdumplog -/usr/bin/pmerr -/usr/bin/pmevent -/usr/bin/pmfind -/usr/bin/pmie -/usr/bin/pmie2col -/usr/bin/pmieconf -/usr/bin/pmiectl -/usr/bin/pminfo -/usr/bin/pmiostat -/usr/bin/pmjson -/usr/bin/pmlc -/usr/bin/pmlogcheck -/usr/bin/pmlogconf -/usr/bin/pmlogctl -/usr/bin/pmlogextract -/usr/bin/pmlogger -/usr/bin/pmloglabel -/usr/bin/pmlogmv -/usr/bin/pmlogpaste -/usr/bin/pmlogsize -/usr/bin/pmlogsummary -/usr/bin/pmprobe -/usr/bin/pmrep -/usr/bin/pmrepconf -/usr/bin/pmsearch -/usr/bin/pmseries -/usr/bin/pmsocks -/usr/bin/pmstat -/usr/bin/pmstore -/usr/bin/pmtrace -/usr/bin/pmval -/usr/libexec/pcp/bin/chkhelp -/usr/libexec/pcp/bin/discover -/usr/libexec/pcp/bin/discover/pcp-kube-pods -/usr/libexec/pcp/bin/find-filter -/usr/libexec/pcp/bin/install-sh -/usr/libexec/pcp/bin/mkaf -/usr/libexec/pcp/bin/newhelp -/usr/libexec/pcp/bin/pcp-atop -/usr/libexec/pcp/bin/pcp-atopsar -/usr/libexec/pcp/bin/pcp-dmcache -/usr/libexec/pcp/bin/pcp-dstat -/usr/libexec/pcp/bin/pcp-free -/usr/libexec/pcp/bin/pcp-iostat -/usr/libexec/pcp/bin/pcp-ipcs -/usr/libexec/pcp/bin/pcp-lvmcache -/usr/libexec/pcp/bin/pcp-mpstat -/usr/libexec/pcp/bin/pcp-numastat -/usr/libexec/pcp/bin/pcp-pidstat -/usr/libexec/pcp/bin/pcp-shping -/usr/libexec/pcp/bin/pcp-summary -/usr/libexec/pcp/bin/pcp-tapestat -/usr/libexec/pcp/bin/pcp-uptime -/usr/libexec/pcp/bin/pcp-verify -/usr/libexec/pcp/bin/pcp-vmstat -/usr/libexec/pcp/bin/pmcd -/usr/libexec/pcp/bin/pmcd_wait -/usr/libexec/pcp/bin/pmconfig -/usr/libexec/pcp/bin/pmcpp -/usr/libexec/pcp/bin/pmfind_check -/usr/libexec/pcp/bin/pmgetopt -/usr/libexec/pcp/bin/pmhostname -/usr/libexec/pcp/bin/pmie_check -/usr/libexec/pcp/bin/pmie_daily -/usr/libexec/pcp/bin/pmie_email -/usr/libexec/pcp/bin/pmlogconf -/usr/libexec/pcp/bin/pmlogextract -/usr/libexec/pcp/bin/pmlogger -/usr/libexec/pcp/bin/pmlogger_check -/usr/libexec/pcp/bin/pmlogger_daily -/usr/libexec/pcp/bin/pmlogger_merge -/usr/libexec/pcp/bin/pmlogger_rewrite -/usr/libexec/pcp/bin/pmlogreduce -/usr/libexec/pcp/bin/pmlogrewrite -/usr/libexec/pcp/bin/pmnewlog -/usr/libexec/pcp/bin/pmnsadd -/usr/libexec/pcp/bin/pmnsdel -/usr/libexec/pcp/bin/pmnsmerge -/usr/libexec/pcp/bin/pmpost -/usr/libexec/pcp/bin/pmproxy -/usr/libexec/pcp/bin/pmsignal -/usr/libexec/pcp/bin/selinux-setup run checks -dstat.1 missing --profile -pcp.1 missing --align -pcp.1 missing --guimode -pcp.1 missing --guiport -pcp.1 missing --start -pcp.1 missing --samples -pcp.1 missing --timezone -pcp.1 missing --hostzone -pmclient.1 missing --guimode -pmclient.1 missing --guiport -pmclient_fg.1 missing --guimode -pmclient_fg.1 missing --guiport -pmiostat.1 missing --align -pmiostat.1 missing --start -pmiostat.1 missing --version -pmiostat.1 missing --hostzone -pcp-atop.1 missing --pcp-flags -pcp-atop.1 missing --align -pcp-atop.1 missing --start -pcp-atop.1 missing --finish -pcp-atop.1 missing --hostzone -pcp-atop.1 missing --version -pcp-atopsar.1 missing display -pcp-dstat.1 missing --profile -pcp-iostat.1 missing --align -pcp-iostat.1 missing --start -pcp-iostat.1 missing --version -pcp-iostat.1 missing --hostzone -pcp-tapestat.1 missing --align -pcp-tapestat.1 missing --start -pcp-tapestat.1 missing --version -pcp-tapestat.1 missing --hostzone -pmlogger_rewrite.1 missing --desperate -pmlogger_rewrite.1 missing --scale -pmlogger_rewrite.1 missing --warnings checks done diff -Nru pcp-5.3.1/qa/1415.out pcp-5.3.2/qa/1415.out --- pcp-5.3.1/qa/1415.out 2020-05-28 23:27:15.000000000 +0000 +++ pcp-5.3.2/qa/1415.out 2021-07-30 04:05:06.000000000 +0000 @@ -48,13 +48,15 @@ units=count (no indom) shorttext=test counter metric - helptext=Yes, this is a test counter metric + helptext=Yes +This is a test counter metric [2/688] discrete type=32-bit int (0x0), sem=discrete (0x4), pad=0x0 units= (no indom) shorttext=test discrete metric - helptext=Yes, this is a test discrete metric + helptext=Yes +This is a test discrete metric [3/792] indom type=32-bit unsigned int (0x1), sem=instant (0x3), pad=0x0 units=count @@ -78,7 +80,8 @@ units= indom=1 shorttext=test string metrics - helptext=Yes, this is a test string metric with instances + helptext=Yes +This is a test string metric with instances TOC[3]: offset 88, values offset 1208 (10 entries) [1/1208] counter = 41 @@ -97,11 +100,14 @@ [2/1784] 00oo00 [3/2040] [4/2296] test counter metric - [5/2552] Yes, this is a test counter metric + [5/2552] Yes +This is a test counter metric [6/2808] test discrete metric - [7/3064] Yes, this is a test discrete metric + [7/3064] Yes +This is a test discrete metric [8/3320] test string metrics - [9/3576] Yes, this is a test string metric with instances + [9/3576] Yes +This is a test string metric with instances [10/3832] We can be heroes [11/4088] We can be heroes, just for one day MMV file = $PCP_TMP_DIR/mmv/notest-PID @@ -173,13 +179,15 @@ units=count (no indom) shorttext=test counter metric - helptext=Yes, this is a test counter metric + helptext=Yes +This is a test counter metric [2/688] discrete type=32-bit int (0x0), sem=discrete (0x4), pad=0x0 units= (no indom) shorttext=test discrete metric - helptext=Yes, this is a test discrete metric + helptext=Yes +This is a test discrete metric [3/792] indom type=32-bit unsigned int (0x1), sem=instant (0x3), pad=0x0 units=count @@ -203,7 +211,8 @@ units= indom=1 shorttext=test string metrics - helptext=Yes, this is a test string metric with instances + helptext=Yes +This is a test string metric with instances TOC[3]: offset 88, values offset 1208 (10 entries) [1/1208] counter = 41 @@ -222,11 +231,14 @@ [2/1784] 00oo00 [3/2040] [4/2296] test counter metric - [5/2552] Yes, this is a test counter metric + [5/2552] Yes +This is a test counter metric [6/2808] test discrete metric - [7/3064] Yes, this is a test discrete metric + [7/3064] Yes +This is a test discrete metric [8/3320] test string metrics - [9/3576] Yes, this is a test string metric with instances + [9/3576] Yes +This is a test string metric with instances [10/3832] We can be heroes [11/4088] We can be heroes, just for one day MMV file = $PCP_TMP_DIR/mmv/notest2-PID @@ -310,13 +322,15 @@ units=count (no indom) shorttext=test counter metric - helptext=Yes, this is a test counter metric + helptext=Yes! +This is a test counter metric [2/368] discrete type=32-bit int (0x0), sem=discrete (0x4), pad=0x0 units= (no indom) shorttext=test discrete metric - helptext=Yes, this is a test discrete metric + helptext=Yes! +This is a test discrete metric [3/416] indom type=32-bit unsigned int (0x1), sem=instant (0x3), pad=0x0 units=count @@ -340,7 +354,8 @@ units= indom=1 shorttext=test string metrics - helptext=Yes, this is a test string metric with instances + helptext=Yes! +This is a test string metric with instances TOC[3]: offset 88, values offset 608 (10 entries) [1/608] counter = 41 @@ -370,11 +385,14 @@ [13/4000] 00oo00 [14/4256] [15/4512] test counter metric - [16/4768] Yes, this is a test counter metric + [16/4768] Yes! +This is a test counter metric [17/5024] test discrete metric - [18/5280] Yes, this is a test discrete metric + [18/5280] Yes! +This is a test discrete metric [19/5536] test string metrics - [20/5792] Yes, this is a test string metric with instances + [20/5792] Yes! +This is a test string metric with instances [21/6048] We can be heroes [22/6304] We can be heroes, just for one day diff -Nru pcp-5.3.1/qa/1422.out pcp-5.3.2/qa/1422.out --- pcp-5.3.1/qa/1422.out 2020-02-27 06:57:32.000000000 +0000 +++ pcp-5.3.2/qa/1422.out 2021-07-30 04:05:06.000000000 +0000 @@ -121,7 +121,7 @@ inst [2117158819 or "qa108/organizationsnapshot"] value NUMBER inst [2136477134 or "qa108/alertlog"] value NUMBER === std err === -[DATE] pminfo(PID) Warning: invalid item 1024 (mmv.spacex.packages.request.circuitbreaker.fallback) in large-parfait, ignored +[DATE] pminfo(PID) Warning: MMV: verify_metric_item: invalid item 1024 (mmv.spacex.packages.request.circuitbreaker.fallback) in large-parfait, ignored [DATE] pminfo(PID) Error: pmdaFetch: PMID 70.42.464 not handled by fetch callback [DATE] pminfo(PID) Error: pmdaFetch: PMID 70.42.464 not handled by fetch callback === filtered valgrind report === diff -Nru pcp-5.3.1/qa/1433 pcp-5.3.2/qa/1433 --- pcp-5.3.1/qa/1433 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/1433 2021-07-30 04:05:06.000000000 +0000 @@ -30,6 +30,7 @@ else echo "Stopping pmproxy ..." >>$here/$seq.full _service pmproxy stop >>$here/$seq.full 2>&1 + _wait_pmproxy_end fi $sudo rm -rf $tmp $tmp.* } @@ -50,11 +51,25 @@ $sudo cp $tmp.local $PCP_PMPROXYOPTIONS_PATH _service pmproxy stop >/dev/null 2>&1 +_wait_pmproxy_end _service pmproxy start 2>&1 | _filter_pmproxy_start +_wait_for_pmproxy _service pmproxy stop 2>&1 | _filter_pmproxy_start +_wait_pmproxy_end _filter_pmproxy_log < $PCP_LOG_DIR/pmproxy/pmproxy.log +# systemd has a default limits ... systemd.unit(5) describe +# StartLimitIntervalSec and StartLimitBurst but not the default values +# which are hidden in *.conf files below /etc/systemd and appear +# to have defaults like: +# DefaultStartLimitIntervalSec=10s +# DefaultStartLimitBurst=5 +# ... this test has 2 (re)starts, so we need it to run for 4 seconds +# to avoid hitting the limit +# +sleep 4 + # success, all done status=0 exit diff -Nru pcp-5.3.1/qa/1457 pcp-5.3.2/qa/1457 --- pcp-5.3.1/qa/1457 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1457 2021-06-15 01:03:49.000000000 +0000 @@ -2,7 +2,7 @@ # PCP QA Test No. 1457 # Exercise HTTPS access to the PMWEBAPI(3). # -# Copyright (c) 2019 Red Hat. +# Copyright (c) 2019,2021 Red Hat. # seq=`basename $0` @@ -138,14 +138,59 @@ fi date >>$seq.full -echo "=== checking TLS operation ===" | tee -a $seq.full -# (-k) allows us to use self-signed (insecure) certificates, so for testing only -# (-v) provides very detailed TLS connection information, for debugging only -curl -k --get 2>$tmp.err \ - "https://localhost:$port/pmapi/metric?name=sample.long.ten" \ - | _filter_json -cat $tmp.err >>$seq.full +echo "=== checking serial http operation ===" | tee -a $seq.full +for i in 1 2 3 4; do + curl -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i +done +for i in 1 2 3 4; do +echo === out$i === | tee -a $seq.full +_filter_json < $tmp.out$i +done + +date >>$seq.full +echo "=== checking parallel http operation ===" | tee -a $seq.full +for i in 1 2 3 4; do + curl -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$! +done +wait $pid1 $pid2 $pid3 $pid4 +for i in 1 2 3 4; do +echo === out$i === | tee -a $seq.full +_filter_json < $tmp.out$i +done + +date >>$seq.full +echo "=== checking serial https/TLS operation ===" | tee -a $seq.full +for i in 1 2 3 4; do + curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i +done +for i in 1 2 3 4; do +echo === out$i === | tee -a $seq.full +_filter_json < $tmp.out$i +done + date >>$seq.full +echo "=== checking parallel https/TLS operation ===" | tee -a $seq.full +for i in 1 2 3 4; do + curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$! +done +wait $pid1 $pid2 $pid3 $pid4 +for i in 1 2 3 4; do +echo === out$i === | tee -a $seq.full +_filter_json < $tmp.out$i +done + +date >>$seq.full +echo "=== checking parallel mixed http and https/TLS operations ===" | tee -a $seq.full +for i in 1 3 5 7; do + j=`expr $i + 1` + curl -k -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$! + curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$j >$tmp.out$j & 2>/dev/null eval pid$j=$! +done +wait $pid1 $pid2 $pid3 $pid4 $pid5 $pid6 $pid7 $pid8 +for i in 1 2 3 4 5 6 7 8; do +echo === out$i === | tee -a $seq.full +_filter_json < $tmp.out$i +done echo "=== check pmproxy is running ===" pminfo -v -h localhost@localhost:$port hinv.ncpu @@ -156,7 +201,7 @@ fi # valgrind takes awhile to shutdown too -pmsignal $pid +pmsignal $pid >/dev/null 2>&1 pmsleep 3.5 echo "=== valgrind stdout ===" | tee -a $seq.full cat $tmp.valout | _filter_valgrind @@ -164,6 +209,9 @@ echo "=== valgrind stderr ===" | tee -a $seq.full cat $tmp.valerr | _filter_pmproxy_log | _filter_port +# final kill if it's spinning +$sudo kill -9 $pid >/dev/null 2>&1 + # success, all done status=0 exit diff -Nru pcp-5.3.1/qa/1457.out pcp-5.3.2/qa/1457.out --- pcp-5.3.1/qa/1457.out 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1457.out 2021-06-15 01:03:49.000000000 +0000 @@ -1,5 +1,539 @@ QA output created by 1457 -=== checking TLS operation === +=== checking serial http operation === +=== out1 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out2 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out3 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out4 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== checking parallel http operation === +=== out1 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out2 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out3 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out4 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== checking serial https/TLS operation === +=== out1 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out2 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out3 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out4 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== checking parallel https/TLS operation === +=== out1 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out2 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out3 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out4 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== checking parallel mixed http and https/TLS operations === +=== out1 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out2 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out3 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out4 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out5 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out6 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out7 === +{ + "context": "CONTEXT" + "metrics": [ + { + "name": "sample.long.ten", + "series": "SERIES" + "pmid": "29.0.11", + "type": "32", + "sem": "instant", + "units": "none", + "labels": { + "agent": "sample", + "cluster": "zero", + "domainname": "DOMAINNAME" + "hostname": "HOSTNAME" + "role": "testing" + }, + "text-oneline": "10 as a 32-bit integer", + "text-help": "10 as a 32-bit integer" + } + ] +} +=== out8 === { "context": "CONTEXT" "metrics": [ diff -Nru pcp-5.3.1/qa/1543 pcp-5.3.2/qa/1543 --- pcp-5.3.1/qa/1543 2020-11-10 22:19:53.000000000 +0000 +++ pcp-5.3.2/qa/1543 2021-07-30 04:05:06.000000000 +0000 @@ -17,7 +17,11 @@ _cleanup() { + echo "Entering _cleanup ..." >>$here/$seq.full + $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mproxy' >>$here/$seq.full + cat $PCP_LOG_DIR/pmproxy/pmproxy.log >>$here/$seq.full cd $here + _restore_auto_restart pmproxy if $need_restore then need_restore=false @@ -34,6 +38,8 @@ echo "Stopping pmproxy ..." >>$here/$seq.full _service pmproxy stop >>$here/$seq.full 2>&1 fi + echo "Exiting _cleanup ..." >>$here/$seq.full + $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mproxy' >>$here/$seq.full $sudo rm -rf $tmp $tmp.* } @@ -42,6 +48,23 @@ $sudo rm -rf $tmp $tmp.* $seq.full trap "_cleanup; exit \$status" 0 1 2 3 15 +# Seen to fail sometimes on vm01 ... pmproxy mysteriously dies off in +# pthread lock land ... we've resolved that it's not worth the +# failure noise and no more triage is warranted on older distros +# +case `admin/whatami` +in + *Ubuntu\ 16.*) + _notrun "avoiding intermittent failure on Ubuntu 16.??" + ;; + *Ubuntu\ 18.*) + _notrun "avoiding intermittent failure on Ubuntu 18.??" + ;; + *Debian\ 10.*) + _notrun "avoiding intermittent failure on Debian 10.?" + ;; +esac + pmproxy_was_running=false [ -f $PCP_RUN_DIR/pmproxy.pid ] && pmproxy_was_running=true echo "pmproxy_was_running=$pmproxy_was_running" >>$here/$seq.full @@ -158,8 +181,13 @@ echo "http.enabled = true" >> $tmp.conf $sudo cp $tmp.conf $PCP_SYSCONF_DIR/pmproxy/pmproxy.conf +_stop_auto_restart pmproxy _service pmproxy stop >/dev/null _service pmproxy start >>$here/$seq.full 2>&1 +_wait_for_pmproxy + +echo "After initial _service start ..." >>$here/$seq.full +$PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mproxy' >>$here/$seq.full port=44322 diff -Nru pcp-5.3.1/qa/1545 pcp-5.3.2/qa/1545 --- pcp-5.3.1/qa/1545 2019-02-26 21:38:22.000000000 +0000 +++ pcp-5.3.2/qa/1545 2021-07-30 04:05:06.000000000 +0000 @@ -47,10 +47,10 @@ # test names-change=update with pcp2xml echo testing names-change=update with pcp2xml -pcp2xml -s 5 -t 1 -5 -r --names-change=update mmv.control.files mmv.test | _filter_xml & +pcp2xml -s 4 -t 4 -5 -r --names-change=update mmv.control.files mmv.test | _filter_xml & -pmsleep 1.5 -$here/src/mmv_genstats test 1 +pmsleep 2 +$here/src/mmv_genstats test 2 wait # success, all done diff -Nru pcp-5.3.1/qa/1545.out pcp-5.3.2/qa/1545.out --- pcp-5.3.1/qa/1545.out 2020-02-27 06:57:32.000000000 +0000 +++ pcp-5.3.2/qa/1545.out 2021-07-30 04:05:06.000000000 +0000 @@ -1,7 +1,7 @@ QA output created by 1545 testing names-change=update with pcp2xml - + @@ -15,15 +15,20 @@ -0 - - - - - - 1 + +41 +42 +0 +43 +0 +0 +xxxxxxx +g'day world +00oo00 + + diff -Nru pcp-5.3.1/qa/154.out pcp-5.3.2/qa/154.out --- pcp-5.3.1/qa/154.out 2016-01-31 09:04:34.000000000 +0000 +++ pcp-5.3.2/qa/154.out 2021-07-30 04:05:06.000000000 +0000 @@ -240,7 +240,8 @@ PMID 5.0.4 cisco.rate_out:Cisco's computed average output rate in bytes per second, over the recent past, for this interface. -PMID 5.0.5 cisco.bandwidth: +PMID 5.0.5 cisco.bandwidth: + PMID 5.0.6 cisco.bytes_out_bcast:Total number of broadcast Kbytes output from the Cisco on this interface. Note that due to network delays in extracting the metrics from the @@ -283,7 +284,8 @@ PMID 5.0.4 cisco.rate_out:Cisco's computed average output rate in bytes per second, over the recent past, for this interface. -PMID 5.0.5 cisco.bandwidth: +PMID 5.0.5 cisco.bandwidth: + PMID 5.0.6 cisco.bytes_out_bcast:Total number of broadcast Kbytes output from the Cisco on this interface. Note that due to network delays in extracting the metrics from the @@ -363,6 +365,7 @@ past, for this interface. PMID 5.0.5 cisco.bandwidth: peak interface bandwidth in bytes per second + PMID 5.0.6 cisco.bytes_out_bcast: Total broadcast Kbytes output from the Cisco Total number of broadcast Kbytes output from the Cisco on this interface. @@ -413,6 +416,7 @@ past, for this interface. PMID 5.0.5 cisco.bandwidth: peak interface bandwidth in bytes per second + PMID 5.0.6 cisco.bytes_out_bcast: Total broadcast Kbytes output from the Cisco Total number of broadcast Kbytes output from the Cisco on this interface. diff -Nru pcp-5.3.1/qa/1573 pcp-5.3.2/qa/1573 --- pcp-5.3.1/qa/1573 2020-04-24 00:15:07.000000000 +0000 +++ pcp-5.3.2/qa/1573 2021-07-30 04:05:06.000000000 +0000 @@ -64,6 +64,7 @@ echo "pcp.enabled = true" >> $tmp.conf echo "http.enabled = true" >> $tmp.conf echo "redis.enabled = true" >> $tmp.conf +echo "secure.enabled = false" >> $tmp.conf echo "[discover]" >> $tmp.conf echo "enabled = true" >> $tmp.conf echo "[pmseries]" >> $tmp.conf @@ -106,6 +107,7 @@ echo "RSS1 for PID $pmproxy_pid is $pmproxy_rss1" >> $here/$seq.full echo "RSS2 for PID $pmproxy_pid is $pmproxy_rss2" >> $here/$seq.full cat $PCP_LOG_DIR/pmproxy/pmproxy.log >>$seq.full +[ -f /proc/$pmproxy_pid/maps ] && echo == maps >>$seq.full && $sudo cat /proc/$pmproxy_pid/maps >>$seq.full echo === see $seq.full for pmproxy rss and logs # success, all done diff -Nru pcp-5.3.1/qa/1599 pcp-5.3.2/qa/1599 --- pcp-5.3.1/qa/1599 2020-02-27 06:57:32.000000000 +0000 +++ pcp-5.3.2/qa/1599 2021-07-30 04:05:06.000000000 +0000 @@ -13,8 +13,6 @@ test -e $PCP_PMDAS_DIR/statsd/pmdastatsd || _notrun "statsd PMDA not installed" -_check_valgrind - _cleanup() { cd $here diff -Nru pcp-5.3.1/qa/1600 pcp-5.3.2/qa/1600 --- pcp-5.3.1/qa/1600 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/1600 2021-07-30 04:05:06.000000000 +0000 @@ -65,12 +65,27 @@ #end } +# not only dodge the timestamp and value, but the number of +# [TIMESTAMP] VALUE +# lines may be 1 or 2 +# _filter_values() { sed \ -e 's/\[[0-9][0-9]*\.[0-9][0-9]*\]/[TIMESTAMP]/g' \ -e 's/ [0-9][0-9]*$/ VALUE/g' \ - #end + | $PCP_AWK_PROG ' +BEGIN { n = 0 } +$2 == "VALUE" { n++ + if (n > 2) { + print "Unexpected extra line:",$0 + } + else { + if (n == 1) print + next + } + } + { print }' } _filter_label_values() @@ -87,6 +102,33 @@ #end } +# sort the values in this line +# agent: "mmv", "sample", "pmcd" +# +_filter_agents() +{ + LC_COLLATE=POSIX $PCP_AWK_PROG ' +$1 == "agent:" { printf "%s ",$1 + for (i = 2; i <= NF; i++) { + small = -1 + for (j = 2; j <= NF; j++) { + if ($j == "") + continue + if (small == -1 || $j < $small) + small = j + } + if (i > 2) + printf ", " + gsub(/,/, "", $small) + printf "%s",$small + $small = "" + } + printf "\n" + next + } + { print }' +} + # real QA test starts here _save_config $PCP_SYSCONF_DIR/labels _save_config $PCP_SYSCONF_DIR/pmproxy @@ -141,6 +183,7 @@ pmlogger -t 0.25 -T 3sec -c $tmp.pmlogger.conf -l $tmp.pmlogger.log $PCP_ARCHIVE_DIR/archive & pmlogger_pid=$! #echo pmlogger=$pmlogger_pid +_wait_for_pmlogger $pmlogger_pid $tmp.pmlogger.log pmsleep 0.5 # time for pmlogger to start logging # start pmproxy @@ -189,11 +232,15 @@ pmseries $options -l $series | _filter_labels | _filter_series echo "== verify metric values" | tee -a $seq.full -pmseries $options -t sample.ulong.million[samples:2] | _filter_values | _filter_series +pmsleep 0.5 +pmseries $options -t sample.ulong.million[samples:2] \ +| tee -a $seq.full \ +| _filter_values \ +| _filter_series echo "== verify label names and values" | tee -a $seq.full labels=`pmseries $options -l | LC_COLLATE=POSIX sort` -pmseries $options -v $labels | _filter_label_values +pmseries $options -v $labels | _filter_label_values | _filter_agents # pause until pmlogger exits to prevent confusion when removing archives wait $pmlogger_pid diff -Nru pcp-5.3.1/qa/1600.out pcp-5.3.2/qa/1600.out --- pcp-5.3.1/qa/1600.out 2020-04-24 00:15:07.000000000 +0000 +++ pcp-5.3.2/qa/1600.out 2021-07-30 04:05:06.000000000 +0000 @@ -40,9 +40,8 @@ TIMESERIES [TIMESTAMP] VALUE - [TIMESTAMP] VALUE == verify label names and values -agent: "mmv", "sample", "pmcd" +agent: "mmv", "pmcd", "sample" bin: 100, 200, 300, 400, 500, 600, 700, 800, 900 changed: false clan: "mcdonell" diff -Nru pcp-5.3.1/qa/1622 pcp-5.3.2/qa/1622 --- pcp-5.3.1/qa/1622 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1622 2021-06-15 01:03:49.000000000 +0000 @@ -156,6 +156,8 @@ type=AVC msg=audit(YYY.100): avc: denied { write } for pid=1797133 comm="pmlogger" name="12" dev="dm-0" ino=435470 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:initrc_tmp_t:s0 tclass=dir permissive=0 type=AVC msg=audit(YYY.101): avc: denied { integrity } for pid=1606 comm="pmdakvm" lockdown_reason="debugfs access" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=lockdown permissive=0 type=AVC msg=audit(YYY.102): avc: denied { map } for pid=7034 comm="pmdanvidia" path="/usr/lib64/libnvidia-ml.so" dev="dm-2" ino=16267329 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0 +type=AVC msg=audit(YYY.103): avc: denied { getattr } for pid=YYYY comm="pmdaproc" path="/dev/dma_heap" dev="devtmpfs" ino=150 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:dma_device_t:s0 tclass=dir permissive=0 +type=AVC msg=audit(YYY.104): avc: denied { sys_ptrace } for pid=9375 comm="pmdaproc" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=cap_userns permissive=1 #Synthesized AVC's type=AVC msg=audit(XXX.1): avc: denied { open read search } for pid=YYYY comm="pmdaX" name="/" dev="tracefs" ino=1 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:svirt_sandbox_file_t:s0 tclass=dir permissive=0 diff -Nru pcp-5.3.1/qa/1626 pcp-5.3.2/qa/1626 --- pcp-5.3.1/qa/1626 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1626 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,133 @@ +#!/bin/sh +# PCP QA Test No. 1626 +# pmproxy metrics +# +# Copyright (c) 2021 Red Hat. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +_check_redis_server +which curl >/dev/null 2>&1 || _notrun needs curl + +_cleanup() +{ + cd $here + if $pmproxy_was_running + then + echo "Restart pmproxy ..." >>$here/$seq.full + _service pmproxy restart >>$here/$seq.full 2>&1 + _wait_for_pmproxy + else + echo "Stopping pmproxy ..." >>$here/$seq.full + _service pmproxy stop >>$here/$seq.full 2>&1 + _wait_pmproxy_end + fi + $sudo rm -rf $tmp $tmp.* +} + +_pmproxy_mainpid() +{ + $PCP_PS_PROG $PCP_PS_ALL_FLAGS | \ + $PCP_AWK_PROG '$8 ~ "'$PCP_BINADM_DIR'/pmproxy" {print $2}' +} + +_probe_val() +{ + _x=`pminfo -f $1` + [ $? -ne 0 ] && echo pminfo $1 FAILED, result \"$_x\" && exit + echo $_x | awk '/value/ {print $NF}' +} + +status=1 # failure is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +pmproxy_was_running=false +[ -f $PCP_RUN_DIR/pmproxy.pid ] && pmproxy_was_running=true +echo "pmproxy_was_running=$pmproxy_was_running" >>$here/$seq.full + +# real QA test starts here +status=0 + +# need a fresh pmproxy service +_service pmproxy stop >/dev/null 2>&1 +_wait_pmproxy_end +_service pmproxy start 2>&1 | _filter_pmproxy_start +_wait_for_pmproxy + +echo == wait for pmproxy server metrics +_wait_for_pmproxy_metrics || exit + +echo === check pmproxy.pid +val=`_probe_val pmproxy.pid` +pid=`_pmproxy_mainpid` +if [ "$pid" -eq "$val" ]; then :; else echo FAIL pid=$pid val=$val && exit; fi + +echo === check initial pmproxy.webgroup metrics +for m in instmap labelsmap namesmap contextmap; do + [ `_probe_val pmproxy.webgroup.$m.size` -eq 0 ] && continue + echo FAILED pmproxy.webgroup.$m.size expected to be zero && exit +done + +echo "=== start the metrics timer with a /metrics RESTAPI call" +val=`curl -Gs 'http://localhost:44322/metrics?names=pmproxy.pid' |\ + $PCP_AWK_PROG '/^pmproxy_pid/ {print $NF}'` +[ "$pid" -ne "$val" ] && echo FAIL RESTAPI fetch for pmproxy.pid && exit + +echo "=== wait for the maps to be updated" +count=0 +while true; do + sz=`_probe_val pmproxy.webgroup.namesmap.size` + [ "$sz" -gt 0 ] && break + count=`expr $count + 1` + [ $count -gt 10 ] && echo FAILED after $count iterations && break + sleep 2 +done + +echo === pmproxy.webgroup map size metrics should now be nonzero +for m in instmap labelsmap namesmap contextmap; do + [ `_probe_val pmproxy.webgroup.$m.size` -gt 0 ] && continue + echo FAILED pmproxy.webgroup.$m.size expected to be non-zero + echo pmproxy.webgroup.$m.size = `_probe_val pmproxy.webgroup.$m.size` + exit +done + +echo === check pmproxy cpu counters +total=`_probe_val pmproxy.cpu.total` +user=`_probe_val pmproxy.cpu.user` +sys=`_probe_val pmproxy.cpu.sys` +[ "$user" -eq 0 ] && echo FAIL pmproxy.cpu.user is zero +[ "$sys" -eq 0 ] && echo FAIL pmproxy.cpu.sys is zero +[ "$total" -eq 0 ] && echo FAIL pmproxy.cpu.total is zero + +echo === check for discovery partial metadata reads +partial=`_probe_val pmproxy.discover.metadata.partial_reads` +[ "$partial" -ne 0 ] && echo FAIL $partial partial reads, should be zero && exit + +echo === check maxrss and datasz values +for m in maxrss datasz; do + val=`_probe_val pmproxy.mem.$m` + [ "$val" -gt 0 ] && continue + echo FAIL pmproxy.mem.$m should be non-zero && exit +done + +echo === check maxrss doesnt grow after 100 basic restapi requests +start_maxrss=`_probe_val pmproxy.mem.maxrss` +for n in `seq 1 100`; do + curl -Gs 'http://localhost:44322/metrics?names=kernel.all.load' >/dev/null 2>&1 +done +finish_maxrss=`_probe_val pmproxy.mem.maxrss` +growth=`expr $finish_maxrss - $start_maxrss` +# [ $growth -gt 0 ] && echo start=$start_maxrss finish=$finish_maxrss, growth = $growth +_within_tolerance "maxrss growth after 100 /metrics calls" $finish_maxrss $start_maxrss %3 -v + +# sleep to avoid systemd StartLimitIntervalSec limits +sleep 4 +exit diff -Nru pcp-5.3.1/qa/1626.out pcp-5.3.2/qa/1626.out --- pcp-5.3.1/qa/1626.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1626.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,12 @@ +QA output created by 1626 +== wait for pmproxy server metrics +=== check pmproxy.pid +=== check initial pmproxy.webgroup metrics +=== start the metrics timer with a /metrics RESTAPI call +=== wait for the maps to be updated +=== pmproxy.webgroup map size metrics should now be nonzero +=== check pmproxy cpu counters +=== check for discovery partial metadata reads +=== check maxrss and datasz values +=== check maxrss doesnt grow after 100 basic restapi requests +maxrss growth after 100 /metrics calls is in range diff -Nru pcp-5.3.1/qa/1627 pcp-5.3.2/qa/1627 --- pcp-5.3.1/qa/1627 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1627 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,62 @@ +#!/bin/sh +# PCP QA Test No. 1627 +# Exercise LOGIMPORT PM_ERR_CONV error handling condition +# https://github.com/performancecopilot/pcp/issues/1327 +# +# Copyright (c) 2021 Red Hat. All Rights Reserved. +# + +if [ $# -eq 0 ] +then + seq=`basename $0` + echo "QA output created by $seq" +else + # use $seq from caller, unless not set + [ -n "$seq" ] || seq=`basename $0` + echo "QA output created by `basename $0` $*" +fi + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +do_valgrind=false +if [ "$1" = "--valgrind" ] +then + _check_valgrind + do_valgrind=true +fi + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_filter() +{ + sed \ + -e "s,$tmp.log,TMPLOG,g" \ + # end +} + +# real QA test starts here +rm -f $tmp.log.* + +if $do_valgrind +then + _run_valgrind ./src/check_pmi_errconv $tmp.log +else + ./src/check_pmi_errconv $tmp.log +fi \ +| _filter + +PCP_DERIVED_CONFIG="" TZ=UTC pminfo -fd -a $tmp.log + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1627.out pcp-5.3.2/qa/1627.out --- pcp-5.3.1/qa/1627.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1627.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,18 @@ +QA output created by 1627 +pmiPutValue: inst 0: Impossible value or scale conversion +pmiPutValue: inst 1: Impossible value or scale conversion + +my.metric.int + Data Type: 32-bit int InDom: 245.0 0x3d400000 + Semantics: instant Units: none +Error: Impossible value or scale conversion + +event.flags + Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: discrete Units: none +No value(s) available! + +event.missed + Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: discrete Units: none +No value(s) available! diff -Nru pcp-5.3.1/qa/1628 pcp-5.3.2/qa/1628 --- pcp-5.3.1/qa/1628 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1628 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,40 @@ +#!/bin/sh +# PCP QA Test No. 1628 +# Exercise LOGIMPORT PM_ERR_CONV error handling condition +# https://github.com/performancecopilot/pcp/issues/1327 +# valgrind-enabled variant. +# +# Copyright (c) 2021 Red Hat. All Rights Reserved. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +_check_valgrind + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# real QA test starts here +export seq +./1627 --valgrind \ +| $PCP_AWK_PROG ' +skip == 1 && $1 == "===" { skip = 0 } +/^=== std err ===/ { skip = 1 } +skip == 0 { print } +skip == 1 { print >>"'$here/$seq.full'" }' + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1628.out pcp-5.3.2/qa/1628.out --- pcp-5.3.1/qa/1628.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1628.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,25 @@ +QA output created by 1628 +QA output created by 1627 --valgrind +=== std out === +=== filtered valgrind report === +Memcheck, a memory error detector +Command: ./src/check_pmi_errconv TMPLOG +LEAK SUMMARY: +definitely lost: 0 bytes in 0 blocks +indirectly lost: 0 bytes in 0 blocks +ERROR SUMMARY: 0 errors from 0 contexts ... + +my.metric.int + Data Type: 32-bit int InDom: 245.0 0x3d400000 + Semantics: instant Units: none +Error: Impossible value or scale conversion + +event.flags + Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: discrete Units: none +No value(s) available! + +event.missed + Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: discrete Units: none +No value(s) available! diff -Nru pcp-5.3.1/qa/1633 pcp-5.3.2/qa/1633 --- pcp-5.3.1/qa/1633 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1633 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,59 @@ +#!/bin/sh +# PCP QA Test No. 1633 +# Exercise the pcp-ss(1) command using an archive +# +# Copyright (c) 2021 Red Hat. +# + +seq=`basename $0` +echo "QA output created by $seq" + +. ./common.python + +status=1 # failure is the default! +$sudo rm -rf $tmp.* $seq.full +trap "cd $here; rm -rf $tmp.*; exit \$status" 0 1 2 3 15 + +# Something in pcp-ss is non-deterministic about how the +# output lines are ordered, so we have to sort 'em here. +# The first 2 lines are "heading", so keep them out of +# the sort. +# +_filter() +{ + $PCP_AWK_PROG ' +BEGIN { out = "head" } +NR == 3 { out = "body" } + { print >"'$tmp'." out }' + cat $tmp.head + LC_COLLATE=POSIX sort $tmp.body +} + +pcp_ss="$PCP_BINADM_DIR/pcp-ss" +test -x $pcp_ss || _notrun "No pcp-ss(1) installed" + +# real QA test starts here +archive=$here/archives/pcp-ss + +echo && echo pcp-ss output, at default offset +pcp -z -a $archive ss -oemitauO \ +| _filter + +echo && echo pcp-ss output, at 10s offset +pcp -z -S10s -a $archive ss -oemitauO \ +| _filter + +echo && echo pcp-ss output, at specific start time +pcp -z -S'@Fri Jun 18 13:33:39 2021' -a $archive ss -oemitauO \ +| _filter + +echo && echo pcp-ss output, at archive end +pcp -z -O-0 -a $archive ss -oemitauO \ +| _filter + +echo && echo check error handling when metrics not present. Note error is expected +pcp -z -O-0 -a $here/archives/pcp-mpstat ss 2>&1 | sed -e "s;$here/;;" + +# success, all done +status=0 +exit diff -Nru pcp-5.3.1/qa/1633.out pcp-5.3.2/qa/1633.out --- pcp-5.3.1/qa/1633.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1633.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,790 @@ +QA output created by 1633 + +pcp-ss output, at default offset +# Time: 2021-06-18 13:34:14.168998 Filter: state connected +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +tcp ESTAB 0 0 [::1]:3000 [::1]:51232 timer(keepalive,8.488ms,0) uid:378 inode:165581925 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.014/0.011 ato:40 mss:65464 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65464 +tcp ESTAB 0 0 [::1]:51228 [::1]:3000 timer(keepalive,3.596ms,0) uid:1024 inode:165582929 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.422/0.763 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51232 [::1]:3000 timer(keepalive,3.596ms,0) uid:1024 inode:165552950 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d3) ts sack cubic wscale:7,7 rtt:8.219/14.257 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:163840 +tcp ESTAB 0 0 [::1]:51236 [::1]:3000 timer(keepalive,514ms,0) uid:1024 inode:165575931 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4585000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:5.713/10.966 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51238 [::1]:3000 timer(keepalive,11sec,0) uid:1024 inode:165581951 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d1) ts sack cubic wscale:7,7 rtt:4.802/9.371 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65476 +tcp ESTAB 0 0 [::1]:51240 [::1]:3000 timer(keepalive,15sec,0) uid:1024 inode:165583008 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.783/1.488 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65476 +tcp ESTAB 0 0 127.0.0.1:6379 127.0.0.1:34526 timer(keepalive,299ms,0) uid:379 inode:164789635 sk:17e9 cgroup:/system.slice/redis.service <-> skmem(r0,rb6291456,t0,tb4194304,f0,w0,o0,bl0,d226) ts sack cubic wscale:7,7 rtt:5.268/10.344 ato:40 mss:65483 cwnd:51 pmtu:65535 ssthresh:27 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:1379162 +tcp ESTAB 0 0 10.0.0.10:33256 10.0.0.6:8009 timer(keepalive,19sec,0) uid:1024 inode:161634072 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2554304,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:6,7 rtt:7.326/1.581 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65491 +tcp ESTAB 0 0 10.0.0.10:34914 142.250.70.234:443 uid:1024 inode:165418039 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d11) ts sack cubic wscale:8,7 rtt:10.278/0.678 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:34916 142.250.70.234:443 uid:1024 inode:165418040 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d9) ts sack cubic wscale:8,7 rtt:10.081/1.167 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:37256 157.240.8.18:443 timer(keepalive,2min13sec,0) uid:1024 inode:163353710 sk:262 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb1623296,t0,tb46080,f4096,w0,o0,bl0,d37) ts sack cubic wscale:8,7 rtt:21.667/1.031 ato:40 mss:1380 cwnd:22 pmtu:1500 ssthresh:22 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:87463 +tcp ESTAB 0 0 10.0.0.10:37330 217.182.79.119:6667 timer(keepalive,3min20sec,0) uid:1024 inode:147037462 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2467768,t0,tb87040,f0,w0,o0,bl0,d15) ts sack cubic wscale:7,7 rtt:381.926/27.664 ato:40 mss:1448 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:64371 +tcp ESTAB 0 0 10.0.0.10:39906 172.217.194.188:5228 timer(keepalive,15sec,0) uid:1024 inode:164287111 sk:eacd cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:94.893/7.701 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40218 142.250.70.142:443 uid:1024 inode:165413160 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d16) ts sack cubic wscale:8,7 rtt:10.194/0.696 ato:40 mss:1418 cwnd:3 pmtu:1500 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40226 13.54.123.156:443 timer(keepalive,28sec,0) uid:1024 inode:163971400 sk:3b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2673664,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:23.063/0.882 ato:46 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:67012 +tcp ESTAB 0 0 10.0.0.10:40232 13.54.123.156:443 timer(keepalive,15sec,0) uid:1024 inode:164254779 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2730360,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:21.7/0.326 ato:42 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:67755 +tcp ESTAB 0 0 10.0.0.10:43990 142.250.70.131:443 uid:1024 inode:165420073 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:9.826/0.515 ato:40 mss:1418 cwnd:4 pmtu:1500 ssthresh:4 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44322 10.0.0.10:55342 timer(keepalive,44sec,0) uid:386 inode:165594871 sk:5 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.05/0.056 ato:40 mss:65483 cwnd:20 pmtu:65535 ssthresh:20 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65483 +tcp ESTAB 0 0 10.0.0.10:44388 142.250.4.189:443 uid:1024 inode:165419510 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:96.696/2.871 ato:40 mss:1418 cwnd:7 pmtu:1500 ssthresh:7 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44852 202.58.9.228:443 timer(keepalive,3.777ms,0) uid:1024 inode:143675936 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1770) sack cubic wscale:9,7 rtt:98.707/11.472 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:45164 173.194.202.125:443 timer(keepalive,28sec,0) uid:1024 inode:161888302 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:228.663/49.231 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46306 3.233.54.64:443 timer(keepalive,28sec,0) uid:1024 inode:165592357 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:246.45/50.358 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46392 142.251.10.189:443 uid:1024 inode:165466671 sk:f23b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d3) ts sack cubic wscale:8,7 rtt:111.69/24.888 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:49614 142.250.70.165:443 uid:1024 inode:165581235 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:10.2/1.047 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:52874 199.127.207.181:443 timer(keepalive,28sec,0) uid:1024 inode:154981923 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d433) sack cubic wscale:9,7 rtt:231.99/42.333 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:55332 10.0.0.10:44322 timer(keepalive,28sec,0) uid:378 inode:165581545 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb4454646,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:3.728/6.7 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:105770 +tcp ESTAB 0 0 10.0.0.10:55342 10.0.0.10:44322 timer(keepalive,29sec,0) uid:378 inode:165616642 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb2882418,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.041/0.024 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:73728 +tcp ESTAB 0 0 10.0.0.10:55532 140.82.114.26:443 timer(keepalive,29sec,0) uid:1024 inode:165515920 sk:17eb cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:248.861/32.644 ato:40 mss:1424 cwnd:20 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55534 140.82.114.26:443 timer(keepalive,2.767ms,0) uid:1024 inode:165521771 sk:ef38 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:283.095/41.806 ato:40 mss:1424 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55694 34.120.177.193:443 timer(keepalive,7.793ms,0) uid:1024 inode:165577700 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:8,7 rtt:13.091/4.789 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:57232 157.240.8.35:443 uid:1024 inode:165408121 sk:1781 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb46080,f8192,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:23.193/1.8 ato:40 mss:1380 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:58310 52.88.142.33:443 timer(keepalive,1min53sec,0) uid:1024 inode:143231822 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:211.152/22.951 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 127.0.0.1:34526 127.0.0.1:6379 timer(keepalive,646ms,0) uid:386 inode:164791620 sk:ef22 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb4978722,t0,tb4194304,f0,w0,o0,bl0,d397) ts sack cubic wscale:7,7 rtt:0.217/0.167 ato:40 mss:65483 cwnd:36 pmtu:65535 ssthresh:16 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:245440 +tcp ESTAB 0 0 127.0.0.1:49798 127.0.0.1:3000 uid:0 inode:164815425 sk:17e9 cgroup:/system.slice/pmcd.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:6.023/4.348 ato:40 mss:65483 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65495 +tcp ESTAB 0 0 10.40.192.134:47862 10.0.15.20:6667 timer(keepalive,2min48sec,0) uid:1024 inode:143267906 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb181972,t0,tb46080,f0,w0,o0,bl0,d56) ts sack cubic wscale:8,7 rtt:456.275/44.255 ato:40 mss:1308 cwnd:2 pmtu:1360 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:19026 +tcp ESTAB 0 0 192.168.122.1:53100 192.168.122.54:22 timer(keepalive,1min43sec,0) uid:1024 inode:152890200 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d11) ts sack cubic wscale:7,7 rtt:6.415/11.95 ato:40 mss:1448 cwnd:20 pmtu:1500 ssthresh:20 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 [::ffff:127.0.0.1]:3000 [::ffff:127.0.0.1]:49798 timer(keepalive,5.265ms,0) uid:378 inode:164821548 sk:17e9 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb2358342,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.033/0.018 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65664 +tcp TIME-WAIT 0 0 10.0.0.10:49594 142.250.70.165:443 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55014 10.0.0.10:44322 timer(timewait,581ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55020 10.0.0.10:44322 timer(timewait,3.571ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55022 10.0.0.10:44322 timer(timewait,586ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55024 10.0.0.10:44322 timer(timewait,1.623ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55026 10.0.0.10:44322 timer(timewait,1.601ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55028 10.0.0.10:44322 timer(timewait,2.601ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55030 10.0.0.10:44322 timer(timewait,1.618ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55032 10.0.0.10:44322 timer(timewait,2.607ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55034 10.0.0.10:44322 timer(timewait,4.636ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55036 10.0.0.10:44322 timer(timewait,3.608ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55038 10.0.0.10:44322 timer(timewait,5.580ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55040 10.0.0.10:44322 timer(timewait,4.635ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55042 10.0.0.10:44322 timer(timewait,6.447ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55044 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55046 10.0.0.10:44322 timer(timewait,5.577ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55048 10.0.0.10:44322 timer(timewait,8.579ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55050 10.0.0.10:44322 timer(timewait,6.570ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55052 10.0.0.10:44322 timer(timewait,6.568ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55054 10.0.0.10:44322 timer(timewait,7.474ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55056 10.0.0.10:44322 timer(timewait,7.623ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55058 10.0.0.10:44322 timer(timewait,7.617ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55060 10.0.0.10:44322 timer(timewait,8.449ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55062 10.0.0.10:44322 timer(timewait,9.618ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55064 10.0.0.10:44322 timer(timewait,8.577ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55066 10.0.0.10:44322 timer(timewait,9.605ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55068 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55070 10.0.0.10:44322 timer(timewait,9.625ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55072 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55074 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55078 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55080 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55082 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55084 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55086 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55088 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55090 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55092 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55094 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55096 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55100 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55102 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55104 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55106 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55108 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55110 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55112 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55114 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55116 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55118 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55122 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55124 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55126 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55130 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55132 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55134 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55136 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55138 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55140 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55142 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55144 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55146 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55148 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55150 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55152 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55154 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:ef49 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55156 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:ef4b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55158 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:ef4e cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55160 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:ef4d cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55162 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:ef4a cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55164 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55166 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:ef50 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55168 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:ef4c cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55172 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55174 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55176 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55178 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55180 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55182 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55184 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55186 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55188 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55190 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55194 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55196 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55200 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55204 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55206 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55210 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55212 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55214 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55216 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55218 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55220 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55222 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55224 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55226 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55228 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55230 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55232 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55234 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55236 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55238 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55240 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55242 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55244 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55248 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55250 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55254 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55256 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55260 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55262 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55266 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55268 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55270 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55272 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55274 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55276 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55278 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55280 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55282 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55284 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55286 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55288 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55292 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55294 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55296 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55298 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55300 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55302 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55304 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55306 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55308 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55310 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55312 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55316 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55318 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55320 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55322 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55326 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55328 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55330 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55334 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55338 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55340 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:57958 142.250.70.238:443 timer(timewait,54sec,0) uid:0 inode:0 sk:183a cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35754 142.251.10.189:443 uid:1024 inode:165318004 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35983 142.250.70.142:443 uid:1024 inode:165466809 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:36244 142.250.70.138:443 uid:1024 inode:165293889 sk:f231 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:44639 142.250.70.131:443 uid:1024 inode:165411837 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:49123 142.250.4.189:443 uid:1024 inode:165373416 sk:ef33 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 + +pcp-ss output, at 10s offset +# Time: 2021-06-18 13:33:39.076141 Filter: state connected +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +tcp ESTAB 0 0 [::1]:3000 [::1]:51232 timer(keepalive,4.425ms,0) uid:378 inode:165581925 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.392/0.759 ato:40 mss:65464 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:10193629 bytes_acked:10160847 bytes_received:278360 segs_out:992 segs_in:851 send 13360000000bps lastsnd:607 lastrcv:760 lastack:607 pacing_rate 26677465768bps delivery_rate 174570666664bps rcv_space:65464 +tcp ESTAB 0 0 [::1]:51228 [::1]:3000 timer(keepalive,43sec,0) uid:1024 inode:165582929 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:2.415/4.642 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:266019 bytes_acked:266020 bytes_received:6994873 segs_out:842 segs_in:867 send 1085482402bps lastsnd:759 lastrcv:623 lastack:623 pacing_rate 2170964800bps delivery_rate 87381333328bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51232 [::1]:3000 timer(keepalive,43sec,0) uid:1024 inode:165552950 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d3) ts sack cubic wscale:7,7 rtt:3.701/7.013 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:278360 bytes_acked:278361 bytes_received:10160847 segs_out:851 segs_in:993 send 708305863bps lastsnd:760 lastrcv:607 lastack:607 pacing_rate 1416324704bps delivery_rate 87381333328bps rcv_space:163840 +tcp ESTAB 0 0 [::1]:51236 [::1]:3000 timer(keepalive,40sec,0) uid:1024 inode:165575931 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4585000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.942/1.793 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:274730 bytes_acked:274731 bytes_received:12994135 segs_out:925 segs_in:1058 send 2782845011bps lastsnd:4761 lastrcv:4697 lastack:4697 pacing_rate 5564213312bps delivery_rate 65536000000bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51238 [::1]:3000 timer(keepalive,6.381ms,0) uid:1024 inode:165581951 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d1) ts sack cubic wscale:7,7 rtt:4.48/8.875 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:238787 bytes_acked:238788 bytes_received:6296966 segs_out:626 segs_in:849 send 585142857bps lastsnd:758 lastrcv:616 lastack:616 pacing_rate 1170122464bps delivery_rate 87381333328bps rcv_space:65476 +tcp ESTAB 0 0 [::1]:51240 [::1]:3000 timer(keepalive,10sec,0) uid:1024 inode:165583008 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:4.388/8.395 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:247338 bytes_acked:247339 bytes_received:6277019 segs_out:642 segs_in:867 send 597411121bps lastsnd:764 lastrcv:635 lastack:635 pacing_rate 1194686104bps delivery_rate 87381333328bps rcv_space:65476 +tcp ESTAB 0 0 127.0.0.1:6379 127.0.0.1:34526 timer(keepalive,40sec,0) uid:379 inode:164789635 sk:17e9 cgroup:/system.slice/redis.service <-> skmem(r0,rb6291456,t0,tb4194304,f0,w0,o0,bl0,d191) ts sack cubic wscale:7,7 rtt:5.308/10.357 ato:40 mss:65483 cwnd:37 pmtu:65535 ssthresh:27 bytes_sent:1742159061 bytes_acked:1737331568 bytes_received:348908437 segs_out:100169 segs_in:51994 send 3651651846bps lastsnd:609 lastrcv:609 lastack:568 pacing_rate 4381982208bps delivery_rate 69848533328bps rcv_space:1379162 +tcp ESTAB 0 0 10.0.0.10:33256 10.0.0.6:8009 timer(keepalive,14sec,0) uid:1024 inode:161634072 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2554304,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:6,7 rtt:7.135/1.044 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:734660 bytes_acked:734551 bytes_received:739570 segs_out:13349 segs_in:6686 send 16235459bps lastsnd:524 lastrcv:516 lastack:516 pacing_rate 32468640bps delivery_rate 7613536bps rcv_space:65491 +tcp ESTAB 0 0 10.0.0.10:34914 142.250.70.234:443 uid:1024 inode:165418039 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d11) ts sack cubic wscale:8,7 rtt:10.278/0.678 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:22452 bytes_acked:22453 bytes_received:16959 segs_out:307 segs_in:321 send 11037167bps lastsnd:11065 lastrcv:10735 lastack:10735 pacing_rate 22073256bps delivery_rate 2827752bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:34916 142.250.70.234:443 uid:1024 inode:165418040 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d9) ts sack cubic wscale:8,7 rtt:10.081/1.167 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:19775 bytes_acked:19776 bytes_received:15769 segs_out:277 segs_in:301 send 11252852bps lastsnd:11066 lastrcv:11066 lastack:11056 pacing_rate 22505424bps delivery_rate 3209656bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:37256 157.240.8.18:443 timer(keepalive,2min53sec,0) uid:1024 inode:163353710 sk:262 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb1623296,t0,tb46080,f0,w0,o0,bl0,d37) ts sack cubic wscale:8,7 rtt:21.5/0.94 ato:40 mss:1380 cwnd:22 pmtu:1500 ssthresh:22 bytes_sent:71046 bytes_acked:71015 bytes_received:222343 segs_out:4414 segs_in:4458 send 11296744bps lastsnd:1471 lastrcv:1255 lastack:1449 pacing_rate 13556008bps delivery_rate 9819152bps rcv_space:87463 +tcp ESTAB 0 0 10.0.0.10:39906 172.217.194.188:5228 timer(keepalive,6.702ms,0) uid:1024 inode:164287111 sk:eacd cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:94.893/7.701 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:893 bytes_acked:894 bytes_received:5528 segs_out:187 segs_in:187 send 1195452bps lastsnd:1336001 lastrcv:1335906 lastack:38204 pacing_rate 2390880bps delivery_rate 229032bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40218 142.250.70.142:443 uid:1024 inode:165413160 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d16) ts sack cubic wscale:8,7 rtt:10.371/0.673 ato:40 mss:1418 cwnd:3 pmtu:1500 ssthresh:2 bytes_sent:128059 bytes_acked:122619 bytes_received:60993 segs_out:493 segs_in:558 send 3281458bps lastsnd:48748 lastrcv:48749 lastack:48739 pacing_rate 3937552bps delivery_rate 2269480bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40226 13.54.123.156:443 timer(keepalive,8.158ms,0) uid:1024 inode:163971400 sk:3b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2673664,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:23.038/1.11 ato:46 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:13434 bytes_acked:13435 bytes_received:76107 segs_out:671 segs_in:482 send 4472610bps lastsnd:22123 lastrcv:22098 lastack:22098 pacing_rate 8945216bps delivery_rate 1318208bps rcv_space:67012 +tcp ESTAB 0 0 10.0.0.10:40232 13.54.123.156:443 timer(keepalive,15sec,0) uid:1024 inode:164254779 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2730360,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:21.965/0.395 ato:42 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:21565 bytes_acked:21566 bytes_received:71363 segs_out:842 segs_in:526 send 4691099bps lastsnd:9624 lastrcv:9601 lastack:9601 pacing_rate 9381984bps delivery_rate 1362840bps rcv_space:67755 +tcp ESTAB 0 0 10.0.0.10:43990 142.250.70.131:443 uid:1024 inode:165420073 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:9.654/0.506 ato:40 mss:1418 cwnd:4 pmtu:1500 ssthresh:4 bytes_sent:10189 bytes_acked:10000 bytes_received:16620 segs_out:246 segs_in:410 send 4700228bps lastsnd:17768 lastrcv:17783 lastack:17759 pacing_rate 5640272bps delivery_rate 2983168bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44322 10.0.0.10:55122 timer(keepalive,44sec,0) uid:386 inode:165594717 sk:5 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:5.315/10.43 ato:40 mss:65483 cwnd:17 pmtu:65535 ssthresh:17 bytes_sent:3498895 bytes_acked:3498895 bytes_received:8301 segs_out:65 segs_in:47 send 1675576294bps lastsnd:609 lastrcv:611 lastack:567 pacing_rate 2010691552bps delivery_rate 130966000000bps rcv_space:65483 +tcp ESTAB 0 0 10.0.0.10:44388 142.250.4.189:443 uid:1024 inode:165419510 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:96.696/2.871 ato:40 mss:1418 cwnd:7 pmtu:1500 ssthresh:7 bytes_sent:10276 bytes_acked:9774 bytes_received:14545 segs_out:207 segs_in:207 send 821213bps lastsnd:17146 lastrcv:17036 lastack:17036 pacing_rate 985448bps delivery_rate 467400bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44852 202.58.9.228:443 timer(keepalive,43sec,0) uid:1024 inode:143675936 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1769) sack cubic wscale:9,7 rtt:98.707/11.472 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:6723 bytes_acked:6724 bytes_received:9572 segs_out:8675 segs_in:8669 send 1183300bps lastsnd:8818069 lastrcv:8817969 lastack:1340 pacing_rate 2366592bps delivery_rate 480352bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:45164 173.194.202.125:443 timer(keepalive,23sec,0) uid:1024 inode:161888302 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:228.663/49.231 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:11353 bytes_acked:11354 bytes_received:23756 segs_out:890 segs_in:895 send 496101bps lastsnd:207468 lastrcv:207250 lastack:21813 pacing_rate 992200bps delivery_rate 103864bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46306 3.233.54.64:443 timer(keepalive,23sec,0) uid:1024 inode:165592357 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:246.45/50.358 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3814 bytes_acked:3815 bytes_received:4765 segs_out:12 segs_in:12 send 470034bps lastsnd:22071 lastrcv:21847 lastack:21848 pacing_rate 940064bps delivery_rate 120016bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46392 142.251.10.189:443 uid:1024 inode:165466671 sk:f23b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d2) ts sack cubic wscale:8,7 rtt:111.69/24.888 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:8645 bytes_acked:8646 bytes_received:12267 segs_out:135 segs_in:139 send 1015668bps lastsnd:52309 lastrcv:25403 lastack:50572 pacing_rate 2031320bps delivery_rate 335272bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:49594 142.250.70.165:443 timer(keepalive,6.621ms,0) uid:1024 inode:165410113 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb1074240,t0,tb87040,f0,w0,o0,bl0,d6) ts sack cubic wscale:8,7 rtt:11.987/1.417 ato:40 mss:1418 cwnd:18 pmtu:1500 ssthresh:0 bytes_sent:76222 bytes_acked:76223 bytes_received:199808 segs_out:342 segs_in:404 send 17034454bps lastsnd:218733 lastrcv:218735 lastack:38371 pacing_rate 34068192bps delivery_rate 8192584bps rcv_space:75339 +tcp ESTAB 0 0 10.0.0.10:49614 142.250.70.165:443 uid:1024 inode:165581235 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:10.118/1.177 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3573 bytes_acked:3574 bytes_received:2558 segs_out:20 segs_in:19 send 11211702bps lastsnd:27596 lastrcv:27584 lastack:27584 pacing_rate 22423400bps delivery_rate 3963936bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:52874 199.127.207.181:443 timer(keepalive,23sec,0) uid:1024 inode:154981923 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d433) sack cubic wscale:9,7 rtt:231.99/42.333 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3792 bytes_acked:3793 bytes_received:6931 segs_out:2107 segs_in:2102 send 503470bps lastsnd:78116165 lastrcv:78116159 lastack:21772 pacing_rate 1006936bps delivery_rate 206000bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:55104 10.0.0.10:44322 timer(keepalive,26sec,0) uid:378 inode:165606577 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb6291456,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:8.43/11.76 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:8327 bytes_acked:8328 bytes_received:3510941 segs_out:178 segs_in:356 send 310965599bps lastsnd:756 lastrcv:637 lastack:639 pacing_rate 621875864bps delivery_rate 20164923072bps rcv_space:469929 +tcp ESTAB 0 0 10.0.0.10:55122 10.0.0.10:44322 timer(keepalive,29sec,0) uid:378 inode:165608516 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb3013437,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.236/0.425 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:16 bytes_acked:16 bytes_received:6325 segs_out:47 segs_in:66 send 11107796610bps lastsnd:611 lastrcv:609 lastack:609 pacing_rate 22145216472bps delivery_rate 32768000000bps rcv_space:81920 +tcp ESTAB 0 0 10.0.0.10:55308 142.250.70.228:443 uid:1024 inode:165561257 sk:eb1c cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d3) ts sack cubic wscale:8,7 rtt:11.532/2.782 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3051 bytes_acked:3052 bytes_received:4379 segs_out:38 segs_in:36 send 9836975bps lastsnd:46596 lastrcv:46586 lastack:46587 pacing_rate 19672664bps delivery_rate 1814168bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55532 140.82.114.26:443 timer(keepalive,9.693ms,0) uid:1024 inode:165515920 sk:17eb cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:251.743/35.839 ato:40 mss:1424 cwnd:20 pmtu:1500 ssthresh:0 bytes_sent:17930 bytes_acked:17931 bytes_received:4200 segs_out:49 segs_in:46 send 905050bps lastsnd:20795 lastrcv:20795 lastack:20571 pacing_rate 1810096bps delivery_rate 503048bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55534 140.82.114.26:443 timer(keepalive,28sec,0) uid:1024 inode:165521771 sk:ef38 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:283.095/41.806 ato:40 mss:1424 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:2643 bytes_acked:2644 bytes_received:3981 segs_out:36 segs_in:38 send 402409bps lastsnd:2669 lastrcv:2669 lastack:2444 pacing_rate 804816bps delivery_rate 73400bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55694 34.120.177.193:443 timer(keepalive,2.525ms,0) uid:1024 inode:165577700 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:8,7 rtt:13.091/4.789 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:1234 bytes_acked:1235 bytes_received:5268 segs_out:21 segs_in:20 send 8665495bps lastsnd:224263 lastrcv:224265 lastack:42465 pacing_rate 17330160bps delivery_rate 2267288bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:57232 157.240.8.35:443 uid:1024 inode:165408121 sk:1781 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb46080,f8192,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:23.193/1.8 ato:40 mss:1380 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:69963 bytes_acked:68311 bytes_received:28389 segs_out:252 segs_in:206 send 952011bps lastsnd:6934 lastrcv:6458 lastack:6458 pacing_rate 1142400bps delivery_rate 371224bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:57958 142.250.70.238:443 uid:1024 inode:165594185 sk:183a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:8,7 rtt:10.608/1.213 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:7836 bytes_acked:7837 bytes_received:3104 segs_out:27 segs_in:27 send 10693816bps lastsnd:18595 lastrcv:18584 lastack:18584 pacing_rate 21387376bps delivery_rate 5058864bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:58310 52.88.142.33:443 timer(keepalive,2min33sec,0) uid:1024 inode:143231822 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:211.152/22.951 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:46445 bytes_acked:46409 bytes_received:48039 segs_out:2072 segs_in:2598 send 548610bps lastsnd:146234 lastrcv:146236 lastack:146029 pacing_rate 1097216bps delivery_rate 120648bps rcv_space:14480 +tcp ESTAB 0 0 127.0.0.1:34526 127.0.0.1:6379 timer(keepalive,10sec,0) uid:386 inode:164791620 sk:ef22 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb4978722,t0,tb4194304,f0,w0,o0,bl0,d352) ts sack cubic wscale:7,7 rtt:0.301/0.282 ato:40 mss:65483 cwnd:34 pmtu:65535 ssthresh:16 bytes_sent:349068015 bytes_acked:348908438 bytes_received:1737331568 segs_out:51994 segs_in:100170 send 59174006645bps lastsnd:609 lastrcv:609 lastack:609 pacing_rate 71008807968bps delivery_rate 104772800000bps rcv_space:245440 +tcp ESTAB 0 0 127.0.0.1:49798 127.0.0.1:3000 uid:0 inode:164815425 sk:17e9 cgroup:/system.slice/pmcd.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:5.821/8.743 ato:40 mss:65483 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:95302 bytes_acked:95303 bytes_received:3077768 segs_out:1880 segs_in:1389 send 899955334bps lastsnd:9970 lastrcv:9968 lastack:9968 pacing_rate 1799678784bps delivery_rate 40297230768bps rcv_space:65495 +tcp ESTAB 0 0 192.168.122.1:53100 192.168.122.54:22 timer(keepalive,2min22sec,0) uid:1024 inode:152890200 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d11) ts sack cubic wscale:7,7 rtt:6.415/11.95 ato:40 mss:1448 cwnd:20 pmtu:1500 ssthresh:20 bytes_sent:65329 bytes_acked:65330 bytes_received:138089 segs_out:2145 segs_in:1352 send 36115355bps lastsnd:6216424 lastrcv:6216231 lastack:157163 pacing_rate 43332512bps delivery_rate 1079864400bps rcv_space:14480 +tcp ESTAB 0 0 [::ffff:127.0.0.1]:3000 [::ffff:127.0.0.1]:49798 timer(keepalive,5.031ms,0) uid:378 inode:164821548 sk:17e9 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb2358342,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.029/0.019 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:3077768 bytes_acked:3077768 bytes_received:95302 segs_out:1388 segs_in:1880 send 90394482759bps lastsnd:9969 lastrcv:9971 lastack:9969 pacing_rate 178481021272bps delivery_rate 65536000000bps rcv_space:65664 +tcp ESTAB 23 0 10.0.0.10:37330 217.182.79.119:6667 timer(on,543ms,0) uid:1024 inode:147037462 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2467768,t0,tb87040,f2793,w1303,o0,bl0,d15) ts sack cubic wscale:7,7 rtt:377.613/33.401 ato:40 mss:1448 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:149848 bytes_acked:149435 bytes_received:440822 segs_out:13042 segs_in:6567 send 61354bps lastsnd:39 lastrcv:29806 lastack:29806 pacing_rate 73624bps delivery_rate 36280bps rcv_space:64371 +tcp ESTAB 23 0 10.40.192.134:47862 10.0.15.20:6667 timer(on,614ms,0) uid:1024 inode:143267906 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb181972,t0,tb46080,f2793,w1303,o0,bl0,d56) ts sack cubic wscale:8,7 rtt:453.799/37.471 ato:40 mss:1308 cwnd:2 pmtu:1360 ssthresh:2 bytes_sent:387993 bytes_acked:386592 bytes_received:72874142 segs_out:117097 segs_in:108401 send 46117bps lastsnd:40 lastrcv:6050 lastack:22432 pacing_rate 55336bps delivery_rate 24936bps rcv_space:19026 +tcp TIME-WAIT 0 0 10.0.0.10:54774 10.0.0.10:44322 timer(timewait,,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54784 10.0.0.10:44322 timer(timewait,,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54792 10.0.0.10:44322 timer(timewait,,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54794 10.0.0.10:44322 timer(timewait,2.383ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54796 10.0.0.10:44322 timer(timewait,350ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54798 10.0.0.10:44322 timer(timewait,222ms,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54800 10.0.0.10:44322 timer(timewait,354ms,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54802 10.0.0.10:44322 timer(timewait,3.376ms,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54804 10.0.0.10:44322 timer(timewait,1.440ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54806 10.0.0.10:44322 timer(timewait,1.441ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54808 10.0.0.10:44322 timer(timewait,2.383ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54810 10.0.0.10:44322 timer(timewait,4.343ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54812 10.0.0.10:44322 timer(timewait,5.358ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54814 10.0.0.10:44322 timer(timewait,3.380ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54816 10.0.0.10:44322 timer(timewait,4.219ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54818 10.0.0.10:44322 timer(timewait,6.800ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54820 10.0.0.10:44322 timer(timewait,4.339ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54822 10.0.0.10:44322 timer(timewait,8.347ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54824 10.0.0.10:44322 timer(timewait,5.225ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54826 10.0.0.10:44322 timer(timewait,5.357ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54830 10.0.0.10:44322 timer(timewait,7.365ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54832 10.0.0.10:44322 timer(timewait,6.800ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54834 10.0.0.10:44322 timer(timewait,6.831ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54836 10.0.0.10:44322 timer(timewait,7.364ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54838 10.0.0.10:44322 timer(timewait,9.447ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54840 10.0.0.10:44322 timer(timewait,8.342ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54842 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54846 10.0.0.10:44322 timer(timewait,9.223ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54850 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54852 10.0.0.10:44322 timer(timewait,9.426ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54854 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54856 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54858 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54860 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54862 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54864 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54866 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54868 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54870 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54872 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54874 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54876 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54878 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54880 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54882 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54884 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54886 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54888 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54890 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54892 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54894 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54896 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54898 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54900 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54902 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54904 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54906 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54910 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54914 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54916 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54920 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54922 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54926 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54928 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54930 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54932 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54936 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54938 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54942 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54944 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54948 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54952 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54954 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54956 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54958 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54960 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54962 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54964 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54966 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54968 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54972 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54974 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54976 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54978 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54980 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54982 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54984 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54986 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54988 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54990 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54992 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54994 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54996 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54998 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55000 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55002 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55004 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55006 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55008 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55012 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55014 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55016 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55018 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55020 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55022 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55024 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55026 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55028 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55030 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55032 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55034 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55036 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55038 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55040 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55042 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55044 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55046 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55048 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55050 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55052 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55054 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55056 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55058 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55060 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55062 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55064 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55066 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55068 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55070 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55072 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55074 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55078 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55080 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55082 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55084 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55086 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55088 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55090 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55092 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55094 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55096 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55100 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55102 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55106 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55108 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55110 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55112 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55114 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55116 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55118 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35754 142.251.10.189:443 uid:1024 inode:165318004 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35983 142.250.70.142:443 uid:1024 inode:165466809 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:36244 142.250.70.138:443 uid:1024 inode:165293889 sk:f231 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:37128 142.250.70.138:443 uid:1024 inode:165585835 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:44639 142.250.70.131:443 uid:1024 inode:165411837 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:49113 142.250.70.131:443 uid:1024 inode:165606514 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:49123 142.250.4.189:443 uid:1024 inode:165373416 sk:ef33 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 + +pcp-ss output, at specific start time +# Time: 2021-06-18 13:33:39 Filter: state connected +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +tcp ESTAB 0 0 [::1]:3000 [::1]:51232 timer(keepalive,4.425ms,0) uid:378 inode:165581925 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.392/0.759 ato:40 mss:65464 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:10191280 bytes_acked:10158498 bytes_received:278267 segs_out:992 segs_in:851 send 13360000000bps lastsnd:607 lastrcv:760 lastack:607 pacing_rate 26677465768bps delivery_rate 174570666664bps rcv_space:65464 +tcp ESTAB 0 0 [::1]:51228 [::1]:3000 timer(keepalive,43sec,0) uid:1024 inode:165582929 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:2.415/4.642 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:265964 bytes_acked:265965 bytes_received:6993639 segs_out:842 segs_in:867 send 1085482402bps lastsnd:759 lastrcv:623 lastack:623 pacing_rate 2170964800bps delivery_rate 87381333328bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51232 [::1]:3000 timer(keepalive,43sec,0) uid:1024 inode:165552950 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d3) ts sack cubic wscale:7,7 rtt:3.701/7.013 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:278267 bytes_acked:278268 bytes_received:10158498 segs_out:851 segs_in:993 send 708305863bps lastsnd:760 lastrcv:607 lastack:607 pacing_rate 1416324704bps delivery_rate 87381333328bps rcv_space:163840 +tcp ESTAB 0 0 [::1]:51236 [::1]:3000 timer(keepalive,40sec,0) uid:1024 inode:165575931 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4585000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.942/1.793 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:274616 bytes_acked:274617 bytes_received:12991541 segs_out:925 segs_in:1058 send 2782845011bps lastsnd:4761 lastrcv:4697 lastack:4697 pacing_rate 5564213312bps delivery_rate 65536000000bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51238 [::1]:3000 timer(keepalive,6.381ms,0) uid:1024 inode:165581951 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d1) ts sack cubic wscale:7,7 rtt:4.48/8.875 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:238691 bytes_acked:238692 bytes_received:6294114 segs_out:626 segs_in:849 send 585142857bps lastsnd:758 lastrcv:616 lastack:616 pacing_rate 1170122464bps delivery_rate 87381333328bps rcv_space:65476 +tcp ESTAB 0 0 [::1]:51240 [::1]:3000 timer(keepalive,10sec,0) uid:1024 inode:165583008 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:4.388/8.395 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:247230 bytes_acked:247231 bytes_received:6274312 segs_out:642 segs_in:867 send 597411121bps lastsnd:764 lastrcv:635 lastack:635 pacing_rate 1194686104bps delivery_rate 87381333328bps rcv_space:65476 +tcp ESTAB 0 0 127.0.0.1:6379 127.0.0.1:34526 timer(keepalive,40sec,0) uid:379 inode:164789635 sk:17e9 cgroup:/system.slice/redis.service <-> skmem(r0,rb6291456,t0,tb4194304,f0,w0,o0,bl0,d191) ts sack cubic wscale:7,7 rtt:5.308/10.357 ato:40 mss:65483 cwnd:37 pmtu:65535 ssthresh:27 bytes_sent:1741543822 bytes_acked:1736716332 bytes_received:348902250 segs_out:100169 segs_in:51994 send 3651651846bps lastsnd:609 lastrcv:609 lastack:568 pacing_rate 4381982208bps delivery_rate 69848533328bps rcv_space:1379162 +tcp ESTAB 0 0 10.0.0.10:33256 10.0.0.6:8009 timer(keepalive,14sec,0) uid:1024 inode:161634072 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2554304,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:6,7 rtt:7.135/1.044 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:734658 bytes_acked:734549 bytes_received:739568 segs_out:13349 segs_in:6686 send 16235459bps lastsnd:524 lastrcv:516 lastack:516 pacing_rate 32468640bps delivery_rate 7613536bps rcv_space:65491 +tcp ESTAB 0 0 10.0.0.10:34914 142.250.70.234:443 uid:1024 inode:165418039 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d11) ts sack cubic wscale:8,7 rtt:10.278/0.678 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:22452 bytes_acked:22453 bytes_received:16959 segs_out:307 segs_in:321 send 11037167bps lastsnd:11065 lastrcv:10735 lastack:10735 pacing_rate 22073256bps delivery_rate 2827752bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:34916 142.250.70.234:443 uid:1024 inode:165418040 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d9) ts sack cubic wscale:8,7 rtt:10.081/1.167 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:19775 bytes_acked:19776 bytes_received:15769 segs_out:277 segs_in:301 send 11252852bps lastsnd:11066 lastrcv:11066 lastack:11056 pacing_rate 22505424bps delivery_rate 3209656bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:37256 157.240.8.18:443 timer(keepalive,2min53sec,0) uid:1024 inode:163353710 sk:262 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb1623296,t0,tb46080,f0,w0,o0,bl0,d37) ts sack cubic wscale:8,7 rtt:21.5/0.94 ato:40 mss:1380 cwnd:22 pmtu:1500 ssthresh:22 bytes_sent:71046 bytes_acked:71015 bytes_received:222343 segs_out:4414 segs_in:4458 send 11296744bps lastsnd:1471 lastrcv:1255 lastack:1449 pacing_rate 13556008bps delivery_rate 9819152bps rcv_space:87463 +tcp ESTAB 0 0 10.0.0.10:39906 172.217.194.188:5228 timer(keepalive,6.702ms,0) uid:1024 inode:164287111 sk:eacd cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:94.893/7.701 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:893 bytes_acked:894 bytes_received:5528 segs_out:187 segs_in:187 send 1195452bps lastsnd:1336001 lastrcv:1335906 lastack:38204 pacing_rate 2390880bps delivery_rate 229032bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40218 142.250.70.142:443 uid:1024 inode:165413160 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d16) ts sack cubic wscale:8,7 rtt:10.371/0.673 ato:40 mss:1418 cwnd:3 pmtu:1500 ssthresh:2 bytes_sent:128059 bytes_acked:122619 bytes_received:60993 segs_out:493 segs_in:558 send 3281458bps lastsnd:48748 lastrcv:48749 lastack:48739 pacing_rate 3937552bps delivery_rate 2269480bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40226 13.54.123.156:443 timer(keepalive,8.158ms,0) uid:1024 inode:163971400 sk:3b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2673664,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:23.038/1.11 ato:46 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:13434 bytes_acked:13435 bytes_received:76107 segs_out:671 segs_in:482 send 4472610bps lastsnd:22123 lastrcv:22098 lastack:22098 pacing_rate 8945216bps delivery_rate 1318208bps rcv_space:67012 +tcp ESTAB 0 0 10.0.0.10:40232 13.54.123.156:443 timer(keepalive,15sec,0) uid:1024 inode:164254779 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2730360,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:21.965/0.395 ato:42 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:21565 bytes_acked:21566 bytes_received:71362 segs_out:842 segs_in:526 send 4691099bps lastsnd:9624 lastrcv:9601 lastack:9601 pacing_rate 9381984bps delivery_rate 1362840bps rcv_space:67755 +tcp ESTAB 0 0 10.0.0.10:43990 142.250.70.131:443 uid:1024 inode:165420073 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:9.654/0.506 ato:40 mss:1418 cwnd:4 pmtu:1500 ssthresh:4 bytes_sent:10189 bytes_acked:10000 bytes_received:16620 segs_out:246 segs_in:410 send 4700228bps lastsnd:17768 lastrcv:17783 lastack:17759 pacing_rate 5640272bps delivery_rate 2983168bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44322 10.0.0.10:55122 timer(keepalive,44sec,0) uid:386 inode:165594717 sk:5 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:5.315/10.43 ato:40 mss:65483 cwnd:17 pmtu:65535 ssthresh:17 bytes_sent:3451325 bytes_acked:3451325 bytes_received:8189 segs_out:65 segs_in:47 send 1675576294bps lastsnd:609 lastrcv:611 lastack:567 pacing_rate 2010691552bps delivery_rate 130966000000bps rcv_space:65483 +tcp ESTAB 0 0 10.0.0.10:44388 142.250.4.189:443 uid:1024 inode:165419510 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:96.696/2.871 ato:40 mss:1418 cwnd:7 pmtu:1500 ssthresh:7 bytes_sent:10276 bytes_acked:9774 bytes_received:14545 segs_out:207 segs_in:207 send 821213bps lastsnd:17146 lastrcv:17036 lastack:17036 pacing_rate 985448bps delivery_rate 467400bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44852 202.58.9.228:443 timer(keepalive,43sec,0) uid:1024 inode:143675936 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1769) sack cubic wscale:9,7 rtt:98.707/11.472 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:6723 bytes_acked:6724 bytes_received:9572 segs_out:8675 segs_in:8669 send 1183300bps lastsnd:8818069 lastrcv:8817969 lastack:1340 pacing_rate 2366592bps delivery_rate 480352bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:45164 173.194.202.125:443 timer(keepalive,23sec,0) uid:1024 inode:161888302 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:228.663/49.231 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:11353 bytes_acked:11354 bytes_received:23756 segs_out:890 segs_in:895 send 496101bps lastsnd:207468 lastrcv:207250 lastack:21813 pacing_rate 992200bps delivery_rate 103864bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46306 3.233.54.64:443 timer(keepalive,23sec,0) uid:1024 inode:165592357 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:246.45/50.358 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3814 bytes_acked:3815 bytes_received:4765 segs_out:12 segs_in:12 send 470034bps lastsnd:22071 lastrcv:21847 lastack:21848 pacing_rate 940064bps delivery_rate 120016bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46392 142.251.10.189:443 uid:1024 inode:165466671 sk:f23b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d2) ts sack cubic wscale:8,7 rtt:111.69/24.888 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:8645 bytes_acked:8646 bytes_received:12265 segs_out:135 segs_in:139 send 1015668bps lastsnd:52309 lastrcv:25403 lastack:50572 pacing_rate 2031320bps delivery_rate 335272bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:49594 142.250.70.165:443 timer(keepalive,6.621ms,0) uid:1024 inode:165410113 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb1074240,t0,tb87040,f0,w0,o0,bl0,d6) ts sack cubic wscale:8,7 rtt:11.987/1.417 ato:40 mss:1418 cwnd:18 pmtu:1500 ssthresh:0 bytes_sent:76222 bytes_acked:76223 bytes_received:199808 segs_out:342 segs_in:404 send 17034454bps lastsnd:218733 lastrcv:218735 lastack:38371 pacing_rate 34068192bps delivery_rate 8192584bps rcv_space:75339 +tcp ESTAB 0 0 10.0.0.10:49614 142.250.70.165:443 uid:1024 inode:165581235 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:10.118/1.177 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3573 bytes_acked:3574 bytes_received:2558 segs_out:20 segs_in:19 send 11211702bps lastsnd:27596 lastrcv:27584 lastack:27584 pacing_rate 22423400bps delivery_rate 3963936bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:52874 199.127.207.181:443 timer(keepalive,23sec,0) uid:1024 inode:154981923 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d433) sack cubic wscale:9,7 rtt:231.99/42.333 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3792 bytes_acked:3793 bytes_received:6931 segs_out:2107 segs_in:2102 send 503470bps lastsnd:78116165 lastrcv:78116159 lastack:21772 pacing_rate 1006936bps delivery_rate 206000bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:55104 10.0.0.10:44322 timer(keepalive,26sec,0) uid:378 inode:165606577 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb6291456,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:8.43/11.76 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:8252 bytes_acked:8253 bytes_received:3480217 segs_out:178 segs_in:356 send 310965599bps lastsnd:756 lastrcv:637 lastack:639 pacing_rate 621875864bps delivery_rate 20164923072bps rcv_space:469929 +tcp ESTAB 0 0 10.0.0.10:55122 10.0.0.10:44322 timer(keepalive,29sec,0) uid:378 inode:165608516 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb3013437,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.236/0.425 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:37 bytes_acked:37 bytes_received:15171 segs_out:47 segs_in:66 send 11107796610bps lastsnd:611 lastrcv:609 lastack:609 pacing_rate 22145216472bps delivery_rate 32768000000bps rcv_space:81920 +tcp ESTAB 0 0 10.0.0.10:55308 142.250.70.228:443 uid:1024 inode:165561257 sk:eb1c cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d3) ts sack cubic wscale:8,7 rtt:11.532/2.782 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:3051 bytes_acked:3052 bytes_received:4379 segs_out:38 segs_in:36 send 9836975bps lastsnd:46596 lastrcv:46586 lastack:46587 pacing_rate 19672664bps delivery_rate 1814168bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55532 140.82.114.26:443 timer(keepalive,9.693ms,0) uid:1024 inode:165515920 sk:17eb cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:251.743/35.839 ato:40 mss:1424 cwnd:20 pmtu:1500 ssthresh:0 bytes_sent:17930 bytes_acked:17931 bytes_received:4200 segs_out:49 segs_in:46 send 905050bps lastsnd:20795 lastrcv:20795 lastack:20571 pacing_rate 1810096bps delivery_rate 503048bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55534 140.82.114.26:443 timer(keepalive,28sec,0) uid:1024 inode:165521771 sk:ef38 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:283.095/41.806 ato:40 mss:1424 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:2643 bytes_acked:2644 bytes_received:3981 segs_out:36 segs_in:38 send 402409bps lastsnd:2669 lastrcv:2669 lastack:2444 pacing_rate 804816bps delivery_rate 73400bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55694 34.120.177.193:443 timer(keepalive,2.525ms,0) uid:1024 inode:165577700 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:8,7 rtt:13.091/4.789 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:1234 bytes_acked:1235 bytes_received:5268 segs_out:21 segs_in:20 send 8665495bps lastsnd:224263 lastrcv:224265 lastack:42465 pacing_rate 17330160bps delivery_rate 2267288bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:57232 157.240.8.35:443 uid:1024 inode:165408121 sk:1781 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb46080,f8192,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:23.193/1.8 ato:40 mss:1380 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:69963 bytes_acked:68311 bytes_received:28389 segs_out:252 segs_in:206 send 952011bps lastsnd:6934 lastrcv:6458 lastack:6458 pacing_rate 1142400bps delivery_rate 371224bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:57958 142.250.70.238:443 uid:1024 inode:165594185 sk:183a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:8,7 rtt:10.608/1.213 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:7836 bytes_acked:7837 bytes_received:3104 segs_out:27 segs_in:27 send 10693816bps lastsnd:18595 lastrcv:18584 lastack:18584 pacing_rate 21387376bps delivery_rate 5058864bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:58310 52.88.142.33:443 timer(keepalive,2min33sec,0) uid:1024 inode:143231822 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:211.152/22.951 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:46445 bytes_acked:46409 bytes_received:48039 segs_out:2072 segs_in:2598 send 548610bps lastsnd:146234 lastrcv:146236 lastack:146029 pacing_rate 1097216bps delivery_rate 120648bps rcv_space:14480 +tcp ESTAB 0 0 127.0.0.1:34526 127.0.0.1:6379 timer(keepalive,10sec,0) uid:386 inode:164791620 sk:ef22 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb4978722,t0,tb4194304,f0,w0,o0,bl0,d352) ts sack cubic wscale:7,7 rtt:0.301/0.282 ato:40 mss:65483 cwnd:34 pmtu:65535 ssthresh:16 bytes_sent:349061810 bytes_acked:348902251 bytes_received:1736716332 segs_out:51994 segs_in:100170 send 59174006645bps lastsnd:609 lastrcv:609 lastack:609 pacing_rate 71008807968bps delivery_rate 104772800000bps rcv_space:245440 +tcp ESTAB 0 0 127.0.0.1:49798 127.0.0.1:3000 uid:0 inode:164815425 sk:17e9 cgroup:/system.slice/pmcd.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:5.821/8.743 ato:40 mss:65483 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:95300 bytes_acked:95301 bytes_received:3077689 segs_out:1880 segs_in:1389 send 899955334bps lastsnd:9970 lastrcv:9968 lastack:9968 pacing_rate 1799678784bps delivery_rate 40297230768bps rcv_space:65495 +tcp ESTAB 0 0 192.168.122.1:53100 192.168.122.54:22 timer(keepalive,2min22sec,0) uid:1024 inode:152890200 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d11) ts sack cubic wscale:7,7 rtt:6.415/11.95 ato:40 mss:1448 cwnd:20 pmtu:1500 ssthresh:20 bytes_sent:65329 bytes_acked:65330 bytes_received:138089 segs_out:2145 segs_in:1352 send 36115355bps lastsnd:6216424 lastrcv:6216231 lastack:157163 pacing_rate 43332512bps delivery_rate 1079864400bps rcv_space:14480 +tcp ESTAB 0 0 [::ffff:127.0.0.1]:3000 [::ffff:127.0.0.1]:49798 timer(keepalive,5.031ms,0) uid:378 inode:164821548 sk:17e9 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb2358342,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.029/0.019 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:3077689 bytes_acked:3077689 bytes_received:95300 segs_out:1388 segs_in:1880 send 90394482759bps lastsnd:9969 lastrcv:9971 lastack:9969 pacing_rate 178481021272bps delivery_rate 65536000000bps rcv_space:65664 +tcp ESTAB 23 0 10.0.0.10:37330 217.182.79.119:6667 timer(on,543ms,0) uid:1024 inode:147037462 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2467768,t0,tb87040,f2793,w1303,o0,bl0,d15) ts sack cubic wscale:7,7 rtt:377.613/33.401 ato:40 mss:1448 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:149848 bytes_acked:149434 bytes_received:440821 segs_out:13042 segs_in:6567 send 61354bps lastsnd:39 lastrcv:29806 lastack:29806 pacing_rate 73624bps delivery_rate 36280bps rcv_space:64371 +tcp ESTAB 23 0 10.40.192.134:47862 10.0.15.20:6667 timer(on,614ms,0) uid:1024 inode:143267906 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb181972,t0,tb46080,f2793,w1303,o0,bl0,d56) ts sack cubic wscale:8,7 rtt:453.799/37.471 ato:40 mss:1308 cwnd:2 pmtu:1360 ssthresh:2 bytes_sent:387993 bytes_acked:386591 bytes_received:72874141 segs_out:117097 segs_in:108401 send 46117bps lastsnd:40 lastrcv:6050 lastack:22432 pacing_rate 55336bps delivery_rate 24936bps rcv_space:19026 +tcp TIME-WAIT 0 0 10.0.0.10:54774 10.0.0.10:44322 timer(timewait,,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54784 10.0.0.10:44322 timer(timewait,,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54792 10.0.0.10:44322 timer(timewait,,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54794 10.0.0.10:44322 timer(timewait,2.383ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54796 10.0.0.10:44322 timer(timewait,350ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54798 10.0.0.10:44322 timer(timewait,222ms,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54800 10.0.0.10:44322 timer(timewait,354ms,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54802 10.0.0.10:44322 timer(timewait,3.376ms,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54804 10.0.0.10:44322 timer(timewait,1.440ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54806 10.0.0.10:44322 timer(timewait,1.441ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54808 10.0.0.10:44322 timer(timewait,2.383ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54810 10.0.0.10:44322 timer(timewait,4.343ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54812 10.0.0.10:44322 timer(timewait,5.358ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54814 10.0.0.10:44322 timer(timewait,3.380ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54816 10.0.0.10:44322 timer(timewait,4.219ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54818 10.0.0.10:44322 timer(timewait,6.800ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54820 10.0.0.10:44322 timer(timewait,4.339ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54822 10.0.0.10:44322 timer(timewait,8.347ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54824 10.0.0.10:44322 timer(timewait,5.225ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54826 10.0.0.10:44322 timer(timewait,5.357ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54830 10.0.0.10:44322 timer(timewait,7.365ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54832 10.0.0.10:44322 timer(timewait,6.800ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54834 10.0.0.10:44322 timer(timewait,6.831ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54836 10.0.0.10:44322 timer(timewait,7.364ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54838 10.0.0.10:44322 timer(timewait,9.447ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54840 10.0.0.10:44322 timer(timewait,8.342ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54842 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54846 10.0.0.10:44322 timer(timewait,9.223ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54850 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54852 10.0.0.10:44322 timer(timewait,9.426ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54854 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54856 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54858 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54860 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54862 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54864 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54866 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54868 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54870 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54872 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54874 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54876 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54878 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54880 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54882 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54884 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54886 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54888 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54890 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54892 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54894 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54896 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54898 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54900 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54902 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54904 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54906 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54910 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54914 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54916 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54920 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54922 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54926 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54928 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54930 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54932 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54936 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54938 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54942 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54944 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54948 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54952 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54954 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54956 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54958 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54960 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54962 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54964 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54966 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54968 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54972 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54974 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54976 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54978 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54980 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54982 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54984 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54986 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54988 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54990 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54992 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54994 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54996 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:54998 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55000 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55002 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55004 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55006 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55008 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55012 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55014 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55016 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55018 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55020 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55022 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55024 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55026 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55028 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55030 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55032 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55034 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55036 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55038 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55040 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55042 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55044 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55046 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55048 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55050 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55052 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55054 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55056 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55058 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55060 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55062 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55064 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55066 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55068 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55070 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55072 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55074 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55078 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55080 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55082 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55084 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55086 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55088 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55090 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55092 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55094 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55096 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55100 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55102 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55106 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55108 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55110 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55112 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55114 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55116 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55118 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35754 142.251.10.189:443 uid:1024 inode:165318004 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35983 142.250.70.142:443 uid:1024 inode:165466809 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:36244 142.250.70.138:443 uid:1024 inode:165293889 sk:f231 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:37128 142.250.70.138:443 uid:1024 inode:165585835 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:44639 142.250.70.131:443 uid:1024 inode:165411837 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:49113 142.250.70.131:443 uid:1024 inode:165606514 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:49123 142.250.4.189:443 uid:1024 inode:165373416 sk:ef33 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 + +pcp-ss output, at archive end +# Time: 2021-06-18 13:34:14.168998 Filter: state connected +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +tcp ESTAB 0 0 [::1]:3000 [::1]:51232 timer(keepalive,8.488ms,0) uid:378 inode:165581925 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.014/0.011 ato:40 mss:65464 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65464 +tcp ESTAB 0 0 [::1]:51228 [::1]:3000 timer(keepalive,3.596ms,0) uid:1024 inode:165582929 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.422/0.763 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51232 [::1]:3000 timer(keepalive,3.596ms,0) uid:1024 inode:165552950 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4978000,t0,tb2626560,f0,w0,o0,bl0,d3) ts sack cubic wscale:7,7 rtt:8.219/14.257 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:163840 +tcp ESTAB 0 0 [::1]:51236 [::1]:3000 timer(keepalive,514ms,0) uid:1024 inode:165575931 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb4585000,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:5.713/10.966 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:98304 +tcp ESTAB 0 0 [::1]:51238 [::1]:3000 timer(keepalive,11sec,0) uid:1024 inode:165581951 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d1) ts sack cubic wscale:7,7 rtt:4.802/9.371 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65476 +tcp ESTAB 0 0 [::1]:51240 [::1]:3000 timer(keepalive,15sec,0) uid:1024 inode:165583008 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.783/1.488 ato:40 mss:32768 cwnd:10 pmtu:65536 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65476 +tcp ESTAB 0 0 127.0.0.1:6379 127.0.0.1:34526 timer(keepalive,299ms,0) uid:379 inode:164789635 sk:17e9 cgroup:/system.slice/redis.service <-> skmem(r0,rb6291456,t0,tb4194304,f0,w0,o0,bl0,d226) ts sack cubic wscale:7,7 rtt:5.268/10.344 ato:40 mss:65483 cwnd:51 pmtu:65535 ssthresh:27 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:1379162 +tcp ESTAB 0 0 10.0.0.10:33256 10.0.0.6:8009 timer(keepalive,19sec,0) uid:1024 inode:161634072 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2554304,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:6,7 rtt:7.326/1.581 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65491 +tcp ESTAB 0 0 10.0.0.10:34914 142.250.70.234:443 uid:1024 inode:165418039 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d11) ts sack cubic wscale:8,7 rtt:10.278/0.678 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:34916 142.250.70.234:443 uid:1024 inode:165418040 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d9) ts sack cubic wscale:8,7 rtt:10.081/1.167 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:37256 157.240.8.18:443 timer(keepalive,2min13sec,0) uid:1024 inode:163353710 sk:262 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb1623296,t0,tb46080,f4096,w0,o0,bl0,d37) ts sack cubic wscale:8,7 rtt:21.667/1.031 ato:40 mss:1380 cwnd:22 pmtu:1500 ssthresh:22 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:87463 +tcp ESTAB 0 0 10.0.0.10:37330 217.182.79.119:6667 timer(keepalive,3min20sec,0) uid:1024 inode:147037462 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2467768,t0,tb87040,f0,w0,o0,bl0,d15) ts sack cubic wscale:7,7 rtt:381.926/27.664 ato:40 mss:1448 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:64371 +tcp ESTAB 0 0 10.0.0.10:39906 172.217.194.188:5228 timer(keepalive,15sec,0) uid:1024 inode:164287111 sk:eacd cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:94.893/7.701 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40218 142.250.70.142:443 uid:1024 inode:165413160 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d16) ts sack cubic wscale:8,7 rtt:10.194/0.696 ato:40 mss:1418 cwnd:3 pmtu:1500 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:40226 13.54.123.156:443 timer(keepalive,28sec,0) uid:1024 inode:163971400 sk:3b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2673664,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:23.063/0.882 ato:46 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:67012 +tcp ESTAB 0 0 10.0.0.10:40232 13.54.123.156:443 timer(keepalive,15sec,0) uid:1024 inode:164254779 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb2730360,t0,tb46080,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:21.7/0.326 ato:42 mss:1288 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:67755 +tcp ESTAB 0 0 10.0.0.10:43990 142.250.70.131:443 uid:1024 inode:165420073 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:9.826/0.515 ato:40 mss:1418 cwnd:4 pmtu:1500 ssthresh:4 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44322 10.0.0.10:55342 timer(keepalive,44sec,0) uid:386 inode:165594871 sk:5 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.05/0.056 ato:40 mss:65483 cwnd:20 pmtu:65535 ssthresh:20 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65483 +tcp ESTAB 0 0 10.0.0.10:44388 142.250.4.189:443 uid:1024 inode:165419510 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:96.696/2.871 ato:40 mss:1418 cwnd:7 pmtu:1500 ssthresh:7 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:44852 202.58.9.228:443 timer(keepalive,3.777ms,0) uid:1024 inode:143675936 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1770) sack cubic wscale:9,7 rtt:98.707/11.472 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:45164 173.194.202.125:443 timer(keepalive,28sec,0) uid:1024 inode:161888302 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:228.663/49.231 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46306 3.233.54.64:443 timer(keepalive,28sec,0) uid:1024 inode:165592357 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:12,7 rtt:246.45/50.358 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:46392 142.251.10.189:443 uid:1024 inode:165466671 sk:f23b cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f4096,w0,o0,bl0,d3) ts sack cubic wscale:8,7 rtt:111.69/24.888 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:49614 142.250.70.165:443 uid:1024 inode:165581235 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:8,7 rtt:10.2/1.047 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:52874 199.127.207.181:443 timer(keepalive,28sec,0) uid:1024 inode:154981923 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d433) sack cubic wscale:9,7 rtt:231.99/42.333 ato:40 mss:1460 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14600 +tcp ESTAB 0 0 10.0.0.10:55332 10.0.0.10:44322 timer(keepalive,28sec,0) uid:378 inode:165581545 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb4454646,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:3.728/6.7 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:105770 +tcp ESTAB 0 0 10.0.0.10:55342 10.0.0.10:44322 timer(keepalive,29sec,0) uid:378 inode:165616642 sk:5 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb2882418,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.041/0.024 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:73728 +tcp ESTAB 0 0 10.0.0.10:55532 140.82.114.26:443 timer(keepalive,29sec,0) uid:1024 inode:165515920 sk:17eb cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:248.861/32.644 ato:40 mss:1424 cwnd:20 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55534 140.82.114.26:443 timer(keepalive,2.767ms,0) uid:1024 inode:165521771 sk:ef38 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) ts sack cubic wscale:10,7 rtt:283.095/41.806 ato:40 mss:1424 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:55694 34.120.177.193:443 timer(keepalive,7.793ms,0) uid:1024 inode:165577700 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d1) ts sack cubic wscale:8,7 rtt:13.091/4.789 ato:40 mss:1418 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:57232 157.240.8.35:443 uid:1024 inode:165408121 sk:1781 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb46080,f8192,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:23.193/1.8 ato:40 mss:1380 cwnd:2 pmtu:1500 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 10.0.0.10:58310 52.88.142.33:443 timer(keepalive,1min53sec,0) uid:1024 inode:143231822 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d4) ts sack cubic wscale:8,7 rtt:211.152/22.951 ato:40 mss:1448 cwnd:10 pmtu:1500 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 127.0.0.1:34526 127.0.0.1:6379 timer(keepalive,646ms,0) uid:386 inode:164791620 sk:ef22 cgroup:/system.slice/pmproxy.service <-> skmem(r0,rb4978722,t0,tb4194304,f0,w0,o0,bl0,d397) ts sack cubic wscale:7,7 rtt:0.217/0.167 ato:40 mss:65483 cwnd:36 pmtu:65535 ssthresh:16 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:245440 +tcp ESTAB 0 0 127.0.0.1:49798 127.0.0.1:3000 uid:0 inode:164815425 sk:17e9 cgroup:/system.slice/pmcd.service <-> skmem(r0,rb131072,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:6.023/4.348 ato:40 mss:65483 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65495 +tcp ESTAB 0 0 10.40.192.134:47862 10.0.15.20:6667 timer(keepalive,2min48sec,0) uid:1024 inode:143267906 sk:39 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb181972,t0,tb46080,f0,w0,o0,bl0,d56) ts sack cubic wscale:8,7 rtt:456.275/44.255 ato:40 mss:1308 cwnd:2 pmtu:1360 ssthresh:2 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:19026 +tcp ESTAB 0 0 192.168.122.1:53100 192.168.122.54:22 timer(keepalive,1min43sec,0) uid:1024 inode:152890200 sk:3a cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d11) ts sack cubic wscale:7,7 rtt:6.415/11.95 ato:40 mss:1448 cwnd:20 pmtu:1500 ssthresh:20 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:14480 +tcp ESTAB 0 0 [::ffff:127.0.0.1]:3000 [::ffff:127.0.0.1]:49798 timer(keepalive,5.265ms,0) uid:378 inode:164821548 sk:17e9 cgroup:/system.slice/grafana-server.service <-> skmem(r0,rb2358342,t0,tb2626560,f0,w0,o0,bl0,d0) ts sack cubic wscale:7,7 rtt:0.033/0.018 ato:40 mss:32768 cwnd:10 pmtu:65535 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:65664 +tcp TIME-WAIT 0 0 10.0.0.10:49594 142.250.70.165:443 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55014 10.0.0.10:44322 timer(timewait,581ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55020 10.0.0.10:44322 timer(timewait,3.571ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55022 10.0.0.10:44322 timer(timewait,586ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55024 10.0.0.10:44322 timer(timewait,1.623ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55026 10.0.0.10:44322 timer(timewait,1.601ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55028 10.0.0.10:44322 timer(timewait,2.601ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55030 10.0.0.10:44322 timer(timewait,1.618ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55032 10.0.0.10:44322 timer(timewait,2.607ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55034 10.0.0.10:44322 timer(timewait,4.636ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55036 10.0.0.10:44322 timer(timewait,3.608ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55038 10.0.0.10:44322 timer(timewait,5.580ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55040 10.0.0.10:44322 timer(timewait,4.635ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55042 10.0.0.10:44322 timer(timewait,6.447ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55044 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55046 10.0.0.10:44322 timer(timewait,5.577ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55048 10.0.0.10:44322 timer(timewait,8.579ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55050 10.0.0.10:44322 timer(timewait,6.570ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55052 10.0.0.10:44322 timer(timewait,6.568ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55054 10.0.0.10:44322 timer(timewait,7.474ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55056 10.0.0.10:44322 timer(timewait,7.623ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55058 10.0.0.10:44322 timer(timewait,7.617ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55060 10.0.0.10:44322 timer(timewait,8.449ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55062 10.0.0.10:44322 timer(timewait,9.618ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55064 10.0.0.10:44322 timer(timewait,8.577ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55066 10.0.0.10:44322 timer(timewait,9.605ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55068 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55070 10.0.0.10:44322 timer(timewait,9.625ms,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55072 10.0.0.10:44322 timer(timewait,10sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55074 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55078 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55080 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55082 10.0.0.10:44322 timer(timewait,11sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55084 10.0.0.10:44322 timer(timewait,12sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55086 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55088 10.0.0.10:44322 timer(timewait,15sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55090 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55092 10.0.0.10:44322 timer(timewait,13sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55094 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55096 10.0.0.10:44322 timer(timewait,14sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55100 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55102 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55104 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55106 10.0.0.10:44322 timer(timewait,16sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55108 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55110 10.0.0.10:44322 timer(timewait,17sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55112 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55114 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55116 10.0.0.10:44322 timer(timewait,18sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55118 10.0.0.10:44322 timer(timewait,19sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55122 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55124 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55126 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55130 10.0.0.10:44322 timer(timewait,20sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55132 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55134 10.0.0.10:44322 timer(timewait,21sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55136 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55138 10.0.0.10:44322 timer(timewait,22sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55140 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55142 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55144 10.0.0.10:44322 timer(timewait,23sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55146 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55148 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55150 10.0.0.10:44322 timer(timewait,24sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55152 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55154 10.0.0.10:44322 timer(timewait,25sec,0) uid:0 inode:0 sk:ef49 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55156 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:ef4b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55158 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:ef4e cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55160 10.0.0.10:44322 timer(timewait,26sec,0) uid:0 inode:0 sk:ef4d cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55162 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:ef4a cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55164 10.0.0.10:44322 timer(timewait,27sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55166 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:ef50 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55168 10.0.0.10:44322 timer(timewait,28sec,0) uid:0 inode:0 sk:ef4c cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55172 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55174 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55176 10.0.0.10:44322 timer(timewait,29sec,0) uid:0 inode:0 sk:17ed cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55178 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55180 10.0.0.10:44322 timer(timewait,30sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55182 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55184 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55186 10.0.0.10:44322 timer(timewait,31sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55188 10.0.0.10:44322 timer(timewait,32sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55190 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55194 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55196 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55200 10.0.0.10:44322 timer(timewait,33sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55204 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55206 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55210 10.0.0.10:44322 timer(timewait,34sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55212 10.0.0.10:44322 timer(timewait,35sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55214 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55216 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55218 10.0.0.10:44322 timer(timewait,36sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55220 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55222 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55224 10.0.0.10:44322 timer(timewait,37sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55226 10.0.0.10:44322 timer(timewait,38sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55228 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55230 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55232 10.0.0.10:44322 timer(timewait,39sec,0) uid:0 inode:0 sk:3b cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55234 10.0.0.10:44322 timer(timewait,40sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55236 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55238 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55240 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55242 10.0.0.10:44322 timer(timewait,41sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55244 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55248 10.0.0.10:44322 timer(timewait,42sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55250 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55254 10.0.0.10:44322 timer(timewait,44sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55256 10.0.0.10:44322 timer(timewait,43sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55260 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55262 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55266 10.0.0.10:44322 timer(timewait,45sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55268 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55270 10.0.0.10:44322 timer(timewait,46sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55272 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55274 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55276 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55278 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55280 10.0.0.10:44322 timer(timewait,47sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55282 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55284 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55286 10.0.0.10:44322 timer(timewait,48sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55288 10.0.0.10:44322 timer(timewait,49sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55292 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:259 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55294 10.0.0.10:44322 timer(timewait,50sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55296 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55298 10.0.0.10:44322 timer(timewait,51sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55300 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55302 10.0.0.10:44322 timer(timewait,52sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55304 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55306 10.0.0.10:44322 timer(timewait,53sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55308 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55310 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55312 10.0.0.10:44322 timer(timewait,54sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55316 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55318 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55320 10.0.0.10:44322 timer(timewait,55sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55322 10.0.0.10:44322 timer(timewait,56sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55326 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55328 10.0.0.10:44322 timer(timewait,57sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55330 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55334 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55338 10.0.0.10:44322 timer(timewait,58sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:55340 10.0.0.10:44322 timer(timewait,59sec,0) uid:0 inode:0 sk:5 cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +tcp TIME-WAIT 0 0 10.0.0.10:57958 142.250.70.238:443 timer(timewait,54sec,0) uid:0 inode:0 sk:183a cgroup: <-> wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35754 142.251.10.189:443 uid:1024 inode:165318004 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:35983 142.250.70.142:443 uid:1024 inode:165466809 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:36244 142.250.70.138:443 uid:1024 inode:165293889 sk:f231 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:44639 142.250.70.131:443 uid:1024 inode:165411837 sk:5 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 +udp ESTAB 0 0 10.0.0.10:49123 142.250.4.189:443 uid:1024 inode:165373416 sk:ef33 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) wscale: rtt: ato:0 mss:0 cwnd:0 pmtu:0 ssthresh:0 bytes_sent:0 bytes_acked:0 bytes_received:0 segs_out:0 segs_in:0 send 0bps lastsnd:0 lastrcv:0 lastack:0 pacing_rate 0bps delivery_rate 0bps rcv_space:0 + +check error handling when metrics not present. Note error is expected +Error: metrics for 'network.persocket' not found in archive archives/pcp-mpstat diff -Nru pcp-5.3.1/qa/1634 pcp-5.3.2/qa/1634 --- pcp-5.3.1/qa/1634 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/qa/1634 2021-07-30 04:05:06.000000000 +0000 @@ -20,33 +20,22 @@ . ./common.filter . ./common.check -do_valgrind=false -if [ "$1" = "--valgrind" ] -then - _check_valgrind - do_valgrind=true -fi - [ $PCP_PLATFORM = linux ] || _notrun "pmdasockets is Linux-specific" [ -f $PCP_PMDAS_DIR/sockets/pmdasockets ] || _notrun "sockets pmda not installed" -pmns=$PCP_PMDAS_DIR/sockets/root -pmda=$PCP_PMDAS_DIR/sockets/pmda_sockets.$DSO_SUFFIX,sockets_init -_make_helptext sockets +# _notrun if valgrind is not installed +_check_valgrind -# override the default contents of PMDA cache files -# (do not want localhost versions to be used here). -# -domain=154 -[ -f $PCP_VAR_DIR/config/pmda/$domain.0 ] && \ -_save_config $PCP_VAR_DIR/config/pmda/$domain.0 -$sudo rm -f $PCP_VAR_DIR/config/pmda/$domain.0 +# Override the pmda's filter.conf +[ -f $PCP_PMDAS_DIR/sockets/filter.conf ] && \ +_save_config $PCP_SYSCONF_DIR/sockets/filter.conf +echo "state connected" >$tmp.filter +$sudo cp $tmp.filter $PCP_SYSCONF_DIR/sockets/filter.conf _cleanup() { cd $here - [ -f $PCP_VAR_DIR/config/pmda/$domain.0.$seq ] && \ - _restore_config $PCP_VAR_DIR/config/pmda/$domain.0 + _restore_config $PCP_SYSCONF_DIR/sockets/filter.conf $sudo rm -rf $tmp $tmp.* } @@ -57,17 +46,22 @@ _filter() { - sed \ - -e 's///' \ - # end + sed -e "s;$tmp;TMP;g" -e '/Unable to open help text file/d' } # real QA test starts here -for f in sockets/ss_noemitauOH.txt sockets/ss_noemitauOH_ubuntu.txt; do +[ ! -d "$tmp" ] && mkdir -p $tmp +qadomain=251 # FORQA +sed -e "/^root/i#undef SOCKETS\n#define SOCKETS $qadomain" <$PCP_PMDAS_DIR/sockets/root >$tmp/root +cp $PCP_PMDAS_DIR/sockets/pmns $tmp/pmns +pmns=$tmp/root +pmda=$PCP_PMDAS_DIR/sockets/pmda_sockets.$DSO_SUFFIX,sockets_init + +for f in `ls -1 sockets/*.txt | LC_COLLATE=POSIX sort`; do echo === testing $f === + $sudo rm -f $PCP_VAR_DIR/config/pmda/$qadomain.0 # reset indom export PCPQA_PMDA_SOCKETS="$f" - $sudo rm -f $PCP_VAR_DIR/config/pmda/$domain.0 - _run_valgrind pminfo -L -K clear -K add,154,$pmda -dfmt -n $pmns network.persocket + _run_valgrind pminfo -L -K clear -K add,$qadomain,$pmda -dfm -n $pmns network.persocket | _filter done # success, all done diff -Nru pcp-5.3.1/qa/1634.out pcp-5.3.2/qa/1634.out --- pcp-5.3.1/qa/1634.out 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/qa/1634.out 2021-07-30 04:05:06.000000000 +0000 @@ -2,13 +2,13 @@ === testing sockets/ss_noemitauOH.txt === === std out === -network.persocket.filter PMID: 154.0.0 [filter for sockets of interest] +network.persocket.filter PMID: 251.0.0 Data Type: string InDom: PM_INDOM_NULL 0xffffffff Semantics: discrete Units: none value "state connected" -network.persocket.netid PMID: 154.1.0 [socket protocol identifier] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.netid PMID: 251.1.0 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "udp" inst [1 or "udp/192.168.1.169:58624"] value "udp" @@ -102,8 +102,8 @@ inst [89 or "tcp6/[::]:44323"] value "tcp" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "tcp" -network.persocket.state PMID: 154.1.1 [socket state as a string, commonly UNCONN, ESTAB, TIME-WAIT] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.state PMID: 251.1.1 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "ESTAB" inst [1 or "udp/192.168.1.169:58624"] value "UNCONN" @@ -197,8 +197,8 @@ inst [89 or "tcp6/[::]:44323"] value "LISTEN" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "ESTAB" -network.persocket.recvq PMID: 154.1.2 [length of the receive queue] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.recvq PMID: 251.1.2 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -292,8 +292,8 @@ inst [89 or "tcp6/[::]:44323"] value 128 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.sendq PMID: 154.1.3 [length of the send queue] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.sendq PMID: 251.1.3 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -387,8 +387,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.src PMID: 154.1.4 [local (source) IP address (IPv4 or IPv6) and port] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.src PMID: 251.1.4 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "10.0.0.10:49693" inst [1 or "udp/192.168.1.169:58624"] value "192.168.1.169:58624" @@ -482,8 +482,8 @@ inst [89 or "tcp6/[::]:44323"] value "[::]:44323" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "[::ffff:127.0.0.1]:3000" -network.persocket.dst PMID: 154.1.5 [destination IP address (IPv4 or IPv6) and port] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.dst PMID: 251.1.5 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "74.125.68.189:443" inst [1 or "udp/192.168.1.169:58624"] value "0.0.0.0:*" @@ -577,8 +577,8 @@ inst [89 or "tcp6/[::]:44323"] value "[::]:*" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "[::ffff:127.0.0.1]:38136" -network.persocket.inode PMID: 154.1.6 [the socket's inode number in VFS] - Data Type: 64-bit int InDom: 154.0 0x26800000 +network.persocket.inode PMID: 251.1.6 + Data Type: 64-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 28605309 inst [1 or "udp/192.168.1.169:58624"] value 19693830 @@ -672,8 +672,8 @@ inst [89 or "tcp6/[::]:44323"] value 28529158 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 28540274 -network.persocket.uid PMID: 154.1.8 [the user id the socket belongs to] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.uid PMID: 251.1.8 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 1024 inst [1 or "udp/192.168.1.169:58624"] value 1024 @@ -767,8 +767,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 378 -network.persocket.sk PMID: 154.1.9 [uuid cookie of the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.sk PMID: 251.1.9 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 976 inst [1 or "udp/192.168.1.169:58624"] value 3154 @@ -862,8 +862,8 @@ inst [89 or "tcp6/[::]:44323"] value 973 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 9745 -network.persocket.cgroup PMID: 154.1.10 [cgroup v2 pathname] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.cgroup PMID: 251.1.10 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "/user.slice/user-1024.slice/session-2.scope" inst [1 or "udp/192.168.1.169:58624"] value "/user.slice/user-1024.slice/session-2.scope" @@ -957,8 +957,8 @@ inst [89 or "tcp6/[::]:44323"] value "/system.slice/pmproxy.service" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "/system.slice/grafana-server.service" -network.persocket.v6only PMID: 154.1.11 [boolean value set to one if the socket is IPv6, 0 otherwise] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.v6only PMID: 251.1.11 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1052,8 +1052,8 @@ inst [89 or "tcp6/[::]:44323"] value 1 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.ts PMID: 154.1.13 [boolean value set to one if the timestamp option is set] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.ts PMID: 251.1.13 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1147,8 +1147,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1 -network.persocket.sack PMID: 154.1.14 [boolean value set to one if the sack option is set] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.sack PMID: 251.1.14 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1242,8 +1242,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1 -network.persocket.cubic PMID: 154.1.15 [boolean value set to one if cubic congestion control is enabled] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.cubic PMID: 251.1.15 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1337,8 +1337,8 @@ inst [89 or "tcp6/[::]:44323"] value 1 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1 -network.persocket.ato PMID: 154.1.16 [ack timeout when using delayed ack mode] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.ato PMID: 251.1.16 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: discrete Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1432,8 +1432,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 40 -network.persocket.mss PMID: 154.1.17 [maximum segment size] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.mss PMID: 251.1.17 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1527,8 +1527,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 32768 -network.persocket.pmtu PMID: 154.1.18 [path maximum transmission unit] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.pmtu PMID: 251.1.18 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1622,8 +1622,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 65535 -network.persocket.rcvmss PMID: 154.1.19 [receive maximum transmission units] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.rcvmss PMID: 251.1.19 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1717,8 +1717,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 536 -network.persocket.advmss PMID: 154.1.20 [advertised maximum segment size] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.advmss PMID: 251.1.20 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1812,8 +1812,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 65483 -network.persocket.cwnd PMID: 154.1.21 [congestion window size] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.cwnd PMID: 251.1.21 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -1907,8 +1907,8 @@ inst [89 or "tcp6/[::]:44323"] value 10 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 10 -network.persocket.ssthresh PMID: 154.1.22 [tcp congestion window slow start threshold] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.ssthresh PMID: 251.1.22 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2002,8 +2002,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.bytes_sent PMID: 154.1.23 [count of bytes sent using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_sent PMID: 251.1.23 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2097,8 +2097,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1955159 -network.persocket.bytes_retrans PMID: 154.1.24 [count of bytes retransmitted using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_retrans PMID: 251.1.24 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2192,8 +2192,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.bytes_acked PMID: 154.1.25 [count of bytes acked using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_acked PMID: 251.1.25 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2287,8 +2287,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1955159 -network.persocket.bytes_received PMID: 154.1.36 [count of bytes received using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_received PMID: 251.1.36 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2382,8 +2382,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 69464 -network.persocket.segs_out PMID: 154.1.37 [count of segments sent out using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.segs_out PMID: 251.1.37 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2477,8 +2477,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 918 -network.persocket.segs_in PMID: 154.1.38 [count of segments received using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.segs_in PMID: 251.1.38 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2572,8 +2572,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1373 -network.persocket.data_segs_out PMID: 154.1.39 [count of data segments sent out using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.data_segs_out PMID: 251.1.39 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2667,8 +2667,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 914 -network.persocket.data_segs_in PMID: 154.1.40 [count of data segments received using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.data_segs_in PMID: 251.1.40 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2762,8 +2762,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 457 -network.persocket.send PMID: 154.1.41 [egress bps] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.send PMID: 251.1.41 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2857,8 +2857,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 58254222222 -network.persocket.lastsnd PMID: 154.1.42 [how long time since the last packet sent in milliseconds] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.lastsnd PMID: 251.1.42 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -2952,8 +2952,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 3495 -network.persocket.lastrcv PMID: 154.1.43 [how long time since the last packet received in milliseconds] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.lastrcv PMID: 251.1.43 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3047,8 +3047,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 3499 -network.persocket.lastack PMID: 154.1.44 [how long time since the last ack received in milliseconds] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.lastack PMID: 251.1.44 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3142,8 +3142,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 3495 -network.persocket.pacing_rate PMID: 154.1.45 [the current pacing rate of the socket] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.pacing_rate PMID: 251.1.45 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: byte / sec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3237,8 +3237,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 116185706368 -network.persocket.delivery_rate PMID: 154.1.46 [delivery bandwidth estimate excluding idle periods] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.delivery_rate PMID: 251.1.46 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: byte / sec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3332,8 +3332,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 65536000000 -network.persocket.delivered PMID: 154.1.47 [] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.delivered PMID: 251.1.47 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3427,8 +3427,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 915 -network.persocket.app_limited PMID: 154.1.48 [TCP flows are limited with application-limiting] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.app_limited PMID: 251.1.48 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3522,8 +3522,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 1 -network.persocket.reord_seen PMID: 154.1.49 [] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.reord_seen PMID: 251.1.49 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3617,8 +3617,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 34 -network.persocket.busy PMID: 154.1.50 [TCP connection is busy??] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.busy PMID: 251.1.50 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3712,8 +3712,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 34 -network.persocket.dsack_dups PMID: 154.1.51 [duplicate selective acknowledgements] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.dsack_dups PMID: 251.1.51 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3807,8 +3807,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.rcv_rtt PMID: 154.1.52 [receive round trip time] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.rcv_rtt PMID: 251.1.52 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3902,8 +3902,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 6115.7 -network.persocket.rcv_space PMID: 154.1.53 [TCP internal auto tuning socket receive buffer size] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.rcv_space PMID: 251.1.53 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -3997,8 +3997,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 65664 -network.persocket.rcv_ssthresh PMID: 154.1.54 [TCP congestion window slow start threshold] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.rcv_ssthresh PMID: 251.1.54 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -4092,8 +4092,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 92283 -network.persocket.minrtt PMID: 154.1.55 [minimum round trip time achieved in the socket] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.minrtt PMID: 251.1.55 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: discrete Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -4187,8 +4187,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0.004 -network.persocket.notsent PMID: 154.1.56 [unsent data bytes that are still buffered] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.notsent PMID: 251.1.56 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -4282,8 +4282,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.timer.str PMID: 154.1.70 [the 'timer:' string, as reported by ss] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.timer.str PMID: 251.1.70 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "" inst [1 or "udp/192.168.1.169:58624"] value "" @@ -4377,8 +4377,8 @@ inst [89 or "tcp6/[::]:44323"] value "" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "keepalive,1.504ms,0" -network.persocket.timer.name PMID: 154.1.71 [name of the socket timer.] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.timer.name PMID: 251.1.71 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "" inst [1 or "udp/192.168.1.169:58624"] value "" @@ -4472,8 +4472,8 @@ inst [89 or "tcp6/[::]:44323"] value "" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "keepalive" -network.persocket.timer.expire_str PMID: 154.1.72 [how long until the timer will expire] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.timer.expire_str PMID: 251.1.72 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "" inst [1 or "udp/192.168.1.169:58624"] value "" @@ -4567,8 +4567,8 @@ inst [89 or "tcp6/[::]:44323"] value "" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "1.504ms" -network.persocket.timer.retrans PMID: 154.1.73 [how many times the retransmission occured in timer] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.timer.retrans PMID: 251.1.73 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -4662,8 +4662,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.str PMID: 154.1.80 [socket memory details, as a string] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.skmem.str PMID: 251.1.80 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0" inst [1 or "udp/192.168.1.169:58624"] value "r0,rb212992,t0,tb212992,f4096,w0,o0,bl0,d0" @@ -4757,8 +4757,8 @@ inst [89 or "tcp6/[::]:44323"] value "r0,rb131072,t0,tb16384,f0,w0,o0,bl0,d0" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "r0,rb2358342,t0,tb2626560,f0,w0,o0,bl0,d0" -network.persocket.skmem.rmem_alloc PMID: 154.1.81 [memory allocated for receiving packet] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.rmem_alloc PMID: 251.1.81 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -4852,8 +4852,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.wmem_alloc PMID: 154.1.82 [memory used for sending packet (which has been sent] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.wmem_alloc PMID: 251.1.82 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -4947,8 +4947,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.rcv_buf PMID: 154.1.83 [total memory that can be allocated to recv packets] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.rcv_buf PMID: 251.1.83 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 425984 inst [1 or "udp/192.168.1.169:58624"] value 212992 @@ -5042,8 +5042,8 @@ inst [89 or "tcp6/[::]:44323"] value 131072 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 2358342 -network.persocket.skmem.snd_buf PMID: 154.1.84 [total memory that can be allocated to send packets] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.snd_buf PMID: 251.1.84 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 58080 inst [1 or "udp/192.168.1.169:58624"] value 212992 @@ -5137,8 +5137,8 @@ inst [89 or "tcp6/[::]:44323"] value 16384 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 2626560 -network.persocket.skmem.fwd_alloc PMID: 154.1.95 [cache memory allocated but not yet used for snd/rcv] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.fwd_alloc PMID: 251.1.95 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 4096 inst [1 or "udp/192.168.1.169:58624"] value 4096 @@ -5232,8 +5232,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.wmem_queued PMID: 154.1.86 [memory allocated for sending packet] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.wmem_queued PMID: 251.1.86 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -5327,8 +5327,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.ropt_mem PMID: 154.1.87 [memory used for storing socket options] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.ropt_mem PMID: 251.1.87 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -5422,8 +5422,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.back_log PMID: 154.1.88 [memory used for the sk backlog queue] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.back_log PMID: 251.1.88 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -5517,8 +5517,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.skmem.sock_drop PMID: 154.1.89 [dropped packets before demultiplexed into socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.sock_drop PMID: 251.1.89 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -5612,8 +5612,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0 -network.persocket.wscale.str PMID: 154.1.60 [send and rcv scale factor as a string] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.wscale.str PMID: 251.1.60 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "" inst [1 or "udp/192.168.1.169:58624"] value "" @@ -5707,8 +5707,8 @@ inst [89 or "tcp6/[::]:44323"] value "" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "7,7" -network.persocket.wscale.snd PMID: 154.1.61 [send scale factor when window scale is used] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.wscale.snd PMID: 251.1.61 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -5802,8 +5802,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 7 -network.persocket.wscale.rcv PMID: 154.1.62 [receive scale factor when window scale is used] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.wscale.rcv PMID: 251.1.62 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -5897,8 +5897,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 7 -network.persocket.round_trip.str PMID: 154.1.90 [average round trip time and variance, as a string] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.round_trip.str PMID: 251.1.90 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/10.0.0.10:49693"] value "" inst [1 or "udp/192.168.1.169:58624"] value "" @@ -5992,8 +5992,8 @@ inst [89 or "tcp6/[::]:44323"] value "" inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value "0.045/0.025" -network.persocket.round_trip.rtt PMID: 154.1.91 [average round trip time in milliseconds] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.round_trip.rtt PMID: 251.1.91 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -6087,8 +6087,8 @@ inst [89 or "tcp6/[::]:44323"] value 0 inst [90 or "tcp/[::ffff:127.0.0.1]:3000"] value 0.045 -network.persocket.round_trip.rttvar PMID: 154.1.92 [round trip time mean deviation.] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.round_trip.rttvar PMID: 251.1.92 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/10.0.0.10:49693"] value 0 inst [1 or "udp/192.168.1.169:58624"] value 0 @@ -6184,7 +6184,7 @@ === std err === === filtered valgrind report === Memcheck, a memory error detector -Command: pminfo -L -K clear -K add,154,/var/lib/pcp/pmdas/sockets/pmda_sockets.so,sockets_init -dfmt -n /var/lib/pcp/pmdas/sockets/root network.persocket +Command: pminfo -L -K clear -K add,251,/var/lib/pcp/pmdas/sockets/pmda_sockets.so,sockets_init -dfm -n TMP/root network.persocket LEAK SUMMARY: definitely lost: 0 bytes in 0 blocks indirectly lost: 0 bytes in 0 blocks @@ -6192,13 +6192,13 @@ === testing sockets/ss_noemitauOH_ubuntu.txt === === std out === -network.persocket.filter PMID: 154.0.0 [filter for sockets of interest] +network.persocket.filter PMID: 251.0.0 Data Type: string InDom: PM_INDOM_NULL 0xffffffff Semantics: discrete Units: none value "state connected" -network.persocket.netid PMID: 154.1.0 [socket protocol identifier] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.netid PMID: 251.1.0 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "udp" inst [1 or "udp/0.0.0.0:38162"] value "udp" @@ -6229,8 +6229,8 @@ inst [26 or "tcp/*:80"] value "tcp" inst [27 or "tcp6/[::1]:53"] value "tcp" -network.persocket.state PMID: 154.1.1 [socket state as a string, commonly UNCONN, ESTAB, TIME-WAIT] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.state PMID: 251.1.1 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "UNCONN" inst [1 or "udp/0.0.0.0:38162"] value "UNCONN" @@ -6261,8 +6261,8 @@ inst [26 or "tcp/*:80"] value "LISTEN" inst [27 or "tcp6/[::1]:53"] value "LISTEN" -network.persocket.recvq PMID: 154.1.2 [length of the receive queue] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.recvq PMID: 251.1.2 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6293,8 +6293,8 @@ inst [26 or "tcp/*:80"] value 511 inst [27 or "tcp6/[::1]:53"] value 256 -network.persocket.sendq PMID: 154.1.3 [length of the send queue] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.sendq PMID: 251.1.3 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6325,8 +6325,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.src PMID: 154.1.4 [local (source) IP address (IPv4 or IPv6) and port] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.src PMID: 251.1.4 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "0.0.0.0:5353" inst [1 or "udp/0.0.0.0:38162"] value "0.0.0.0:38162" @@ -6357,8 +6357,8 @@ inst [26 or "tcp/*:80"] value "*:80" inst [27 or "tcp6/[::1]:53"] value "[::1]:53" -network.persocket.dst PMID: 154.1.5 [destination IP address (IPv4 or IPv6) and port] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.dst PMID: 251.1.5 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "0.0.0.0:*" inst [1 or "udp/0.0.0.0:38162"] value "0.0.0.0:*" @@ -6389,8 +6389,8 @@ inst [26 or "tcp/*:80"] value "*:*" inst [27 or "tcp6/[::1]:53"] value "[::]:*" -network.persocket.inode PMID: 154.1.6 [the socket's inode number in VFS] - Data Type: 64-bit int InDom: 154.0 0x26800000 +network.persocket.inode PMID: 251.1.6 + Data Type: 64-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 177686 inst [1 or "udp/0.0.0.0:38162"] value 177688 @@ -6421,8 +6421,8 @@ inst [26 or "tcp/*:80"] value 179878 inst [27 or "tcp6/[::1]:53"] value 179210 -network.persocket.uid PMID: 154.1.8 [the user id the socket belongs to] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.uid PMID: 251.1.8 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 117 inst [1 or "udp/0.0.0.0:38162"] value 117 @@ -6453,8 +6453,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.sk PMID: 154.1.9 [uuid cookie of the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.sk PMID: 251.1.9 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 9 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6485,8 +6485,8 @@ inst [26 or "tcp/*:80"] value 20 inst [27 or "tcp6/[::1]:53"] value 21 -network.persocket.cgroup PMID: 154.1.10 [cgroup v2 pathname] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.cgroup PMID: 251.1.10 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "" inst [1 or "udp/0.0.0.0:38162"] value "" @@ -6517,8 +6517,8 @@ inst [26 or "tcp/*:80"] value "" inst [27 or "tcp6/[::1]:53"] value "" -network.persocket.v6only PMID: 154.1.11 [boolean value set to one if the socket is IPv6, 0 otherwise] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.v6only PMID: 251.1.11 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6549,8 +6549,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 1 -network.persocket.ts PMID: 154.1.13 [boolean value set to one if the timestamp option is set] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.ts PMID: 251.1.13 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6581,8 +6581,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.sack PMID: 154.1.14 [boolean value set to one if the sack option is set] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.sack PMID: 251.1.14 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6613,8 +6613,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.cubic PMID: 154.1.15 [boolean value set to one if cubic congestion control is enabled] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.cubic PMID: 251.1.15 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6645,8 +6645,8 @@ inst [26 or "tcp/*:80"] value 1 inst [27 or "tcp6/[::1]:53"] value 1 -network.persocket.ato PMID: 154.1.16 [ack timeout when using delayed ack mode] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.ato PMID: 251.1.16 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: discrete Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6677,8 +6677,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.mss PMID: 154.1.17 [maximum segment size] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.mss PMID: 251.1.17 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6709,8 +6709,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.pmtu PMID: 154.1.18 [path maximum transmission unit] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.pmtu PMID: 251.1.18 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6741,8 +6741,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.rcvmss PMID: 154.1.19 [receive maximum transmission units] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.rcvmss PMID: 251.1.19 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6773,8 +6773,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.advmss PMID: 154.1.20 [advertised maximum segment size] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.advmss PMID: 251.1.20 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6805,8 +6805,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.cwnd PMID: 154.1.21 [congestion window size] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.cwnd PMID: 251.1.21 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6837,8 +6837,8 @@ inst [26 or "tcp/*:80"] value 10 inst [27 or "tcp6/[::1]:53"] value 10 -network.persocket.ssthresh PMID: 154.1.22 [tcp congestion window slow start threshold] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.ssthresh PMID: 251.1.22 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6869,8 +6869,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.bytes_sent PMID: 154.1.23 [count of bytes sent using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_sent PMID: 251.1.23 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6901,8 +6901,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.bytes_retrans PMID: 154.1.24 [count of bytes retransmitted using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_retrans PMID: 251.1.24 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6933,8 +6933,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.bytes_acked PMID: 154.1.25 [count of bytes acked using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_acked PMID: 251.1.25 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6965,8 +6965,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.bytes_received PMID: 154.1.36 [count of bytes received using the socket] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.bytes_received PMID: 251.1.36 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -6997,8 +6997,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.segs_out PMID: 154.1.37 [count of segments sent out using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.segs_out PMID: 251.1.37 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7029,8 +7029,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.segs_in PMID: 154.1.38 [count of segments received using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.segs_in PMID: 251.1.38 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7061,8 +7061,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.data_segs_out PMID: 154.1.39 [count of data segments sent out using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.data_segs_out PMID: 251.1.39 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7093,8 +7093,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.data_segs_in PMID: 154.1.40 [count of data segments received using the socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.data_segs_in PMID: 251.1.40 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7125,8 +7125,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.send PMID: 154.1.41 [egress bps] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.send PMID: 251.1.41 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7157,8 +7157,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.lastsnd PMID: 154.1.42 [how long time since the last packet sent in milliseconds] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.lastsnd PMID: 251.1.42 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7189,8 +7189,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.lastrcv PMID: 154.1.43 [how long time since the last packet received in milliseconds] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.lastrcv PMID: 251.1.43 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7221,8 +7221,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.lastack PMID: 154.1.44 [how long time since the last ack received in milliseconds] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.lastack PMID: 251.1.44 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7253,8 +7253,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.pacing_rate PMID: 154.1.45 [the current pacing rate of the socket] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.pacing_rate PMID: 251.1.45 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: byte / sec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7285,8 +7285,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.delivery_rate PMID: 154.1.46 [delivery bandwidth estimate excluding idle periods] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.delivery_rate PMID: 251.1.46 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: byte / sec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7317,8 +7317,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.delivered PMID: 154.1.47 [] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.delivered PMID: 251.1.47 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: counter Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7349,8 +7349,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.app_limited PMID: 154.1.48 [TCP flows are limited with application-limiting] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.app_limited PMID: 251.1.48 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7381,8 +7381,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.reord_seen PMID: 154.1.49 [] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.reord_seen PMID: 251.1.49 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7413,8 +7413,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.busy PMID: 154.1.50 [TCP connection is busy??] - Data Type: 64-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.busy PMID: 251.1.50 + Data Type: 64-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7445,8 +7445,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.dsack_dups PMID: 154.1.51 [duplicate selective acknowledgements] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.dsack_dups PMID: 251.1.51 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7477,8 +7477,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.rcv_rtt PMID: 154.1.52 [receive round trip time] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.rcv_rtt PMID: 251.1.52 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7509,8 +7509,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.rcv_space PMID: 154.1.53 [TCP internal auto tuning socket receive buffer size] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.rcv_space PMID: 251.1.53 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7541,8 +7541,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.rcv_ssthresh PMID: 154.1.54 [TCP congestion window slow start threshold] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.rcv_ssthresh PMID: 251.1.54 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: discrete Units: count inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7573,8 +7573,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.minrtt PMID: 154.1.55 [minimum round trip time achieved in the socket] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.minrtt PMID: 251.1.55 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: discrete Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7605,8 +7605,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.notsent PMID: 154.1.56 [unsent data bytes that are still buffered] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.notsent PMID: 251.1.56 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7637,8 +7637,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.timer.str PMID: 154.1.70 [the 'timer:' string, as reported by ss] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.timer.str PMID: 251.1.70 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "" inst [1 or "udp/0.0.0.0:38162"] value "" @@ -7669,8 +7669,8 @@ inst [26 or "tcp/*:80"] value "" inst [27 or "tcp6/[::1]:53"] value "" -network.persocket.timer.name PMID: 154.1.71 [name of the socket timer.] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.timer.name PMID: 251.1.71 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "" inst [1 or "udp/0.0.0.0:38162"] value "" @@ -7701,8 +7701,8 @@ inst [26 or "tcp/*:80"] value "" inst [27 or "tcp6/[::1]:53"] value "" -network.persocket.timer.expire_str PMID: 154.1.72 [how long until the timer will expire] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.timer.expire_str PMID: 251.1.72 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "" inst [1 or "udp/0.0.0.0:38162"] value "" @@ -7733,8 +7733,8 @@ inst [26 or "tcp/*:80"] value "" inst [27 or "tcp6/[::1]:53"] value "" -network.persocket.timer.retrans PMID: 154.1.73 [how many times the retransmission occured in timer] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.timer.retrans PMID: 251.1.73 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7765,8 +7765,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.str PMID: 154.1.80 [socket memory details, as a string] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.skmem.str PMID: 251.1.80 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "r0,rb212992,t0,tb212992,f4096,w0,o144,bl0,d0" inst [1 or "udp/0.0.0.0:38162"] value "r0,rb212992,t0,tb212992,f0,w0,o0,bl0,d0" @@ -7797,8 +7797,8 @@ inst [26 or "tcp/*:80"] value "r0,rb131072,t0,tb16384,f0,w0,o0,bl0,d0" inst [27 or "tcp6/[::1]:53"] value "r0,rb131072,t0,tb16384,f0,w0,o0,bl0,d0" -network.persocket.skmem.rmem_alloc PMID: 154.1.81 [memory allocated for receiving packet] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.rmem_alloc PMID: 251.1.81 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7829,8 +7829,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.wmem_alloc PMID: 154.1.82 [memory used for sending packet (which has been sent] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.wmem_alloc PMID: 251.1.82 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7861,8 +7861,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.rcv_buf PMID: 154.1.83 [total memory that can be allocated to recv packets] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.rcv_buf PMID: 251.1.83 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 212992 inst [1 or "udp/0.0.0.0:38162"] value 212992 @@ -7893,8 +7893,8 @@ inst [26 or "tcp/*:80"] value 131072 inst [27 or "tcp6/[::1]:53"] value 131072 -network.persocket.skmem.snd_buf PMID: 154.1.84 [total memory that can be allocated to send packets] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.snd_buf PMID: 251.1.84 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 212992 inst [1 or "udp/0.0.0.0:38162"] value 212992 @@ -7925,8 +7925,8 @@ inst [26 or "tcp/*:80"] value 16384 inst [27 or "tcp6/[::1]:53"] value 16384 -network.persocket.skmem.fwd_alloc PMID: 154.1.95 [cache memory allocated but not yet used for snd/rcv] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.fwd_alloc PMID: 251.1.95 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 4096 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7957,8 +7957,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.wmem_queued PMID: 154.1.86 [memory allocated for sending packet] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.wmem_queued PMID: 251.1.86 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -7989,8 +7989,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.ropt_mem PMID: 154.1.87 [memory used for storing socket options] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.ropt_mem PMID: 251.1.87 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 144 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8021,8 +8021,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.back_log PMID: 154.1.88 [memory used for the sk backlog queue] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.back_log PMID: 251.1.88 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: byte inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8053,8 +8053,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.skmem.sock_drop PMID: 154.1.89 [dropped packets before demultiplexed into socket] - Data Type: 32-bit unsigned int InDom: 154.0 0x26800000 +network.persocket.skmem.sock_drop PMID: 251.1.89 + Data Type: 32-bit unsigned int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8085,8 +8085,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.wscale.str PMID: 154.1.60 [send and rcv scale factor as a string] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.wscale.str PMID: 251.1.60 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "" inst [1 or "udp/0.0.0.0:38162"] value "" @@ -8117,8 +8117,8 @@ inst [26 or "tcp/*:80"] value "" inst [27 or "tcp6/[::1]:53"] value "" -network.persocket.wscale.snd PMID: 154.1.61 [send scale factor when window scale is used] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.wscale.snd PMID: 251.1.61 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8149,8 +8149,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.wscale.rcv PMID: 154.1.62 [receive scale factor when window scale is used] - Data Type: 32-bit int InDom: 154.0 0x26800000 +network.persocket.wscale.rcv PMID: 251.1.62 + Data Type: 32-bit int InDom: 251.0 0x3ec00000 Semantics: instant Units: none inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8181,8 +8181,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.round_trip.str PMID: 154.1.90 [average round trip time and variance, as a string] - Data Type: string InDom: 154.0 0x26800000 +network.persocket.round_trip.str PMID: 251.1.90 + Data Type: string InDom: 251.0 0x3ec00000 Semantics: discrete Units: none inst [0 or "udp/0.0.0.0:5353"] value "" inst [1 or "udp/0.0.0.0:38162"] value "" @@ -8213,8 +8213,8 @@ inst [26 or "tcp/*:80"] value "" inst [27 or "tcp6/[::1]:53"] value "" -network.persocket.round_trip.rtt PMID: 154.1.91 [average round trip time in milliseconds] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.round_trip.rtt PMID: 251.1.91 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8245,8 +8245,8 @@ inst [26 or "tcp/*:80"] value 0 inst [27 or "tcp6/[::1]:53"] value 0 -network.persocket.round_trip.rttvar PMID: 154.1.92 [round trip time mean deviation.] - Data Type: double InDom: 154.0 0x26800000 +network.persocket.round_trip.rttvar PMID: 251.1.92 + Data Type: double InDom: 251.0 0x3ec00000 Semantics: instant Units: millisec inst [0 or "udp/0.0.0.0:5353"] value 0 inst [1 or "udp/0.0.0.0:38162"] value 0 @@ -8279,7 +8279,7 @@ === std err === === filtered valgrind report === Memcheck, a memory error detector -Command: pminfo -L -K clear -K add,154,/var/lib/pcp/pmdas/sockets/pmda_sockets.so,sockets_init -dfmt -n /var/lib/pcp/pmdas/sockets/root network.persocket +Command: pminfo -L -K clear -K add,251,/var/lib/pcp/pmdas/sockets/pmda_sockets.so,sockets_init -dfm -n TMP/root network.persocket LEAK SUMMARY: definitely lost: 0 bytes in 0 blocks indirectly lost: 0 bytes in 0 blocks diff -Nru pcp-5.3.1/qa/1653 pcp-5.3.2/qa/1653 --- pcp-5.3.1/qa/1653 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1653 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,76 @@ +#!/bin/sh +# PCP QA Test No. 1653 +# Checks for pmda-denki +# +# Copyright (c) 2021 Christian Horn. All Rights Reserved. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +[ $PCP_PLATFORM = linux ] || _notrun "Linux-specific kernel metrics" + +_cleanup() +{ + cd $here + $sudo cp $tmp.install $PCP_PMDAS_DIR/denki/Install + _cleanup_pmda denki +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_filter() +{ + sed \ + -e "s,$here,PWD,g" \ + -e "s,$PCP_PMDAS_DIR,PCP_PMDAS_DIR,g" \ + # end +} + +# real QA test starts here +_prepare_pmda denki +$sudo cp $PCP_PMDAS_DIR/denki/Install $tmp.install + +echo +echo "### Extracting test datasets..." +echo +cd $here/denki/ +tar xzf bigsystem.tgz +tar xzf Thinkpad_L480_bat_busy.tgz + +echo +echo "### Installing test dataset 1..." +echo +cd $PCP_PMDAS_DIR/denki +ROOTPATH="$here/denki/Thinkpad_L480_bat_busy" +$sudo sed -ie \ + "s,^args.*,args=\"-U root -r ${ROOTPATH}\"," \ + Install +$sudo ./Install 2>&1 +pminfo -fF denki + +echo +echo "### Installing test dataset 2..." +echo +ROOTPATH="$here/denki/bigsystem" +$sudo sed -ie \ + "s,^args.*,args=\"-U root -r ${ROOTPATH}\"," \ + Install +$sudo ./Install 2>&1 +pminfo -fF denki + +echo +echo "### Removing test datasets..." +echo +rm -rf $here/denki/bigsystem +rm -rf $here/denki/Thinkpad_L480_bat_busy + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1653.out pcp-5.3.2/qa/1653.out --- pcp-5.3.1/qa/1653.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1653.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,63 @@ +QA output created by 1653 + +### Extracting test datasets... + + +### Installing test dataset 1... + +Updating the Performance Metrics Name Space (PMNS) ... +Terminate PMDA if already installed ... +Updating the PMCD control file, and notifying PMCD ... +Check denki metrics have appeared ... 5 metrics and 11 values + +denki.rapl.rate + inst [0 or "package-0"] value 26716 + inst [1 or "core"] value 12628 + inst [2 or "uncore"] value 2711 + inst [3 or "dram"] value 7743 + +denki.rapl.raw + inst [0 or "package-0"] value 26716 + inst [1 or "core"] value 12628 + inst [2 or "uncore"] value 2711 + inst [3 or "dram"] value 7743 + +denki.bat.energy_now_raw + value 34.71 + +denki.bat.energy_now_rate + value 0 + +denki.bat.power_now + value 26.439 + +### Installing test dataset 2... + +Updating the Performance Metrics Name Space (PMNS) ... +Terminate PMDA if already installed ... +Updating the PMCD control file, and notifying PMCD ... +Check denki metrics have appeared ... 5 metrics and 11 values + +denki.rapl.rate + inst [0 or "0-package-1"] value 8826 + inst [1 or "0-core"] value 3483 + inst [2 or "1-package-0"] value 13719 + inst [3 or "1-core"] value 8334 + +denki.rapl.raw + inst [0 or "0-package-1"] value 8826 + inst [1 or "0-core"] value 3483 + inst [2 or "1-package-0"] value 13719 + inst [3 or "1-core"] value 8334 + +denki.bat.energy_now_raw + value 0 + +denki.bat.energy_now_rate + value 0 + +denki.bat.power_now + value 0 + +### Removing test datasets... + diff -Nru pcp-5.3.1/qa/1672 pcp-5.3.2/qa/1672 --- pcp-5.3.1/qa/1672 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/qa/1672 2021-07-30 04:05:06.000000000 +0000 @@ -27,11 +27,21 @@ mechanisms="plain login scram-sha-256" for mech in $mechanisms do - mechanism=`echo $mech | sed -e 's/-.*//g'` - $pluginviewer -c | grep 'Plugin "'$mechanism'"' >/dev/null 2>&1 - test $? -eq 0 || _notrun "No client support for $mechanism authentication" - $pluginviewer -s | grep 'Plugin "'$mechanism'"' >/dev/null 2>&1 - test $? -eq 0 || _notrun "No server support for $mechanism authentication" + case $mech + in + scram-*) # special, we need SCRAM-SHA-256 not SCRAM-SHA-1 + $pluginviewer -c | grep 'SCRAM-SHA-256' >/dev/null 2>&1 + test $? -eq 0 || _notrun "No client support for $mech authentication" + $pluginviewer -s | grep 'SCRAM-SHA-256' >/dev/null 2>&1 + test $? -eq 0 || _notrun "No server support for $mech authentication" + ;; + *) + $pluginviewer -c | grep 'Plugin "'$mech'"' >/dev/null 2>&1 + test $? -eq 0 || _notrun "No client support for $mech authentication" + $pluginviewer -s | grep 'Plugin "'$mech'"' >/dev/null 2>&1 + test $? -eq 0 || _notrun "No server support for $mech authentication" + ;; + esac done cleanup() diff -Nru pcp-5.3.1/qa/1681 pcp-5.3.2/qa/1681 --- pcp-5.3.1/qa/1681 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1681 2021-06-15 01:03:49.000000000 +0000 @@ -20,6 +20,8 @@ . ./common.filter . ./common.check +which pmrep >/dev/null 2>&1 || _notrun "no pmrep executable" + do_valgrind=false if [ "$1" = "--valgrind" ] then diff -Nru pcp-5.3.1/qa/1682 pcp-5.3.2/qa/1682 --- pcp-5.3.1/qa/1682 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/qa/1682 2021-07-30 04:05:06.000000000 +0000 @@ -14,6 +14,8 @@ . ./common.filter . ./common.check +which pmrep >/dev/null 2>&1 || _notrun "no pmrep executable" + _check_valgrind _cleanup() diff -Nru pcp-5.3.1/qa/1689 pcp-5.3.2/qa/1689 --- pcp-5.3.1/qa/1689 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/1689 2021-07-30 04:05:06.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/sh # PCP QA Test No. 1689 -# Exercise and check pmproxy / libpcp_web metrics +# Exercise and check pmproxy metrics metadata and help text # # Copyright (c) 2021 Red Hat. All Rights Reserved. # @@ -33,7 +33,5 @@ names=`pminfo pmproxy | LC_COLLATE=POSIX sort` pminfo -mdtT $names -# TODO check metric values after various operations - # success, all done exit diff -Nru pcp-5.3.1/qa/1689.out pcp-5.3.2/qa/1689.out --- pcp-5.3.1/qa/1689.out 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/1689.out 2021-07-30 04:05:06.000000000 +0000 @@ -19,6 +19,24 @@ Writing anything other then 0 to this metric will result in re-reading directory and re-mapping files. +pmproxy.cpu.sys PMID: 4.1.2 [system CPU time] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: counter Units: millisec +Help: +process system CPU time counter + +pmproxy.cpu.total PMID: 4.1.3 [system + user CPU time] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: counter Units: millisec +Help: +process system + user CPU time + +pmproxy.cpu.user PMID: 4.1.1 [user CPU time] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: counter Units: millisec +Help: +process user CPU time counter + pmproxy.discover.changed_callbacks PMID: 4.5.17 [filesystem changed callbacks] Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff Semantics: counter Units: count @@ -110,6 +128,12 @@ Help: total loops processing metadata for all monitored archives +pmproxy.discover.metadata.partial_reads PMID: 4.5.20 [metadata read returned less data than header indicated] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: counter Units: count +Help: +number of times a metadata record read returned less than expected length + pmproxy.discover.monitored PMID: 4.5.1 [directories, sub-directories and archives currently being monitored] Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff Semantics: discrete Units: none @@ -135,11 +159,23 @@ Help: number of throttled filesystem change callbacks -pmproxy.pid PMID: 4.1.0 [pmproxy PID] +pmproxy.mem.datasz PMID: 4.1.5 [virtual data size] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: Kbyte +Help: +process data memory size, returned from sbrk(2) + +pmproxy.mem.maxrss PMID: 4.1.4 [maximum RSS] + Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff + Semantics: instant Units: Kbyte +Help: +process maximum resident set memory size + +pmproxy.pid PMID: 4.1.0 [Identifier] Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff Semantics: discrete Units: none Help: -PID for the current pmproxy invocation +Identifier for the current process pmproxy.redis.requests.error PMID: 4.2.2 [number of request errors] Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff diff -Nru pcp-5.3.1/qa/1703 pcp-5.3.2/qa/1703 --- pcp-5.3.1/qa/1703 2019-11-04 01:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1703 2021-07-30 04:05:06.000000000 +0000 @@ -10,6 +10,13 @@ _pmdabpftrace_check +case `hostname -s` +in + bozo-vm) + _notrun "cannot set bpftrace hz=999 on this VM" + ;; +esac + status=1 # failure is the default! $sudo rm -rf $tmp.* $seq.full diff -Nru pcp-5.3.1/qa/1705 pcp-5.3.2/qa/1705 --- pcp-5.3.1/qa/1705 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1705 2021-07-30 04:05:06.000000000 +0000 @@ -10,6 +10,13 @@ _pmdabpftrace_check +case `hostname -s` +in + bozo-vm) + _notrun "cannot set bpftrace hz=999 on this VM" + ;; +esac + status=1 # failure is the default! $sudo rm -rf $tmp.* $seq.full @@ -17,6 +24,10 @@ trap "_pmdabpftrace_cleanup; exit \$status" 0 1 2 3 15 _stop_auto_restart pmcd +# on vm04, the limit is 512 which is not enough; 600 seems enough +# +export BPFTRACE_MAX_PROBES=600 + # real QA test starts here _pmdabpftrace_clean_autostart_scripts cat <//' \ + # end +} + +# real QA test starts here + +if $do_valgrind +then + _run_valgrind ...your test goes here... +else + ...your test goes here... 2>&1 +fi \ +| _filter + +# if really bad error +status=1 +exit + +# optional stuff if your test has verbose output to help resolve problems +#echo +#echo "If failure, check $seq.full" + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1727.out pcp-5.3.2/qa/1727.out --- pcp-5.3.1/qa/1727.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1727.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,2 @@ +QA output created by 1727 +[skeleton from qa/new, replace me] diff -Nru pcp-5.3.1/qa/1774 pcp-5.3.2/qa/1774 --- pcp-5.3.1/qa/1774 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1774 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,68 @@ +#!/bin/sh +# PCP QA Test No. 1774 +# [what am I here for?] +# +# Copyright (c) 2021 [who are you?]. All Rights Reserved. +# + +if [ $# -eq 0 ] +then + seq=`basename $0` + echo "QA output created by $seq" +else + # use $seq from caller, unless not set + [ -n "$seq" ] || seq=`basename $0` + echo "QA output created by `basename $0` $*" +fi + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +do_valgrind=false +if [ "$1" = "--valgrind" ] +then + _check_valgrind + do_valgrind=true +fi + +# test for-some-thing || _notrun No support for some-thing + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_filter() +{ + sed \ + -e 's///' \ + # end +} + +# real QA test starts here + +if $do_valgrind +then + _run_valgrind ...your test goes here... +else + ...your test goes here... 2>&1 +fi \ +| _filter + +# if really bad error +status=1 +exit + +# optional stuff if your test has verbose output to help resolve problems +#echo +#echo "If failure, check $seq.full" + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1774.out pcp-5.3.2/qa/1774.out --- pcp-5.3.1/qa/1774.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1774.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,2 @@ +QA output created by 1774 +[skeleton from qa/new, replace me] diff -Nru pcp-5.3.1/qa/1872 pcp-5.3.2/qa/1872 --- pcp-5.3.1/qa/1872 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/1872 2021-07-30 04:05:06.000000000 +0000 @@ -89,7 +89,7 @@ redis.enabled = true [pmseries] enabled = true -servers = localhost:$port +servers = localhost:$redisport [pmsearch] enabled = true EOF @@ -134,6 +134,7 @@ # start pmproxy proxyport=`_find_free_port` +echo "proxyport=$proxyport" >>$seq.full proxyopts="-p $proxyport -r $redisport -c $tmp.conf" # -Dseries,http,af pmproxy -f -U $username -x $seq.full -l $tmp.pmproxy.log $proxyopts & pmproxy_pid=$! @@ -145,7 +146,7 @@ pmsleep 10s $PCP_PS_PROG $PCP_PS_ALL_FLAGS | grep pmproxy >> $seq.full -redis-cli $options keys pcp:text >> $seq.full +redis-cli $port keys pcp:text >> $seq.full cat $tmp.pmproxy.log >> $seq.full echo "=== /search/text - query for '99' 'random' 'interesting' 'result' ===" @@ -153,7 +154,7 @@ for term in $search_terms do url="http://localhost:$proxyport/search/text?query=$term" - echo "== verify request - $url" + echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed done @@ -161,31 +162,31 @@ echo "=== /search/text - no match response ===" url="http://localhost:$proxyport/search/text?query=bazinga" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/text - query param is required ===" url="http://localhost:$proxyport/search/text" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent -s -o /dev/null -w "%{http_code}\n" "$url" | tee -a $seq.full echo "=== /search/text - highlighting is supported on 'name', 'oneline' and 'helptext' by using 'highlight' param ===" url="http://localhost:$proxyport/search/text?query=domain&highlight=name,oneline,helptext" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=sample&highlight=name" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=counter&highlight=oneline,helptext" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed @@ -193,161 +194,161 @@ echo "=== /search/text - pagination is supported using cursor params 'limit' and 'offset'" url="http://localhost:$proxyport/search/text?query=random&limit=1" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=random&limit=1&offset=1" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/text - its possible to query only specific fields (name, oneline, helptext, indom) using 'field' param ===" url="http://localhost:$proxyport/search/text?query=99&field=name" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=99&field=oneline" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=99&field=helptext" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/text - filtering out fields from response (name, oneline, helptext, type, indom) using 'return' param ===" url="http://localhost:$proxyport/search/text?query=99&return=name" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=99&return=type" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=99&return=oneline" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=99&return=helptext" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=99&return=indom" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=random&return=name,type,indom" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/text - filtering based on entity type (metric, instance, indom) using 'type' param ===" url="http://localhost:$proxyport/search/text?query=random&type=metric" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=random&type=indom" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=random&type=instance" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/text?query=random&type=metric,indom" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/suggest - generic request ===" url="http://localhost:$proxyport/search/suggest?query=sam" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/suggest?query=sample.r" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/suggest - limit is supported" url="http://localhost:$proxyport/search/suggest?query=sam&limit=2" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/suggest - query param is required ===" url="http://localhost:$proxyport/search/suggest" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent -s -o /dev/null -w "%{http_code}\n" "$url" | tee -a $seq.full echo "=== /search/suggest - no match response ===" url="http://localhost:$proxyport/search/suggest?query=xxx" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/indom - generic request ===" url="http://localhost:$proxyport/search/indom?query=29.1" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/indom?query=29.3" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/indom - no match response ===" url="http://localhost:$proxyport/search/indom?query=x" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/indom - query param is required ===" url="http://localhost:$proxyport/search/indom" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent -s -o /dev/null -w "%{http_code}\n" "$url" | tee -a $seq.full echo "=== /search/indom - pagination is supported using cursor params 'limit' and 'offset'" url="http://localhost:$proxyport/search/indom?query=29.1&limit=2&offset=0" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed url="http://localhost:$proxyport/search/indom?query=29.1&limit=2&offset=2" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_elapsed echo "=== /search/info ===" url="http://localhost:$proxyport/search/info" -echo "== verify request - $url" +echo "== verify request - $url" | sed -e "s/$proxyport/PORT/" echo "$url" >> $seq.full curl --get --silent "$url" | tee -a $seq.full | pmjson | _filter_info diff -Nru pcp-5.3.1/qa/1872.out pcp-5.3.2/qa/1872.out --- pcp-5.3.1/qa/1872.out 2020-11-10 22:19:53.000000000 +0000 +++ pcp-5.3.2/qa/1872.out 2021-07-30 04:05:06.000000000 +0000 @@ -6,7 +6,7 @@ === Load deterministic search content === pmseries: [Info] processed 4 archive records from PATH/archives/sample-labels === /search/text - query for '99' 'random' 'interesting' 'result' === -== verify request - http://localhost:54322/search/text?query=99 +== verify request - http://localhost:PORT/search/text?query=99 { "total": 1, "elapsed": XXX, @@ -22,7 +22,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=random +== verify request - http://localhost:PORT/search/text?query=random { "total": 2, "elapsed": XXX, @@ -45,7 +45,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=interesting +== verify request - http://localhost:PORT/search/text?query=interesting { "total": 1, "elapsed": XXX, @@ -61,7 +61,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=result +== verify request - http://localhost:PORT/search/text?query=result { "total": 1, "elapsed": XXX, @@ -78,7 +78,7 @@ ] } === /search/text - no match response === -== verify request - http://localhost:54322/search/text?query=bazinga +== verify request - http://localhost:PORT/search/text?query=bazinga { "total": 0, "elapsed": 0, @@ -87,10 +87,10 @@ "results": [ ] } === /search/text - query param is required === -== verify request - http://localhost:54322/search/text +== verify request - http://localhost:PORT/search/text 400 === /search/text - highlighting is supported on 'name', 'oneline' and 'helptext' by using 'highlight' param === -== verify request - http://localhost:54322/search/text?query=domain&highlight=name,oneline,helptext +== verify request - http://localhost:PORT/search/text?query=domain&highlight=name,oneline,helptext { "total": 2, "elapsed": XXX, @@ -113,7 +113,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=sample&highlight=name +== verify request - http://localhost:PORT/search/text?query=sample&highlight=name { "total": 5, "elapsed": XXX, @@ -157,7 +157,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=counter&highlight=oneline,helptext +== verify request - http://localhost:PORT/search/text?query=counter&highlight=oneline,helptext { "total": 3, "elapsed": XXX, @@ -188,7 +188,7 @@ ] } === /search/text - pagination is supported using cursor params 'limit' and 'offset' -== verify request - http://localhost:54322/search/text?query=random&limit=1 +== verify request - http://localhost:PORT/search/text?query=random&limit=1 { "total": 2, "elapsed": XXX, @@ -204,7 +204,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=random&limit=1&offset=1 +== verify request - http://localhost:PORT/search/text?query=random&limit=1&offset=1 { "total": 2, "elapsed": XXX, @@ -221,7 +221,7 @@ ] } === /search/text - its possible to query only specific fields (name, oneline, helptext, indom) using 'field' param === -== verify request - http://localhost:54322/search/text?query=99&field=name +== verify request - http://localhost:PORT/search/text?query=99&field=name { "total": 0, "elapsed": 0, @@ -229,7 +229,7 @@ "limit": 10, "results": [ ] } -== verify request - http://localhost:54322/search/text?query=99&field=oneline +== verify request - http://localhost:PORT/search/text?query=99&field=oneline { "total": 0, "elapsed": 0, @@ -237,7 +237,7 @@ "limit": 10, "results": [ ] } -== verify request - http://localhost:54322/search/text?query=99&field=helptext +== verify request - http://localhost:PORT/search/text?query=99&field=helptext { "total": 1, "elapsed": XXX, @@ -254,7 +254,7 @@ ] } === /search/text - filtering out fields from response (name, oneline, helptext, type, indom) using 'return' param === -== verify request - http://localhost:54322/search/text?query=99&return=name +== verify request - http://localhost:PORT/search/text?query=99&return=name { "total": 1, "elapsed": XXX, @@ -266,7 +266,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=99&return=type +== verify request - http://localhost:PORT/search/text?query=99&return=type { "total": 1, "elapsed": XXX, @@ -278,7 +278,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=99&return=oneline +== verify request - http://localhost:PORT/search/text?query=99&return=oneline { "total": 1, "elapsed": XXX, @@ -290,7 +290,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=99&return=helptext +== verify request - http://localhost:PORT/search/text?query=99&return=helptext { "total": 1, "elapsed": XXX, @@ -302,7 +302,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=99&return=indom +== verify request - http://localhost:PORT/search/text?query=99&return=indom { "total": 1, "elapsed": XXX, @@ -314,7 +314,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=random&return=name,type,indom +== verify request - http://localhost:PORT/search/text?query=random&return=name,type,indom { "total": 2, "elapsed": XXX, @@ -334,7 +334,7 @@ ] } === /search/text - filtering based on entity type (metric, instance, indom) using 'type' param === -== verify request - http://localhost:54322/search/text?query=random&type=metric +== verify request - http://localhost:PORT/search/text?query=random&type=metric { "total": 1, "elapsed": XXX, @@ -350,7 +350,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=random&type=indom +== verify request - http://localhost:PORT/search/text?query=random&type=indom { "total": 1, "elapsed": XXX, @@ -366,7 +366,7 @@ } ] } -== verify request - http://localhost:54322/search/text?query=random&type=instance +== verify request - http://localhost:PORT/search/text?query=random&type=instance { "total": 0, "elapsed": 0, @@ -374,7 +374,7 @@ "limit": 10, "results": [ ] } -== verify request - http://localhost:54322/search/text?query=random&type=metric,indom +== verify request - http://localhost:PORT/search/text?query=random&type=metric,indom { "total": 2, "elapsed": XXX, @@ -398,32 +398,32 @@ ] } === /search/suggest - generic request === -== verify request - http://localhost:54322/search/suggest?query=sam +== verify request - http://localhost:PORT/search/suggest?query=sam [ "sample.mirage", "sample.colour", "sample.rapid" ] -== verify request - http://localhost:54322/search/suggest?query=sample.r +== verify request - http://localhost:PORT/search/suggest?query=sample.r [ "sample.mirage", "sample.rapid", "sample.colour" ] === /search/suggest - limit is supported -== verify request - http://localhost:54322/search/suggest?query=sam&limit=2 +== verify request - http://localhost:PORT/search/suggest?query=sam&limit=2 [ "sample.mirage", "sample.colour" ] === /search/suggest - query param is required === -== verify request - http://localhost:54322/search/suggest +== verify request - http://localhost:PORT/search/suggest 400 === /search/suggest - no match response === -== verify request - http://localhost:54322/search/suggest?query=xxx +== verify request - http://localhost:PORT/search/suggest?query=xxx [] === /search/indom - generic request === -== verify request - http://localhost:54322/search/indom?query=29.1 +== verify request - http://localhost:PORT/search/indom?query=29.1 { "total": 5, "elapsed": XXX, @@ -461,7 +461,7 @@ } ] } -== verify request - http://localhost:54322/search/indom?query=29.3 +== verify request - http://localhost:PORT/search/indom?query=29.3 { "total": 5, "elapsed": XXX, @@ -500,7 +500,7 @@ ] } === /search/indom - no match response === -== verify request - http://localhost:54322/search/indom?query=x +== verify request - http://localhost:PORT/search/indom?query=x { "total": 0, "elapsed": 0, @@ -509,10 +509,10 @@ "results": [ ] } === /search/indom - query param is required === -== verify request - http://localhost:54322/search/indom +== verify request - http://localhost:PORT/search/indom 400 === /search/indom - pagination is supported using cursor params 'limit' and 'offset' -== verify request - http://localhost:54322/search/indom?query=29.1&limit=2&offset=0 +== verify request - http://localhost:PORT/search/indom?query=29.1&limit=2&offset=0 { "total": 5, "elapsed": XXX, @@ -531,7 +531,7 @@ } ] } -== verify request - http://localhost:54322/search/indom?query=29.1&limit=2&offset=2 +== verify request - http://localhost:PORT/search/indom?query=29.1&limit=2&offset=2 { "total": 5, "elapsed": XXX, @@ -553,7 +553,7 @@ ] } === /search/info === -== verify request - http://localhost:54322/search/info +== verify request - http://localhost:PORT/search/info { "docs": 18, "terms": 174, diff -Nru pcp-5.3.1/qa/189 pcp-5.3.2/qa/189 --- pcp-5.3.1/qa/189 2018-06-15 01:48:56.000000000 +0000 +++ pcp-5.3.2/qa/189 2021-07-30 04:05:06.000000000 +0000 @@ -49,7 +49,7 @@ pmie -T 10 $tmp.pmie >$tmp.out 2>$tmp.err & pmie_pid=$! wait $pmie_pid -cat $tmp.out $tmp.err | _show_pmie_errors +cat $tmp.out $tmp.err | _show_pmie_exit echo "== stdout ==" >$seq.full cat $tmp.out >>$seq.full diff -Nru pcp-5.3.1/qa/1893 pcp-5.3.2/qa/1893 --- pcp-5.3.1/qa/1893 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1893 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,64 @@ +#!/bin/sh +# PCP QA Test No. 1893 +# Exercise the Linux proc PMDA exe and cwd metrics. +# +# Copyright (c) 2021 Red Hat. All Rights Reserved. +# + +seq=`basename $0` +echo "QA output created by $seq" + +# get standard environment, filters and checks +. ./common.product +. ./common.filter +. ./common.check + +[ $PCP_PLATFORM = linux ] || _notrun "Linux proc PMDA specific test" + +_cleanup() +{ + cd $here + $sudo rm -rf $tmp $tmp.* +} + +status=0 # success is the default! +$sudo rm -rf $tmp $tmp.* $seq.full +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_filter() +{ + sed \ + -e "s/0*$mypid .*sh.] value/MYPID sh] value/g" \ + -e "s/*$mypid or /MYPID or /g" \ + -e "s,$mycwd,CWD,g" \ + -e "s,$myexe,EXE,g" \ + # end +} + +# real QA test starts here +mypid=$$ +mycwd=`pwd` +myexe=`readlink /proc/$$/exe` + +echo mypid: $mypid > $seq.full +echo mycwd: $mycwd >> $seq.full +echo myexe: $myexe >> $seq.full + +echo == check for any exe failures +pminfo -v proc.psinfo.exe +echo done + +echo == check exe value for self | tee -a $seq.full +pminfo -f proc.psinfo.exe | tee -a $seq.full | fgrep "inst [$mypid " | _filter +echo done + +echo == check for any cwd failure +pminfo -v proc.psinfo.cwd +echo done + +echo == check cwd value for self | tee -a $seq.full +pminfo -f proc.psinfo.cwd | tee -a $seq.full | fgrep "inst [$mypid " | _filter +echo done + +# success, all done +exit diff -Nru pcp-5.3.1/qa/1893.out pcp-5.3.2/qa/1893.out --- pcp-5.3.1/qa/1893.out 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/1893.out 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,11 @@ +QA output created by 1893 +== check for any exe failures +done +== check exe value for self + inst [MYPID sh] value "EXE" +done +== check for any cwd failure +done +== check cwd value for self + inst [MYPID sh] value "CWD" +done diff -Nru pcp-5.3.1/qa/1897.out pcp-5.3.2/qa/1897.out --- pcp-5.3.1/qa/1897.out 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/qa/1897.out 2021-07-30 04:05:06.000000000 +0000 @@ -41,7 +41,7 @@ The number of expected quorum votes for the cluster. value 2 -ha_cluster.corosync.quorum_votes.highest_expected PMID: 155.7.2 [Hightest expected vote count] +ha_cluster.corosync.quorum_votes.highest_expected PMID: 155.7.2 [Highest expected vote count] Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff Semantics: instant Units: count Help: @@ -76,6 +76,14 @@ The IP address locally linked to this ring. inst [0 or "0"] value "192.168.122.101" +ha_cluster.corosync.rings.all PMID: 155.15.0 [Corosync rings information] + Data Type: 32-bit unsigned int InDom: 155.13 0x26c0000d + Semantics: instant Units: count +Help: +Value is 1 if a ring exists. The details of the corresponding ring +is given as label metadata values for this metric. + inst [0 or "0"] value 1 + ha_cluster.corosync.rings.node_id PMID: 155.8.2 [ID of the local node] Data Type: 64-bit unsigned int InDom: 155.6 0x26c00006 Semantics: instant Units: count @@ -120,6 +128,14 @@ Amount of writes to the bitmap area of metadata by the DRBD resource:volume. inst [0 or "drbd1:0"] value 0 +ha_cluster.drbd.connections.all PMID: 155.18.0 [DRBD Peer disk information] + Data Type: 32-bit unsigned int InDom: 155.16 0x26c00010 + Semantics: instant Units: count +Help: +Value is 1 if a drbd peer connection exists. The details of the corresponding DRBD peer +connection is given as label metadata values for this metric. + inst [0 or "drbd1:1"] value 1 + ha_cluster.drbd.connections.peer_disk_state PMID: 155.11.4 [Peer disk state] Data Type: string InDom: 155.9 0x26c00009 Semantics: instant Units: count @@ -203,7 +219,7 @@ resource:volume. inst [0 or "drbd1:0"] value 0 -ha_cluster.drbd.quorum PMID: 155.10.10 [Quorum satus of DRBD resource:volume] +ha_cluster.drbd.quorum PMID: 155.10.10 [Quorum status of DRBD resource:volume] Data Type: 32-bit unsigned int InDom: 155.8 0x26c00008 Semantics: instant Units: count Help: @@ -218,6 +234,14 @@ Amount in KiB read by the DRBD resource:volume. inst [0 or "drbd1:0"] value 1888160 +ha_cluster.drbd.resources.all PMID: 155.17.0 [DRBD resource information] + Data Type: 32-bit unsigned int InDom: 155.15 0x26c0000f + Semantics: instant Units: count +Help: +Value is 1 if a drbd resource exists. The details of the corresponding drbd resource +is given as label metadata values for this metric. + inst [0 or "drbd1:0"] value 1 + ha_cluster.drbd.resources.disk_state PMID: 155.10.3 [Disk state] Data Type: string InDom: 155.8 0x26c00008 Semantics: instant Units: count @@ -236,21 +260,21 @@ Data Type: string InDom: 155.8 0x26c00008 Semantics: instant Units: count Help: -The resported role for ther DRBD resource for each resource:volume. +The reported role for the DRBD resource for each resource:volume. inst [0 or "drbd1:0"] value "Primary" ha_cluster.drbd.resources.volume PMID: 155.10.2 [Volume of the resource] Data Type: string InDom: 155.8 0x26c00008 Semantics: instant Units: count Help: -The volume number of ther resource for each resource:volume. +The volume number of the resource for each resource:volume. inst [0 or "drbd1:0"] value "0" ha_cluster.drbd.split_brain PMID: 155.10.11 [Signal for split brain detection.] Data Type: 32-bit unsigned int InDom: 155.8 0x26c00008 Semantics: instant Units: count Help: -This metric signals if there has been a split brain occuring in DRBD for the +This metric signals if there has been a split brain occurring in DRBD for the resource:volume, value is 1 is a split brain has been detected. inst [0 or "drbd1:0"] value 1 @@ -269,7 +293,7 @@ Amount in KiB written to the DRBD resource:volume. inst [0 or "drbd1:0"] value 0 -ha_cluster.pacemaker.config_last_change PMID: 155.0.0 [Unix timestamp corresponding to last Pacmaker configuration change] +ha_cluster.pacemaker.config_last_change PMID: 155.0.0 [Unix timestamp corresponding to last Pacemaker configuration change] Data Type: 64-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff Semantics: instant Units: count Help: @@ -285,6 +309,14 @@ depends on Pacemaker internals. inst [0 or "node-1:my_first_svc"] value 0 +ha_cluster.pacemaker.location_constraints.all PMID: 155.12.0 [Location constraint information] + Data Type: 32-bit unsigned int InDom: 155.10 0x26c0000a + Semantics: instant Units: count +Help: +Value is 1 if a location constraint exists. The details of the location constraint +is given as label metadata values for this metric. + inst [0 or "test"] value 1 + ha_cluster.pacemaker.location_constraints.node PMID: 155.2.0 [Node of the location constraint] Data Type: string InDom: 155.1 0x26c00001 Semantics: instant Units: count @@ -303,7 +335,7 @@ Data Type: string InDom: 155.1 0x26c00001 Semantics: instant Units: count Help: -The resource role that the location contraint applies to, if any. +The resource role that the location constraint applies to, if any. inst [0 or "test"] value "Started" ha_cluster.pacemaker.location_constraints.score PMID: 155.2.3 [Score of the location constraint] @@ -327,12 +359,23 @@ Semantics: instant Units: count Help: The raw values for the cluster metadata attributes and their value per node as -used by the Resource Agents. +used by the Resource Agents. inst [0 or "node-1:test_clone_state"] value "PROMOTED" inst [1 or "node-1:test_site"] value "PRIMARY_SITE_NAME" inst [2 or "node-2:test_clone_state"] value "DEMOTED" inst [3 or "node-2:test_site"] value "SECONDARY_SITE_NAME" +ha_cluster.pacemaker.node_attributes_all PMID: 155.13.0 [Metadata information] + Data Type: 32-bit unsigned int InDom: 155.11 0x26c0000b + Semantics: instant Units: count +Help: +Value is 1 if a node metadata exists. The details of the node metadata +is given as label metadata values for this metric. + inst [0 or "node-1:test_clone_state"] value 1 + inst [1 or "node-1:test_site"] value 1 + inst [2 or "node-2:test_clone_state"] value 1 + inst [3 or "node-2:test_site"] value 1 + ha_cluster.pacemaker.nodes.status.dc PMID: 155.3.8 [Whether the node status is given as disconnected] Data Type: 32-bit unsigned int InDom: 155.2 0x26c00002 Semantics: instant Units: count @@ -435,6 +478,19 @@ inst [4 or "rsc_fs_TEST:node-1"] value "ocf::heartbeat:Filesystem" inst [3 or "rsc_ip_TEST:node-1"] value "ocf::heartbeat:IPaddr2" +ha_cluster.pacemaker.resources.all PMID: 155.14.0 [Pacemaker resources information] + Data Type: 32-bit unsigned int InDom: 155.12 0x26c0000c + Semantics: instant Units: count +Help: +Value is 1 if a resources exists. The details of the resource +is given as label metadata values for this metric. + inst [0 or "my_first_svc:node-1"] value 1 + inst [5 or "rsc_TEST:node-1"] value 1 + inst [1 or "rsc_Test:node-1"] value 1 + inst [2 or "rsc_Test:node-2"] value 1 + inst [4 or "rsc_fs_TEST:node-1"] value 1 + inst [3 or "rsc_ip_TEST:node-1"] value 1 + ha_cluster.pacemaker.resources.clone PMID: 155.5.1 [The name of the clone given for this resource] Data Type: string InDom: 155.4 0x26c00004 Semantics: instant Units: count @@ -557,6 +613,14 @@ Value returns as to whether stonith is enabled or disabled for the cluster. value 0 +ha_cluster.sbd.all PMID: 155.16.0 [SBD device information] + Data Type: 32-bit unsigned int InDom: 155.14 0x26c0000e + Semantics: instant Units: count +Help: +Value is 1 if a sbd device exists. The details of the corresponding SBD device +is given as label metadata values for this metric. + inst [0 or "/dev/vdb"] value 1 + ha_cluster.sbd.devices.path PMID: 155.9.0 [Path of SBD device] Data Type: string InDom: 155.7 0x26c00007 Semantics: instant Units: count diff -Nru pcp-5.3.1/qa/1901 pcp-5.3.2/qa/1901 --- pcp-5.3.1/qa/1901 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/1901 2021-07-30 04:05:06.000000000 +0000 @@ -28,18 +28,28 @@ spec=qa-$seq-%Y%m%d.%H.%M echo "== checking SIGUSR2 reexec does not leak FDs" | tee -a $seq.full -$PMLOGGER -U$username -s10 -t 1s -c config.default -l $tmp/pmlogger.log $tmp/$spec 2>$tmp/$seq.err & -pid=$!; sleep 5; -before=`$sudo pminfo -f proc.fd.count | awk '$2 ~ "'$pid'" {print $NF}'` -$sudo -u $username kill -USR2 $pid; sleep 5 -after=`$sudo pminfo -f proc.fd.count | awk '$2 ~ "'$pid'" {print $NF}'` +$PMLOGGER -U$username -t 2s -c config.default -l $tmp/pmlogger.log $tmp/$spec 2>$tmp/$seq.err & +pid=$! +echo "pid=$pid" >>$seq.full +_wait_for_pmlogger $pid $tmp/pmlogger.log +sleep 5 +before=`$sudo pminfo -f proc.fd.count | awk '$2 ~ /^\['$pid'$/ {print $NF}'` +echo "before=$before" >>$seq.full +$sudo -u $username kill -USR2 $pid +sleep 5 +after=`$sudo pminfo -f proc.fd.count | awk '$2 ~ /^\['$pid'$/ {print $NF}'` +echo "after=$pid" >>$seq.full echo === log === >>$seq.full; cat $tmp/pmlogger.log >>$seq.full echo === err === >>$seq.full; cat $tmp/$seq.err >>$seq.full -if [ "$before" -ne "$after" ] +if [ "$before" != "$after" ] then echo "FAILED $before not equal to $after" + echo pid=$pid status=1 else status=0 fi +$sudo -u $username kill -TERM $pid +_wait_pmlogger_end $pid + exit diff -Nru pcp-5.3.1/qa/213.out pcp-5.3.2/qa/213.out --- pcp-5.3.1/qa/213.out 2018-02-13 04:56:52.000000000 +0000 +++ pcp-5.3.2/qa/213.out 2021-07-30 04:05:06.000000000 +0000 @@ -130,7 +130,8 @@ dbpmda> text mmv.test.strings PMID: 70.1.6 [test string metrics] -Yes, this is a test string metric with instances +Yes +This is a test string metric with instances dbpmda> store mmv.control.reload "1" PMID: 70.0.0 Getting description... @@ -158,7 +159,8 @@ dbpmda> text mmv.test.strings PMID: 70.1.6 [test string metrics] -Yes, this is a test string metric with instances +Yes +This is a test string metric with instances dbpmda> store mmv.control.reload "1" PMID: 70.0.0 Getting description... diff -Nru pcp-5.3.1/qa/220 pcp-5.3.2/qa/220 --- pcp-5.3.1/qa/220 2019-11-28 22:40:45.000000000 +0000 +++ pcp-5.3.2/qa/220 2021-07-30 04:05:06.000000000 +0000 @@ -53,6 +53,24 @@ _wait_for_pmcd _wait_for_pmlogger clean=true + + # for some systems we're seeing ... + # Job for pmlogger.service failed because the service did + # not take the steps required by its unit configuration. + # try to figure out why + # + if which systemctl >/dev/null 2>&1 + then + eval `systemctl show pmlogger.service --property=ActiveState` + if [ "$ActiveState" != active ] + then + $sudo systemctl status pmlogger.service >>$here/$seq.full + if which journalctl >/dev/null 2>&1 + then + $sudo journalctl -xe -u pmlogger.service >>$here/$seq.full + fi + fi + fi fi $sudo rm -f $tmp.* } @@ -67,10 +85,21 @@ # Make sure we have a stable starting point. This test was passing when # run alone, but failing if test 184 was run immediately before it. _service pmlogger restart 2>&1 | _filter_pcp_start +_wait_for_pmlogger +# all running, get primary pmlogger pid, then stop 'em all +# +_pid=`cat $PCP_RUN_DIR/pmlogger.pid 2>/dev/null` +if [ -z "$_pid" ] +then + echo "Botch: primary pmlogger PID not found" + ls -l $PCP_RUN_DIR +fi _service pcp stop | _filter_pcp_stop -echo "primary pmlogger processes? exect none" -ps $PCP_PS_ALL_FLAGS | grep 'pmlogger.* -P' | grep -v grep +_wait_pmcd_end +[ -n "$_pid" ] && _wait_pmlogger_end $_pid +echo "primary pmlogger processes? expect none" +ps $PCP_PS_ALL_FLAGS | grep '[p]mlogger.* -P' echo echo "primary port map? expect none" diff -Nru pcp-5.3.1/qa/220.out pcp-5.3.2/qa/220.out --- pcp-5.3.1/qa/220.out 2019-04-26 01:44:32.000000000 +0000 +++ pcp-5.3.2/qa/220.out 2021-07-30 04:05:06.000000000 +0000 @@ -1,5 +1,5 @@ QA output created by 220 -primary pmlogger processes? exect none +primary pmlogger processes? expect none primary port map? expect none not there - goodness. diff -Nru pcp-5.3.1/qa/226.out pcp-5.3.2/qa/226.out --- pcp-5.3.1/qa/226.out 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/qa/226.out 2021-07-30 04:05:06.000000000 +0000 @@ -6,7 +6,7 @@ children metric-name close debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) desc metric fetch metric [ metric ... ] getdesc on | off @@ -65,7 +65,7 @@ dbpmda> help debug debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) Specify which debugging options should be active (see pmdbg(1)). Options may be specified by name (or number for the old bit-field options), with diff -Nru pcp-5.3.1/qa/249 pcp-5.3.2/qa/249 --- pcp-5.3.1/qa/249 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/249 2021-06-15 01:03:49.000000000 +0000 @@ -64,20 +64,14 @@ # deal with possible scientific notation from # diagnostic %g printfs in libpcp and then # possible suppression of trailing zeroes in - # the fractional part in libc + # the fractional part in libc ... matching + # 4 significant digits is probably close + # enough # - printf "s/ val=%.6fe+06$/ val=/\n",($4+0.5)/1000000,n - printf "s/ val=%.5fe+06$/ val=/\n",($4+0.5)/1000000,n - if ($4 % 100 == 0) - printf "s/ val=%.4fe+06$/ val=/\n",($4+0.5)/1000000,n - if ($4 % 1000 == 0) - printf "s/ val=%.3fe+06$/ val=/\n",($4+0.5)/1000000,n - if ($4 % 10000 == 0) - printf "s/ val=%.2fe+06$/ val=/\n",($4+0.5)/1000000,n - if ($4 % 100000 == 0) - printf "s/ val=%.1fe+06$/ val=/\n",($4+0.5)/1000000,n - if ($4 % 1000000 == 0) - printf "s/ val=%.0fe+06$/ val=/\n",($4+0.5)/1000000,n + printf "s/ val=%.6fe+06$/ val=/\n",$4/1000000,n + printf "s/ val=%.5f[0-9]*e+06$/ val=/\n",$4/1000000,n + printf "s/ val=%.4f[0-9]*e+06$/ val=/\n",$4/1000000,n + printf "s/ val=%.3f[0-9]*e+06$/ val=/\n",$4/1000000,n } n++ seen[$4] = "y" diff -Nru pcp-5.3.1/qa/251 pcp-5.3.2/qa/251 --- pcp-5.3.1/qa/251 2018-02-13 04:56:52.000000000 +0000 +++ pcp-5.3.2/qa/251 2021-07-30 04:05:06.000000000 +0000 @@ -37,7 +37,7 @@ status=1 # failure is the default! $sudo rm -rf $tmp.* $seq.full -trap "cd $here; rm -rf $tmp; exit \$status" 0 1 2 3 15 +trap "cd $here; rm -rf $tmp $tmp.*; exit \$status" 0 1 2 3 15 # real QA test starts here mkdir $tmp @@ -50,56 +50,62 @@ for inst in "bin-100" "bin-100,bin-500,bin-900" do echo - echo "All volumes present ... $inst ..." - pmval -z -O $offset -D128 -t2 -a ok-mv-bar -i $inst sampledso.bin 2>err >out - egrep 'Skip|Change' err - _filter $tmp.err >$tmp.out + cat $tmp.err >>$here/$seq.full + grep '^__pmLogChangeVol:' $tmp.err + _filter <$tmp.out [ -f die ] && exit echo - echo "First volume missing ... $inst ..." + echo "First volume missing ... $inst ..." | tee -a $here/$seq.full mv ok-mv-bar.0 foo.0 - pmval -z -O $offset -D128 -t2 -a ok-mv-bar -i $inst sampledso.bin 2>err >out - egrep 'Skip|Change' err - _filter $tmp.err >$tmp.out + cat $tmp.err >>$here/$seq.full + grep '^__pmLogChangeVol:' $tmp.err + _filter <$tmp.out [ -f die ] && exit mv foo.0 ok-mv-bar.0 echo - echo "Last volume missing ... $inst ..." + echo "Last volume missing ... $inst ..." | tee -a $here/$seq.full mv ok-mv-bar.3 foo.3 - pmval -z -O $offset -D128 -t2 -a ok-mv-bar -i $inst sampledso.bin 2>err >out - egrep 'Skip|Change' err - _filter $tmp.err >$tmp.out + cat $tmp.err >>$here/$seq.full + grep '^__pmLogChangeVol:' $tmp.err + _filter <$tmp.out [ -f die ] && exit mv foo.3 ok-mv-bar.3 echo - echo "Second volume missing ... $inst ..." + echo "Second volume missing ... $inst ..." | tee -a $here/$seq.full mv ok-mv-bar.1 foo.1 - pmval -z -O $offset -D128 -t2 -a ok-mv-bar -i $inst sampledso.bin 2>err >out - egrep 'Skip|Change' err - _filter $tmp.err >$tmp.out + cat $tmp.err >>$here/$seq.full + grep '^__pmLogChangeVol:' $tmp.err + _filter <$tmp.out [ -f die ] && exit mv foo.1 ok-mv-bar.1 echo - echo "Second last volume missing ... $inst ..." + echo "Second last volume missing ... $inst ..." | tee -a $here/$seq.full mv ok-mv-bar.2 foo.2 - pmval -z -O $offset -D128 -t2 -a ok-mv-bar -i $inst sampledso.bin 2>err >out - egrep 'Skip|Change' err - _filter $tmp.err >$tmp.out + cat $tmp.err >>$here/$seq.full + grep '^__pmLogChangeVol:' $tmp.err + _filter <$tmp.out [ -f die ] && exit mv foo.2 ok-mv-bar.2 echo - echo "All volumes but second missing ... $inst ..." + echo "All volumes but second missing ... $inst ..." | tee -a $here/$seq.full mv ok-mv-bar.0 foo.0 mv ok-mv-bar.2 foo.2 mv ok-mv-bar.3 foo.3 - pmval -z -O $offset -D128 -t2 -a ok-mv-bar -i $inst sampledso.bin 2>err >out - egrep 'Skip|Change' err - _filter $tmp.err >$tmp.out + cat $tmp.err >>$here/$seq.full + grep '^__pmLogChangeVol:' $tmp.err + _filter <$tmp.out [ -f die ] && exit mv foo.0 ok-mv-bar.0 mv foo.2 ok-mv-bar.2 diff -Nru pcp-5.3.1/qa/280 pcp-5.3.2/qa/280 --- pcp-5.3.1/qa/280 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/qa/280 2021-07-30 04:05:06.000000000 +0000 @@ -60,10 +60,10 @@ _cleanup() { _restore_config $PCP_ETC_DIR/pcp/pmlogger - _service pmcd restart 2>&1 | _filter_pcp_start + _service pmcd restart 2>&1 | tee -a $seq.full | _filter_pcp_start _wait_for_pmcd _restore_auto_restart pmcd - _service pmlogger restart 2>&1 | _filter_pcp_start + _service pmlogger restart 2>&1 | tee -a $seq.full | _filter_pcp_start _wait_for_pmlogger _restore_auto_restart pmlogger } @@ -78,6 +78,7 @@ # start from a known state # _service pcp stop >/dev/null 2>&1 +_wait_pmcd_end _service pcp start 2>&1 | _filter_pcp_start _wait_for_pmcd _wait_for_pmlogger -P $LOGGING_DIR/$LOCALHOST/pmlogger.log diff -Nru pcp-5.3.1/qa/283 pcp-5.3.2/qa/283 --- pcp-5.3.1/qa/283 2019-02-26 21:38:22.000000000 +0000 +++ pcp-5.3.2/qa/283 2021-07-30 04:05:06.000000000 +0000 @@ -32,6 +32,21 @@ } trap "_cleanup; exit \$status" 0 1 2 3 15 +rm -f $seq.full + +# Test is failing on test-centos6-container in CI deep inside +# the avahi code (not the PCP code), so we've decided to +# _notrun on anything related to RHEL 6. +# +case `admin/whatami` +in + *CentOS6.*) + _notrun "dodge avahi issue on CentOS 6" + ;; + *RHEL*6.*) + _notrun "dodge avahi issue on RHEL 6" + ;; +esac _filter() { @@ -49,8 +64,6 @@ # allow time to cleanup and close all sockets sleep 3 -rm -f $seq.full - # figure out which user we will run pmcd and its pmdas as username=`id -u -n` sudoopts="-u $username" diff -Nru pcp-5.3.1/qa/294 pcp-5.3.2/qa/294 --- pcp-5.3.1/qa/294 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/294 2021-07-30 04:05:06.000000000 +0000 @@ -41,6 +41,10 @@ _cleanup() { + # kill off the pmproxy we started + # + $sudo $signal -a pmproxy >>$here/$seq.full 2>&1 + if $pmproxy_was_running then echo "Restart pmproxy ..." >>$here/$seq.full @@ -158,10 +162,11 @@ proxyargs="-Dcontext -U $username" $PCP_BINADM_DIR/pmproxy $proxyargs -l $tmp.log 2>&1 | _filter_pmproxy _wait_for_pmproxy + +export PMPROXY_HOST=localhost $PCP_BINADM_DIR/pmcd_wait -t 5sec -h localhost@localhost # real QA test starts here -export PMPROXY_HOST=localhost _do pminfo -h $PMPROXY_HOST -d pmcd.agent _do pminfo -h $PMPROXY_HOST -f sample.hordes _do pmprobe -v -h localhost hinv.ncpu diff -Nru pcp-5.3.1/qa/295 pcp-5.3.2/qa/295 --- pcp-5.3.1/qa/295 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/295 2021-06-15 01:03:49.000000000 +0000 @@ -27,6 +27,10 @@ _cleanup() { + # kill off the pmproxy we started + # + $sudo $signal -a pmproxy >>$here/$seq.full 2>&1 + if $pmproxy_was_running then echo "Restart pmproxy ..." >>$here/$seq.full @@ -61,8 +65,26 @@ echo "--- end $tmp.log ---" >>$here/$seq.full } -_service pmproxy stop >/dev/null 2>&1 -$sudo $signal -a pmproxy >/dev/null 2>&1 +_service pmproxy stop >>$here/$seq.full 2>&1 +if $pmproxy_was_running +then + i=0 + while [ $i -lt 10 ] + do + if [ ! -f $PCP_RUN_DIR/pmproxy.pid ] + then + break + fi + sleep 1 + i=`expr $i + 1` + done + if [ $i -ge 10 ] + then + echo "Warning: failed to kill off pmproxy" + ls -l $PCP_RUN_DIR/pmproxy.pid + cat $PCP_RUN_DIR/pmproxy.pid + fi +fi mkdir -p $tmp.rundir export PCP_RUN_DIR=$tmp.rundir diff -Nru pcp-5.3.1/qa/297 pcp-5.3.2/qa/297 --- pcp-5.3.1/qa/297 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/qa/297 2021-07-30 04:05:06.000000000 +0000 @@ -118,6 +118,7 @@ -e '/^IPC table fd/d' \ -e '/^__pmSetVersionIPC: fd=/d' \ -e '/^__pmSetFeaturesIPC: fd=/d' \ + -e '/^__pmSquashTZ/d' \ -e 's/localhost/MY_HOST/g' \ -e '/^pmproxy: disabled time series, requires libuv support (missing)/d' \ # end diff -Nru pcp-5.3.1/qa/326 pcp-5.3.2/qa/326 --- pcp-5.3.1/qa/326 2020-11-10 22:19:53.000000000 +0000 +++ pcp-5.3.2/qa/326 2021-07-30 04:05:06.000000000 +0000 @@ -93,6 +93,7 @@ $PCP_BINADM_DIR/pmcd -f -c $tmp.pmcd.config -l $tmp.pmcd.log -U $iam -s $tmp.socket & pmcd_pid=$! echo "pmcd_pid=$pmcd_pid" >>$seq.full +_wait_for_pmcd cat <$tmp.config log mandatory on 500 msec { pmcd.numagents sample.milliseconds } diff -Nru pcp-5.3.1/qa/439 pcp-5.3.2/qa/439 --- pcp-5.3.1/qa/439 2015-08-06 05:46:36.000000000 +0000 +++ pcp-5.3.2/qa/439 2021-07-30 04:05:06.000000000 +0000 @@ -23,7 +23,9 @@ sed \ -e 's/[A-Z][a-z][a-z] [A-Z][a-z][a-z] *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9]/DATE/' \ -e 's/logcontrol([0-9][0-9]*)/logcontrol(PID)/' \ - -e "s/$$/MYPID/g" \ + -e "s/($$)/(MYPID)/g" \ + -e "s@/$$:@/MYPID:@g" \ + -e "s@/$$ @/MYPID @g" \ -e "s;$PCP_TMP_DIR;\$PCP_TMP_DIR;g" \ -e 's/TCP connection reset by peer/Connection refused/' } diff -Nru pcp-5.3.1/qa/492.out pcp-5.3.2/qa/492.out --- pcp-5.3.1/qa/492.out 2017-10-10 02:18:22.000000000 +0000 +++ pcp-5.3.2/qa/492.out 2021-07-30 04:05:06.000000000 +0000 @@ -13,6 +13,7 @@ -s, --scale do scale conversion -v, --verbose increased diagnostic verbosity -w, --warnings emit warnings [default is silence] + -?, --help show this usage message and exit output-archive is required unless -i is specified @@ -28,6 +29,7 @@ -s, --scale do scale conversion -v, --verbose increased diagnostic verbosity -w, --warnings emit warnings [default is silence] + -?, --help show this usage message and exit output-archive is required unless -i is specified @@ -44,6 +46,7 @@ -s, --scale do scale conversion -v, --verbose increased diagnostic verbosity -w, --warnings emit warnings [default is silence] + -?, --help show this usage message and exit output-archive is required unless -i is specified @@ -60,6 +63,7 @@ -s, --scale do scale conversion -v, --verbose increased diagnostic verbosity -w, --warnings emit warnings [default is silence] + -?, --help show this usage message and exit output-archive is required unless -i is specified @@ -78,6 +82,7 @@ -s, --scale do scale conversion -v, --verbose increased diagnostic verbosity -w, --warnings emit warnings [default is silence] + -?, --help show this usage message and exit output-archive is required unless -i is specified @@ -94,6 +99,7 @@ -s, --scale do scale conversion -v, --verbose increased diagnostic verbosity -w, --warnings emit warnings [default is silence] + -?, --help show this usage message and exit output-archive is required unless -i is specified diff -Nru pcp-5.3.1/qa/514 pcp-5.3.2/qa/514 --- pcp-5.3.1/qa/514 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/514 2021-07-30 04:05:06.000000000 +0000 @@ -195,13 +195,16 @@ echo "SYSLOG ..." if $have_journalctl then + # may need to wait for journalctl to catchup + sleep 5 # be careful ... --boot not supported in all versions, -l not # supported in all versions - $sudo journalctl -b --full | tail -200 >$tmp.syslog 2>>$seq.full + $sudo journalctl -b --full 2>&1 | tail -200 >$tmp.syslog 2>>$seq.full else $sudo tail -200 $SYSLOG >$tmp.syslog fi sed <$tmp.syslog -n \ + -e '/^Journal file .* is truncated, ignoring/d' \ -e 's/PCP QA '"$seq"'/PCP QA xxx/' \ -e '/ncpu equal/s/ [0-9][0-9]*/ N/g' \ -e 's/PCP QA xxx/PCP QA '"$seq"'/' \ diff -Nru pcp-5.3.1/qa/515 pcp-5.3.2/qa/515 --- pcp-5.3.1/qa/515 2018-06-15 01:48:56.000000000 +0000 +++ pcp-5.3.2/qa/515 2021-07-30 04:05:06.000000000 +0000 @@ -20,12 +20,6 @@ $sudo rm -rf $tmp.* $seq.full trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 -_filter_err() -{ - sed \ - -e 's/.*Info: evaluator exiting/pmie: note - evaluator exiting/g' -} - _filter() { _filter_pmie_log @@ -69,7 +63,7 @@ echo "=== stderr ===" | tee -a $seq.full cat $tmp.err >>$seq.full -_filter_err <$tmp.err +_show_pmie_exit <$tmp.err echo "=== stdout ===" | tee -a $seq.full cat $tmp.out >>$seq.full # we used to count each uniq output line, but this is just too timing diff -Nru pcp-5.3.1/qa/535 pcp-5.3.2/qa/535 --- pcp-5.3.1/qa/535 2019-02-26 21:38:22.000000000 +0000 +++ pcp-5.3.2/qa/535 2021-07-30 04:05:06.000000000 +0000 @@ -44,7 +44,7 @@ pmprobe -I sample.dynamic.counter sample.dynamic.instant sample.dynamic.discrete -cat <$tmp.out 2>&1 & +cat <$tmp.out 2>$tmp.err & some_inst ( sample.dynamic.counter > 0 ) -> shell "echo counter:" " %i:?"; some_inst ( sample.dynamic.instant > 0 ) -> shell "echo instant:" " %i:?"; some_inst ( sample.dynamic.discrete > 0 ) -> shell "echo discrete:" " %i:?"; @@ -151,8 +151,13 @@ echo "=== pmie ===" LC_COLLATE=POSIX sort -u $tmp.out +cat $tmp.err | _show_pmie_errors -cp $tmp.out $seq.full +echo "== stdout ==" >$seq.full +cat $tmp.out >>$seq.full +echo >>$seq.full +echo "== stderr ==" >>$seq.full +cat $tmp.err >>$seq.full # success, all done status=0 diff -Nru pcp-5.3.1/qa/560 pcp-5.3.2/qa/560 --- pcp-5.3.1/qa/560 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/qa/560 2021-07-30 04:05:06.000000000 +0000 @@ -19,6 +19,30 @@ trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 $sudo rm -f $seq.full +echo "PCPQA_IN_CI=$PCPQA_IN_CI" >>$seq.full +if [ "$PCPQA_IN_CI" = yes ] +then + # in CI + # failing on test-ubuntu1804i386-container and nowhere else ... + # despite extensive triage, tcp port "already in use" problem + # persists + # + eval `src/sizeof ptr` + echo "ptr=$ptr" >>$seq.full + if [ "$ptr" = 4 ] + then + admin/whatami >>$seq.full + # 32-bit platform + case `admin/whatami` + in + *Ubuntu\ 18.04\ *) + # bingo ... no cigar + _notrun "cannot make this test work for test-ubuntu1804i386-container" + ;; + esac + fi +fi + # real QA test starts here cd $PCP_PMDAS_DIR/simple @@ -37,13 +61,16 @@ # see note below on bind: Address already in use issue # -port=`_get_port tcp 12078 12127` +port=`_get_port tcp 52078 52127` if [ -z "$port" ] then - echo "Arrgh ... no free TCP port in the range 12078 ... 12127" + echo "Arrgh ... no free TCP port in the range 52078 ... 52127" exit fi echo "port=$port" >>$here/$seq.full +echo "hostname: `hostname`" >>$here/$seq.full + +$sudo fuser tcp/$port >>$here/$seq.full 2>&1 cat <$tmp.out 2>&1 foo daemon @@ -90,7 +117,7 @@ # port ... otherwise the second install risks smacking into a # "bind: Address already in use" issue if the previous PMDA # process has not cleaned up ... this is why the first install -# uses a port in the range starting at 1000+2078, so the second +# uses a port in the range starting at 5000+2078, so the second # install below can use the default 2078 port # diff -Nru pcp-5.3.1/qa/564 pcp-5.3.2/qa/564 --- pcp-5.3.1/qa/564 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/564 2021-06-15 01:03:49.000000000 +0000 @@ -77,6 +77,8 @@ -e '/date-and-timestamp/d' \ -e '/^Roll .*\/NOTICES/d' \ -e '/^Start .*\/NOTICES/d' \ + -e '/^+ mv .*\/NOTICES/d' \ + -e '/^+ touch .*\/NOTICES/d' \ -e "s/$TODAY/TODAY/g" \ -e "s/$FIVEDAYS/FIVEDAYS/g" \ -e "s/$FIVEMONTHS/FIVEMONTHS/g" \ diff -Nru pcp-5.3.1/qa/574.out.darwin pcp-5.3.2/qa/574.out.darwin --- pcp-5.3.1/qa/574.out.darwin 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/574.out.darwin 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: PM_ID_NULL name: kernel.all.pswitch pmGetChildren: Unknown metric name diff -Nru pcp-5.3.1/qa/574.out.freebsd pcp-5.3.2/qa/574.out.freebsd --- pcp-5.3.1/qa/574.out.freebsd 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/574.out.freebsd 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 85.0.22 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/574.out.linux pcp-5.3.2/qa/574.out.linux --- pcp-5.3.1/qa/574.out.linux 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/574.out.linux 2021-06-15 01:03:49.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 60.0.13 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/574.out.netbsd pcp-5.3.2/qa/574.out.netbsd --- pcp-5.3.1/qa/574.out.netbsd 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/574.out.netbsd 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 116.5.1 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/574.out.openbsd pcp-5.3.2/qa/574.out.openbsd --- pcp-5.3.1/qa/574.out.openbsd 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/574.out.openbsd 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 139.5.1 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/574.out.solaris pcp-5.3.2/qa/574.out.solaris --- pcp-5.3.1/qa/574.out.solaris 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/574.out.solaris 2021-07-30 04:05:06.000000000 +0000 @@ -24,6 +24,7 @@ simabi timezone version + zoneinfo pmid: 75.0.23 name: kernel.all.pswitch diff -Nru pcp-5.3.1/qa/600 pcp-5.3.2/qa/600 --- pcp-5.3.1/qa/600 2019-08-16 01:19:15.000000000 +0000 +++ pcp-5.3.2/qa/600 2021-07-30 04:05:06.000000000 +0000 @@ -171,13 +171,7 @@ src/tztest >$seq.full TZ=XYZ-11; export TZ +src/tztest -# I don't understand the sed replacement below - Ken, Jul 2003 -# -src/tztest \ -| tee -a $seq.full \ -| sed \ - -e's|XYZ-11:03:04ABC-10:01:02,M12.5.0/3:04:05,M7.1.0/2:06:07|ABC-10:01:02XYZ-11:03:04,M12.5.0/3:04:05,M7.1.0/2:06:07|' \ - -e's|XYZ-11ABC-10,M12.5.0/3:01:02,M7.1.0/2:03:04|ABC-10XYZ-11,M12.5.0/3:01:02,M7.1.0/2:03:04|' status=0 exit diff -Nru pcp-5.3.1/qa/617.out pcp-5.3.2/qa/617.out --- pcp-5.3.1/qa/617.out 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/617.out 2021-07-30 04:05:06.000000000 +0000 @@ -7,7 +7,7 @@ children metric-name close debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) desc metric fetch metric [ metric ... ] getdesc on | off @@ -54,11 +54,11 @@ dbpmda> #test the debug and status commands dbpmda> debug# a command with a trailing comment debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) dbpmda> help debug debug all | none -debug option [ option ... ] (option is a symbolic name or a decimal number) +debug [-]flag [ [-]flag ... ] (- prefix to clear) Specify which debugging options should be active (see pmdbg(1)). Options may be specified by name (or number for the old bit-field options), with diff -Nru pcp-5.3.1/qa/646.out pcp-5.3.2/qa/646.out --- pcp-5.3.1/qa/646.out 2016-09-08 05:04:49.000000000 +0000 +++ pcp-5.3.2/qa/646.out 2021-07-30 04:05:06.000000000 +0000 @@ -30,13 +30,15 @@ units=count (no indom) shorttext=test counter metric - helptext=Yes, this is a test counter metric + helptext=Yes +This is a test counter metric [2/688] discrete type=32-bit int (0x0), sem=discrete (0x4), pad=0x0 units= (no indom) shorttext=test discrete metric - helptext=Yes, this is a test discrete metric + helptext=Yes +This is a test discrete metric [3/792] indom type=32-bit unsigned int (0x1), sem=instant (0x3), pad=0x0 units=count @@ -60,7 +62,8 @@ units= indom=1 shorttext=test string metrics - helptext=Yes, this is a test string metric with instances + helptext=Yes +This is a test string metric with instances TOC[3]: offset 88, values offset 1208 (10 entries) [1/1208] counter = 41 @@ -79,11 +82,14 @@ [2/1784] 00oo00 [3/2040] [4/2296] test counter metric - [5/2552] Yes, this is a test counter metric + [5/2552] Yes +This is a test counter metric [6/2808] test discrete metric - [7/3064] Yes, this is a test discrete metric + [7/3064] Yes +This is a test discrete metric [8/3320] test string metrics - [9/3576] Yes, this is a test string metric with instances + [9/3576] Yes +This is a test string metric with instances [10/3832] We can be heroes [11/4088] We can be heroes, just for one day MMV file = $PCP_TMP_DIR/mmv/notest-PID @@ -144,13 +150,15 @@ units=count (no indom) shorttext=test counter metric - helptext=Yes, this is a test counter metric + helptext=Yes +This is a test counter metric [2/688] discrete type=32-bit int (0x0), sem=discrete (0x4), pad=0x0 units= (no indom) shorttext=test discrete metric - helptext=Yes, this is a test discrete metric + helptext=Yes +This is a test discrete metric [3/792] indom type=32-bit unsigned int (0x1), sem=instant (0x3), pad=0x0 units=count @@ -174,7 +182,8 @@ units= indom=1 shorttext=test string metrics - helptext=Yes, this is a test string metric with instances + helptext=Yes +This is a test string metric with instances TOC[3]: offset 88, values offset 1208 (10 entries) [1/1208] counter = 41 @@ -193,11 +202,14 @@ [2/1784] 00oo00 [3/2040] [4/2296] test counter metric - [5/2552] Yes, this is a test counter metric + [5/2552] Yes +This is a test counter metric [6/2808] test discrete metric - [7/3064] Yes, this is a test discrete metric + [7/3064] Yes +This is a test discrete metric [8/3320] test string metrics - [9/3576] Yes, this is a test string metric with instances + [9/3576] Yes +This is a test string metric with instances [10/3832] We can be heroes [11/4088] We can be heroes, just for one day MMV file = $PCP_TMP_DIR/mmv/notest-PID diff -Nru pcp-5.3.1/qa/647.out pcp-5.3.2/qa/647.out --- pcp-5.3.1/qa/647.out 2019-04-26 01:44:32.000000000 +0000 +++ pcp-5.3.2/qa/647.out 2021-07-30 04:05:06.000000000 +0000 @@ -35,14 +35,16 @@ Data Type: 32-bit unsigned int InDom: PM_INDOM_NULL 0xffffffff Semantics: counter Units: count Help: -Yes, this is a test counter metric +Yes +This is a test counter metric value 41 mmv.test.discrete PMID: 70.1.2 [test discrete metric] Data Type: 32-bit int InDom: PM_INDOM_NULL 0xffffffff Semantics: discrete Units: none Help: -Yes, this is a test discrete metric +Yes +This is a test discrete metric value 42 mmv.test.indom PMID: 70.1.3 One-line Help: Error: One-line or help text is not available @@ -70,7 +72,8 @@ Data Type: string InDom: 70.2049 0x11800801 Semantics: instant Units: none Help: -Yes, this is a test string metric with instances +Yes +This is a test string metric with instances inst [0 or "zero"] value "00oo00" inst [1 or "hero"] value "" diff -Nru pcp-5.3.1/qa/662 pcp-5.3.2/qa/662 --- pcp-5.3.1/qa/662 2020-08-06 23:53:45.000000000 +0000 +++ pcp-5.3.2/qa/662 2021-07-30 04:05:06.000000000 +0000 @@ -11,6 +11,7 @@ _check_series _check_requests_json +_check_64bit_platform $sudo rm -f $tmp.* $seq.full signal=$PCP_BINADM_DIR/pmsignal diff -Nru pcp-5.3.1/qa/713 pcp-5.3.2/qa/713 --- pcp-5.3.1/qa/713 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/713 2021-06-15 01:03:49.000000000 +0000 @@ -19,6 +19,17 @@ _notrun "hostname -> $hostname, no domain name part" fi +# Despite intense triage, on some QA hosts this test simple fails to +# generate and install SSL certificates that the relevant libraries +# will accept as valid +# +case "$hostname" +in + vm01.localdomain|vm29.localdomain) + _notrun "cannot make SSL certificates work on this platform" + ;; +esac + _cleanup() { nss_cleanup diff -Nru pcp-5.3.1/qa/793 pcp-5.3.2/qa/793 --- pcp-5.3.1/qa/793 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/qa/793 2021-07-30 04:05:06.000000000 +0000 @@ -18,7 +18,7 @@ status=1 # failure is the default! $sudo rm -rf $tmp $tmp.* $seq.full -trap "cd $here; $sudo rm -rf $tmp $tmp.*; _cleanup; exit \$status" 0 1 2 3 15 +trap "_cleanup; exit \$status" 0 1 2 3 15 signal=$PCP_BINADM_DIR/pmsignal [ -f $NEEDREWRITE ] && $sudo mv $NEEDREWRITE $NEEDREWRITE.$seq @@ -61,11 +61,23 @@ _stop_loggers() { + echo "entering _stop_loggers ..." >>$here/$seq.full + $PCP_PS_PROG $PCP_PS_ALL_FLAGS \ + | egrep '[P]ID|[p]mlogger' \ + | tee -a $here/$seq.full \ + | grep '[p]mlogger ' \ + | $PCP_AWK_PROG '{print $2}' >$tmp.pids $sudo $signal -a -s TERM pmlogger + for pid in `cat $tmp.pids` + do + _wait_pmlogger_end "$pid" + echo "pmlogger [$pid] is done" >>$here/$seq.full + done } _cleanup() { + cd $here echo echo "Cleaning up" @@ -73,16 +85,31 @@ _stop_loggers >/dev/null 2>&1 + for x in A B C + do + echo "--- $tmp.$x.log ---" >>$here/$seq.full + cat $tmp.$x.log >>$here/$seq.full + echo "--- end pmlogger log ---" >>$here/$seq.full + if [ -f $tmp.$x.strace ] + then + echo "--- $tmp.$x.strace ---" >>$here/$seq.full + cat $tmp.$x.strace >>$here/$seq.full + echo "--- end strace ---" >>$here/$seq.full + fi + done + _service pmlogger restart 2>&1 \ | _filter_pcp_start \ _wait_for_pmlogger _restore_auto_restart pmlogger + + $sudo rm -rf $tmp $tmp.* } _setup() { _service pmlogger stop | _filter_pcp_stop - _stop_loggers >/dev/null 2>&1 + _stop_loggers cd } @@ -93,12 +120,12 @@ # for x in A B C do + rm -f $tmp.found $tmp.$x.pid z=0 - rm -f $tmp.found while [ "$z" -lt 30 ] do - # Cannot use $qatmp as the path prefix, because on some systems - # /var/tmp (what qatmp is set to) and /tmp are symlinked, and + # Cannot use $tmp as the path prefix, because on some systems + # /var/tmp (what $tmp is set to) and /tmp are symlinked, and # pmlogger reports the path in the control file using the real # name (/tmp) not the symlink name (/var/tmp) # ... spotted on vm37 (OpenBSD 6.7) @@ -108,17 +135,40 @@ pid=`grep -l "/$x/" $PCP_TMP_DIR/pmlogger/[0-9]* | sed -e 's/.*pmlogger.//'` if [ -n "$pid" ] then - echo "Found pid $pid for $qatmp/$x after $z iterations" >>$here/$seq.full - echo "status" | pmlc $pid >>$here/$seq.full - touch $tmp.found - break + echo "Found pid $pid for $tmp/$x after $z iterations" >>$here/$seq.full + echo "status" | pmlc $pid >$tmp.pmlc.out 2>&1 + cat $tmp.pmlc.out >>$here/$seq.full + if grep '^log size' $tmp.pmlc.out >/dev/null 2>&1 + then + touch $tmp.found + echo $pid >$tmp.$x.pid + break + fi fi z=`expr $z + 1` sleep 1 done if [ ! -f $tmp.found ] then - echo "Arrgh ... pmlogger_* failed to keep pmlogger running for $qatmp/$x" | tee -a $here/$seq.full + echo "Arrgh ... pmlogger_* failed to keep pmlogger running for $tmp/$x" | tee -a $here/$seq.full + echo "--- $tmp ---" >>$here/$seq.full + ls -l $tmp* >>$here/$seq.full + echo "--- $tmp/$x ---" >>$here/$seq.full + ls -l $tmp/$x >>$here/$seq.full + echo "--- $tmp.$x.log ---" >>$here/$seq.full + cat $tmp.$x.log >>$here/$seq.full + echo "--- end pmlogger log ---" >>$here/$seq.full + for log in log.prev log.from.check log.from.check.prev + do + echo "--- $tmp/$log ---" >>$here/$seq.full + if [ -f $tmp/$log ] + then + cat $tmp/$log >>$here/$seq.full + else + echo "" >>$here/$seq.full + fi + done + echo "--- end of logs ---" >>$here/$seq.full $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mlogger' >>$here/$seq.full for state in $PCP_TMP_DIR/pmlogger/[0-9]* do @@ -157,9 +207,9 @@ # # $qatmp from the caller's environment # $A from the control line above -LOCALHOSTNAME n n \$qatmp/\$A -c $tmp.config -LOCALHOSTNAME n n \$(echo $qatmp/B) -c $tmp.config -LOCALHOSTNAME n n "$qatmp/\`echo c | tr '[a-z]' '[A-Z]'\`" -c $tmp.config +LOCALHOSTNAME n n \$qatmp/\$A -c $tmp.config -l $tmp.A.log -Dservices,appl3,appl4 +LOCALHOSTNAME n n \$(echo $qatmp/B) -c $tmp.config -l $tmp.B.log -Dservices,appl3,appl4 +LOCALHOSTNAME n n "$qatmp/\`echo c | tr '[a-z]' '[A-Z]'\`" -c $tmp.config -l $tmp.C.log -Dservices,appl3,appl4 End-of-File cat $tmp/control >>$here/$seq.full @@ -168,7 +218,11 @@ echo "pmlogger_check #1" | tee -a $here/$seq.full $sudo sh -c "qatmp=$qatmp $PCP_BINADM_DIR/pmlogger_check -V -c $tmp/control -l $tmp/log" -[ -s $tmp/log ] && $sudo cat $tmp/log | tee -a $here/$seq.full | _filter +if [ -s $tmp/log ] +then + echo "$tmp.log from pmlogger_check #1 ..." >>$here/$seq.full + $sudo cat $tmp/log | tee -a $here/$seq.full | _filter +fi _check_loggers for x in A B C do @@ -176,33 +230,72 @@ echo `ls $tmp/$x | grep "\.meta" | wc -l | sed -e 's/ //g'` archives in TMP/$x done -sleep 2 -_stop_loggers >/dev/null 2>&1 +# let pmloggers run for a while +sleep 1 + +_stop_loggers echo "pmlogger_check #2" | tee -a $here/$seq.full $sudo sh -c "qatmp=$qatmp $PCP_BINADM_DIR/pmlogger_check -V -c $tmp/control -l $tmp/log" -[ -s $tmp/log ] && $sudo cat $tmp/log | tee -a $here/$seq.full | _filter +if [ -s $tmp/log ] +then + echo "$tmp.log from pmlogger_check #2 ..." >>$here/$seq.full + $sudo cat $tmp/log | tee -a $here/$seq.full | _filter +fi _check_loggers for x in A B C do + echo "--- $tmp/$x ---" >>$here/$seq.full ls -l $tmp/$x >>$here/$seq.full echo `ls $tmp/$x | grep "\.meta" | wc -l | sed -e 's/ //g'` archives in TMP/$x done +# let pmloggers run for a while +sleep 1 + echo "pmlogger processes ..." >>$here/$seq.full $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mlogger' >>$here/$seq.full +# this test has a history of failing in the pmlogger_daily step below +# when one (or more) of the pmlogger processes vanishes, so we're +# taking extreme measures here! +# +if which strace >/dev/null 2>&1 +then + for x in A B C + do + $sudo strace -p `cat $tmp.$x.pid` >$tmp.$x.strace 2>&1 & + done +fi + echo echo "pmlogger_daily" -$sudo sh -c "qatmp=$qatmp $PCP_BINADM_DIR/pmlogger_daily -V -x never -c $tmp/control -l $tmp/log" -[ -s $tmp/log ] && $sudo cat $tmp/log | tee -a $here/$seq.full | _filter +$sudo sh -c "qatmp=$qatmp $PCP_BINADM_DIR/pmlogger_daily -VV -x never -c $tmp/control -l $tmp/log" +if [ -s $tmp/log ] +then + echo "$tmp.log from pmlogger_daily ..." >>$here/$seq.full + cat $tmp/log >>$here/$seq.full + sed -n <$tmp/log \ + -e '/^=== /p' \ + -e '/^$/p' \ + -e '/merge/p' \ + | _filter +fi + +# wait a bit to be sure all pmloggers have finished their re-exec +# song and dance +sleep 1 + _check_loggers for x in A B C do + echo "--- $tmp/$x ---" >>$here/$seq.full ls -l $tmp/$x >>$here/$seq.full echo `ls $tmp/$x | grep "\.meta" | wc -l | sed -e 's/ //g'` archives in TMP/$x done +rm -f $tmp.?.strace + # success, all done status=0 exit diff -Nru pcp-5.3.1/qa/795 pcp-5.3.2/qa/795 --- pcp-5.3.1/qa/795 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/795 2021-07-30 04:05:06.000000000 +0000 @@ -22,6 +22,13 @@ [ $? -eq 0 ] || _notrun "perl XML::TokeParser module not installed" perl -e "use Spreadsheet::ReadSXC" >>$seq.full 2>&1 [ $? -eq 0 ] || _notrun "perl Spreadsheet::ReadSXC module not installed" +cat <$tmp.pl +use Spreadsheet::ReadSXC; +Spreadsheet::ReadSXC::read_sxc("/dev/null"); +exit(0); +End-of-File +perl eek.pl >>$seq.full 2>&1 +[ $? -eq 0 ] || _notrun "perl Spreadsheet::ReadSXC::read_sxc() routine not found" trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 diff -Nru pcp-5.3.1/qa/821.out pcp-5.3.2/qa/821.out --- pcp-5.3.1/qa/821.out 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/821.out 2021-07-30 04:05:06.000000000 +0000 @@ -38,38 +38,38 @@ mem.buddyinfo.total inst [0 or "DMA::order0::node0"] value 12 - inst [1 or "DMA::order1::node0"] value 4 - inst [2 or "DMA::order2::node0"] value 8 - inst [3 or "DMA::order3::node0"] value 8 - inst [4 or "DMA::order4::node0"] value 8 - inst [5 or "DMA::order5::node0"] value 4 + inst [1 or "DMA::order1::node0"] value 8 + inst [2 or "DMA::order2::node0"] value 32 + inst [3 or "DMA::order3::node0"] value 64 + inst [4 or "DMA::order4::node0"] value 128 + inst [5 or "DMA::order5::node0"] value 128 inst [6 or "DMA::order6::node0"] value 0 inst [7 or "DMA::order7::node0"] value 0 - inst [8 or "DMA::order8::node0"] value 4 - inst [9 or "DMA::order9::node0"] value 4 - inst [10 or "DMA::order10::node0"] value 12 + inst [8 or "DMA::order8::node0"] value 1024 + inst [9 or "DMA::order9::node0"] value 2048 + inst [10 or "DMA::order10::node0"] value 12288 inst [11 or "DMA32::order0::node0"] value 1880 - inst [12 or "DMA32::order1::node0"] value 2096 - inst [13 or "DMA32::order2::node0"] value 392 - inst [14 or "DMA32::order3::node0"] value 616 - inst [15 or "DMA32::order4::node0"] value 344 - inst [16 or "DMA32::order5::node0"] value 120 - inst [17 or "DMA32::order6::node0"] value 92 - inst [18 or "DMA32::order7::node0"] value 40 - inst [19 or "DMA32::order8::node0"] value 104 - inst [20 or "DMA32::order9::node0"] value 48 - inst [21 or "DMA32::order10::node0"] value 2724 + inst [12 or "DMA32::order1::node0"] value 4192 + inst [13 or "DMA32::order2::node0"] value 1568 + inst [14 or "DMA32::order3::node0"] value 4928 + inst [15 or "DMA32::order4::node0"] value 5504 + inst [16 or "DMA32::order5::node0"] value 3840 + inst [17 or "DMA32::order6::node0"] value 5888 + inst [18 or "DMA32::order7::node0"] value 5120 + inst [19 or "DMA32::order8::node0"] value 26624 + inst [20 or "DMA32::order9::node0"] value 24576 + inst [21 or "DMA32::order10::node0"] value 2789376 inst [22 or "Normal::order0::node0"] value 752 - inst [23 or "Normal::order1::node0"] value 1680 - inst [24 or "Normal::order2::node0"] value 572 - inst [25 or "Normal::order3::node0"] value 44 - inst [26 or "Normal::order4::node0"] value 8 + inst [23 or "Normal::order1::node0"] value 3360 + inst [24 or "Normal::order2::node0"] value 2288 + inst [25 or "Normal::order3::node0"] value 352 + inst [26 or "Normal::order4::node0"] value 128 inst [27 or "Normal::order5::node0"] value 0 inst [28 or "Normal::order6::node0"] value 0 inst [29 or "Normal::order7::node0"] value 0 inst [30 or "Normal::order8::node0"] value 0 inst [31 or "Normal::order9::node0"] value 0 - inst [32 or "Normal::order10::node0"] value 4 + inst [32 or "Normal::order10::node0"] value 4096 mem.freemem value 4650860 @@ -2352,38 +2352,38 @@ mem.buddyinfo.total inst [0 or "DMA::order0::node0"] value 12 - inst [1 or "DMA::order1::node0"] value 4 - inst [2 or "DMA::order2::node0"] value 8 - inst [3 or "DMA::order3::node0"] value 8 - inst [4 or "DMA::order4::node0"] value 8 - inst [5 or "DMA::order5::node0"] value 4 + inst [1 or "DMA::order1::node0"] value 8 + inst [2 or "DMA::order2::node0"] value 32 + inst [3 or "DMA::order3::node0"] value 64 + inst [4 or "DMA::order4::node0"] value 128 + inst [5 or "DMA::order5::node0"] value 128 inst [6 or "DMA::order6::node0"] value 0 inst [7 or "DMA::order7::node0"] value 0 - inst [8 or "DMA::order8::node0"] value 4 - inst [9 or "DMA::order9::node0"] value 4 - inst [10 or "DMA::order10::node0"] value 12 + inst [8 or "DMA::order8::node0"] value 1024 + inst [9 or "DMA::order9::node0"] value 2048 + inst [10 or "DMA::order10::node0"] value 12288 inst [11 or "DMA32::order0::node0"] value 1880 - inst [12 or "DMA32::order1::node0"] value 2096 - inst [13 or "DMA32::order2::node0"] value 392 - inst [14 or "DMA32::order3::node0"] value 616 - inst [15 or "DMA32::order4::node0"] value 344 - inst [16 or "DMA32::order5::node0"] value 120 - inst [17 or "DMA32::order6::node0"] value 92 - inst [18 or "DMA32::order7::node0"] value 40 - inst [19 or "DMA32::order8::node0"] value 104 - inst [20 or "DMA32::order9::node0"] value 48 - inst [21 or "DMA32::order10::node0"] value 2724 + inst [12 or "DMA32::order1::node0"] value 4192 + inst [13 or "DMA32::order2::node0"] value 1568 + inst [14 or "DMA32::order3::node0"] value 4928 + inst [15 or "DMA32::order4::node0"] value 5504 + inst [16 or "DMA32::order5::node0"] value 3840 + inst [17 or "DMA32::order6::node0"] value 5888 + inst [18 or "DMA32::order7::node0"] value 5120 + inst [19 or "DMA32::order8::node0"] value 26624 + inst [20 or "DMA32::order9::node0"] value 24576 + inst [21 or "DMA32::order10::node0"] value 2789376 inst [22 or "Normal::order0::node0"] value 752 - inst [23 or "Normal::order1::node0"] value 1680 - inst [24 or "Normal::order2::node0"] value 572 - inst [25 or "Normal::order3::node0"] value 44 - inst [26 or "Normal::order4::node0"] value 8 + inst [23 or "Normal::order1::node0"] value 3360 + inst [24 or "Normal::order2::node0"] value 2288 + inst [25 or "Normal::order3::node0"] value 352 + inst [26 or "Normal::order4::node0"] value 128 inst [27 or "Normal::order5::node0"] value 0 inst [28 or "Normal::order6::node0"] value 0 inst [29 or "Normal::order7::node0"] value 0 inst [30 or "Normal::order8::node0"] value 0 inst [31 or "Normal::order9::node0"] value 0 - inst [32 or "Normal::order10::node0"] value 4 + inst [32 or "Normal::order10::node0"] value 4096 == done diff -Nru pcp-5.3.1/qa/835 pcp-5.3.2/qa/835 --- pcp-5.3.1/qa/835 2019-04-26 01:44:32.000000000 +0000 +++ pcp-5.3.2/qa/835 2021-07-30 04:05:06.000000000 +0000 @@ -36,15 +36,16 @@ { # start from known starting points cd $PCP_PMDAS_DIR/memcache - $sudo ./Remove >/dev/null 2>&1 + $sudo ./Remove >>$here/$seq.full 2>&1 _service pmcd stop | _filter_pcp_stop + _wait_pmcd_end cat <$tmp.config \$memcache_delay = 1; @memcache_instances = ( 0 => '127.0.0.1:11211' ); EOF - echo "pmdamemcache config:" >> $here/$seq.full - cat $tmp.config >> $here/$seq.full + echo "pmdamemcache config:" >>$here/$seq.full + cat $tmp.config >>$here/$seq.full [ -f $PCP_PMDAS_DIR/memcache/memcache.conf ] && \ $sudo cp $PCP_PMDAS_DIR/memcache/memcache.conf $tmp.backup @@ -53,6 +54,7 @@ echo echo "=== memcache agent installation ===" $sudo ./Install $tmp.out 2>&1 + cat $tmp.out >>$here/$seq.full # Check metrics have appeared ... X metrics and Y values _filter_pmda_install <$tmp.out \ | sed \ diff -Nru pcp-5.3.1/qa/878 pcp-5.3.2/qa/878 --- pcp-5.3.1/qa/878 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/878 2021-07-30 04:05:06.000000000 +0000 @@ -16,13 +16,23 @@ [ -f $PCP_PMDAS_DIR/pipe/pmdapipe ] || _notrun "pipe PMDA not installed" id -u nobody >/dev/null 2>&1 || _notrun "User nobody unavailable" +# Despite intense triage, on some QA hosts this test simple fails +# when we don't see the first or second event record +# +hostname=`hostname` +case "$hostname" +in + vm01.localdomain|bozo-vm.localdomain) + _notrun "cannot make this test work on this platform" + ;; +esac + PIPE_CONF_FILE=$PCP_PMDAS_DIR/pipe/pipe.conf PIPE_CONF_DIR=$PCP_SYSCONF_DIR/pipe.conf.d PIPE_INDOM_CACHE=$PCP_VAR_DIR/config/pmda/128.0 status=1 # failure is the default! username=`id -u -n` -hostname=`hostname` $sudo rm -rf $tmp $tmp.* $seq.full _cleanup() diff -Nru pcp-5.3.1/qa/917 pcp-5.3.2/qa/917 --- pcp-5.3.1/qa/917 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/917 2021-06-15 01:03:49.000000000 +0000 @@ -55,6 +55,64 @@ sed -f $tmp.sed } +# As of Fedora 34, sedismod(1) is sorting the attributes ... to +# accommodate older versions of sedismod(1) and keep $seq.out in the +# same order we use the function below to sort both $seq.out.in and +# sedismod(1) output +# +# so we turn (for example) +# allow [pcp_pmproxy_t] [shadow_t] : [file] { ioctl read getattr lock open }; +# into +# allow [pcp_pmproxy_t] [shadow_t] : [file] { getattr ioctl lock open read }; +_sort_attr() +{ + $PCP_AWK_PROG ' +$1 == "allow" { + inattr = 0 + for (f = 1; f <= NF; f++) { + if (inattr == 0 && $f == "{") { + out = out " " $f + inattr = 1 + continue + } + if (inattr > 0 && $f == "};") { + # asort() is a GNU awk extension ... the list + # is short, so linear search is probably OK + for (a = 1; a < inattr; a++) { + pick = -1 + for (p = 1; p < inattr; p++) { + if (attrs[p] != "") { + if (pick == -1) { + # first unselected one + pick = p + } + else if (attrs[p] < attrs[pick]) { + # smallest unselected one, so far + pick = p + } + } + } + out = out " " attrs[pick] + attrs[pick] = "" + } + print " " out " };" + next + } + if (inattr) { + attrs[inattr] = $f + inattr++ + } + else { + if (f == 1) + out = $f + else + out = out " " $f + } + } + } + { print }' +} + status=1 # failure is the default! $sudo rm -rf $tmp $tmp.* $seq.full trap "cd $here; $sudo rm -rf $tmp $tmp.*; exit \$status" 0 1 2 3 15 @@ -66,8 +124,10 @@ echo '/^#/d' >$tmp.sed echo '/^!/s// /' >>$tmp.sed for type in container_runtime_t nsfs_t docker_var_lib_t unreserved_port_t \ - tracefs_t unconfined_service_t numad_t rpm_var_lib_t \ - virt_var_run_t proc_security_t sbd_exec_t kmod_exec_t + tracefs_t unconfined_service_t numad_t \ + virt_var_run_t proc_security_t sbd_exec_t kmod_exec_t \ + dma_device_t \ + # end do if grep "^[ ][ ]*$type\$" $tmp.types >/dev/null then @@ -97,9 +157,6 @@ numad_t) echo '/allow \[pcp_pmcd_t] \[numad_t]/d' >>$tmp.sed ;; - rpm_var_lib_t) - echo '/allow \[pcp_pmcd_t] \[rpm_var_lib_t]/d' >>$tmp.sed - ;; virt_var_run_t) echo '/allow \[pcp_pmcd_t] \[virt_var_run_t]/d' >>$tmp.sed ;; @@ -112,6 +169,9 @@ kmod_exec_t) echo '/allow \[pcp_pmcd_t] \[kmod_exec_t]/d' >>$tmp.sed ;; + dma_device_t) + echo '/allow \[pcp_pmcd_t] \[dma_device_t]/d' >>$tmp.sed + ;; esac fi @@ -125,6 +185,7 @@ : else echo '/allow \[pcp_pmie_t] .*\[cap_userns]/d' >>$tmp.sed + echo '/allow \[pcp_pmcd_t] .*\[cap_userns]/d' >>$tmp.sed fi if seinfo -x --class=file $common_flag 2>&1 \ @@ -139,7 +200,6 @@ # if no map, need to cull these one as map is the only permission # echo '/allow \[pcp_pmcd_t] \[ldconfig_exec_t] : \[file].* map/d' >>$tmp.sed - echo '/allow \[pcp_pmcd_t] \[rpm_var_lib_t] : \[file].* map/d' >>$tmp.sed echo '/allow \[pcp_pmcd_t] \[default_t] : \[file].* map/d' >>$tmp.sed # strip "map" from permissions for others # @@ -221,9 +281,25 @@ then : else + # from expansion of files_mmap_all_files(pcp_domain) + # echo '/allow \[pcp_domain] \[file_type] : \[file].* map/d' >>$tmp.sed fi +if grep 'PCP_SELINUX_LOGGING_WATCH_ALL_LOG_DIRS_PATH[ ]*=[ ]*true' $PCP_INC_DIR/builddefs >/dev/null 2>&1 +then + : +else + # from expansion of logging_watch_all_log_dirs_path(pcp_domain) + # + echo '/allow \[pcp_domain] \[root_t] : \[dir] /d' >>$tmp.sed + echo '/allow \[pcp_domain] \[var_t] : \[dir] /d' >>$tmp.sed + echo '/allow \[pcp_domain] \[logfile] : \[dir] /d' >>$tmp.sed + # and this one is from expansion of logging_watch_journal_dir(pcp_domain) + # + echo '/allow \[pcp_domain] \[syslogd_var_run_t] : \[dir] /d' >>$tmp.sed +fi + if seinfo -x --class=lockdown $common_flag 2>&1 \ | egrep '^[ ][ ]*(class |)lockdown$' >/dev/null then @@ -241,16 +317,32 @@ fi cat $tmp.sed >>$seq.full +echo "--- end of sed ---" >>$seq.full -cat $seq.out.in | _filter_outfile >$seq.out +cat $seq.out.in \ +| _filter_outfile \ +| _sort_attr >$seq.out -echo "full policy modules list on the system" -$sudo semodule -l >>$seq.full echo "Checking that pcpupstream policy module has been properly installed" -awk '{ print $1 }' $seq.full | grep "pcpupstream$" | _filter_semodule +echo "--- semodule -l ---" >>$seq.full +# two styles of semodule -l output need to be accommodated +# pcpupstream\t\n +# pcpupstream\n +# +$sudo semodule -l \ +| tee -a $seq.full \ +| sed -n \ + -e '/^pcpupstream[ ]/s/[ ].*//' \ + -e '/^pcpupstream$/p' \ +# end +echo "--- end of semodule -l ---" >>$seq.full # real QA test starts here echo "Checking policies." -printf '1\nq\n' | sedismod $policy_file | tee -a $seq.full | _filter_sedismod +printf '1\nq\n' \ +| sedismod $policy_file \ +| tee -a $seq.full \ +| _filter_sedismod \ +| _sort_attr # success, all done status=0 diff -Nru pcp-5.3.1/qa/917.out.in pcp-5.3.2/qa/917.out.in --- pcp-5.3.1/qa/917.out.in 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/917.out.in 2021-06-15 01:03:49.000000000 +0000 @@ -1,5 +1,4 @@ QA output created by 917 -full policy modules list on the system Checking that pcpupstream policy module has been properly installed pcpupstream Checking policies. @@ -28,7 +27,7 @@ allow [pcp_pmcd_t] [pcp_var_lib_t] : [fifo_file] { getattr read open unlink }; allow [pcp_pmcd_t] [proc_kcore_t] : [file] { getattr }; ! allow [pcp_pmcd_t] [proc_security_t] : [file] { getattr open read }; - allow [pcp_pmcd_t] self : [capability] { kill sys_pacct chown sys_chroot ipc_lock sys_resource }; + allow [pcp_pmcd_t] self : [capability] { kill sys_pacct chown sys_chroot ipc_lock ipc_owner sys_resource }; ! allow [pcp_pmcd_t] [nsfs_t] : [file] { getattr open read }; ! allow [pcp_pmcd_t] [unreserved_port_t] : [tcp_socket] { name_bind name_connect }; ! allow [pcp_pmcd_t] [unreserved_port_t] : [udp_socket] { name_bind }; @@ -68,6 +67,7 @@ allow [pcp_pmcd_t] [kernel_t] : [system] { module_request }; allow [pcp_pmcd_t] [su_exec_t] : [file] { execute execute_no_trans }; allow [pcp_pmcd_t] [postgresql_var_run_t] : [sock_file] { write }; +! allow [pcp_pmcd_t] self : [cap_userns] { sys_ptrace }; allow [pcp_pmlogger_t] [kmsg_device_t] : [chr_file] { open write }; allow [pcp_pmlogger_t] self : [capability] { kill sys_ptrace fowner fsetid }; allow [pcp_pmlogger_t] [unconfined_t] : [process] { signal }; @@ -126,13 +126,19 @@ allow [pcp_domain] [userdomain] : [sem] { unix_read associate getattr read }; allow [pcp_domain] [domain] : [unix_stream_socket] { connectto }; allow [pcp_domain] [port_type] : [tcp_socket] { name_connect }; +# -- start files_mmap_all_files(pcp_domain) expansion ! allow [pcp_domain] [file_type] : [file] { map }; +# -- end files_mmap_all_files(pcp_domain) expansion +# -- start logging_watch_all_log_dirs_path(pcp_domain) expansion ! allow [pcp_domain] [root_t] : [dir] { getattr watch }; ! allow [pcp_domain] [var_t] : [dir] { getattr open search }; ! allow [pcp_domain] [var_t] : [dir] { getattr open search }; ! allow [pcp_domain] [var_t] : [dir] { getattr watch }; ! allow [pcp_domain] [logfile] : [dir] { getattr open watch search }; +# -- end logging_watch_all_log_dirs_path(pcp_domain) expansion +# -- start logging_watch_journal_dirs(pcp_domain) expansion ! allow [pcp_domain] [syslogd_var_run_t] : [dir] { getattr watch }; +# -- end logging_watch_journal_dirs(pcp_domain) expansion allow [pcp_pmcd_t] [cluster_tmpfs_t] : [file] { write }; allow [pcp_pmcd_t] [drbd_exec_t] : [file] { execute execute_no_trans }; allow [pcp_pmcd_t] self : [netlink_generic_socket] { bind create getattr setopt write read }; diff -Nru pcp-5.3.1/qa/926 pcp-5.3.2/qa/926 --- pcp-5.3.1/qa/926 2018-02-13 04:56:52.000000000 +0000 +++ pcp-5.3.2/qa/926 2021-07-30 04:05:06.000000000 +0000 @@ -31,25 +31,33 @@ perl -e "use RRDs" >/dev/null 2>&1 [ $? -eq 0 ] || _notrun "perl RRDs module not installed" +status=0 # success is the default! +$sudo rm -rf $tmp.* $seq.full +trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 + +# We used to use uname -m to pick the right ganglia file, but +# this does not work in CI where the container "architecture" and +# the base platform architecture may not be the same +# The sizeof(void *) seem safer, which is what src/sizeof reports. +# +uname -a >>$seq.full +src/sizeof int long ptr >>$seq.full + rm -f $seq.out -machine=`uname -m` -case "$machine" +eval `src/sizeof ptr` +case "$ptr" in -i?86|athlon) +4) machine=32 ;; -amd64|x86_64) +8) machine=64 ;; esac [ -f $seq.out.$machine ] || \ - _notrun No qualified output for `uname -m` architecture. Please run mk-gangliatest and submit the new files. + _notrun No qualified output for ptr=$ptr architecture. Please run mk-gangliatest and submit the new files. ln $seq.out.$machine $seq.out || exit 1 -status=0 # success is the default! -$sudo rm -rf $tmp.* $seq.full -trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15 - # real QA test starts here # only one dir for now, add more if we get more sample data # rrdtool can't read data from different architectures diff -Nru pcp-5.3.1/qa/943.out pcp-5.3.2/qa/943.out --- pcp-5.3.1/qa/943.out 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/943.out 2021-07-30 04:05:06.000000000 +0000 @@ -61,11 +61,13 @@ proc.psinfo.cpusallowed -12387 No permission to perform requested operation proc.psinfo.cstime -12387 No permission to perform requested operation proc.psinfo.cutime -12387 No permission to perform requested operation +proc.psinfo.cwd -12387 No permission to perform requested operation proc.psinfo.delayacct_blkio_time -12387 No permission to perform requested operation proc.psinfo.eip -12387 No permission to perform requested operation proc.psinfo.end_code -12387 No permission to perform requested operation proc.psinfo.environ -12387 No permission to perform requested operation proc.psinfo.esp -12387 No permission to perform requested operation +proc.psinfo.exe -12387 No permission to perform requested operation proc.psinfo.exit_signal -12387 No permission to perform requested operation proc.psinfo.flags -12387 No permission to perform requested operation proc.psinfo.guest_time -12387 No permission to perform requested operation @@ -163,11 +165,13 @@ proc.psinfo.cpusallowed COUNT proc.psinfo.cstime COUNT proc.psinfo.cutime COUNT +proc.psinfo.cwd COUNT proc.psinfo.delayacct_blkio_time COUNT proc.psinfo.eip COUNT proc.psinfo.end_code COUNT proc.psinfo.environ COUNT proc.psinfo.esp COUNT +proc.psinfo.exe COUNT proc.psinfo.exit_signal COUNT proc.psinfo.flags COUNT proc.psinfo.guest_time COUNT diff -Nru pcp-5.3.1/qa/964 pcp-5.3.2/qa/964 --- pcp-5.3.1/qa/964 2020-04-24 00:15:07.000000000 +0000 +++ pcp-5.3.2/qa/964 2021-07-30 04:05:06.000000000 +0000 @@ -123,6 +123,13 @@ echo "Found same pmcd" else echo "Error: pmcd restarted? PID changed from $pmcd_pid to $new_pmcd_pid" + if [ -f $PCP_LOG_DIR/pmcd/pmcd.log.prior ] + then + echo "--- $PCP_LOG_DIR/pmcd/pmcd.log.prior ---" >>$here/$seq.full + cat $PCP_LOG_DIR/pmcd/pmcd.log.prior >>$here/$seq.full + else + echo "Cannot find $PCP_LOG_DIR/pmcd/pmcd.log.prior" >>$here/$seq.full + fi pmcd_pid=$new_pmcd_pid fi else @@ -142,6 +149,13 @@ else echo "Found new primary pmlogger" echo "Error: PID changed from $pid to $newpid" + if [ -f $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior ] + then + echo "--- $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior ---" >>$here/$seq.full + cat $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior >>$here/$seq.full + else + echo "Cannot find $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior" >>$here/$seq.full + fi pid=$newpid fi else @@ -185,6 +199,13 @@ else echo "Found new primary pmlogger" echo "Error: PID changed from $pid to $newpid" + if [ -f $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior ] + then + echo "--- $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior ---" >>$here/$seq.full + cat $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior >>$here/$seq.full + else + echo "Cannot find $PCP_LOG_DIR/pmlogger/`hostname`/pmlogger.log.prior" >>$here/$seq.full + fi pid=$newpid fi else diff -Nru pcp-5.3.1/qa/974 pcp-5.3.2/qa/974 --- pcp-5.3.1/qa/974 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/974 2021-07-30 04:05:06.000000000 +0000 @@ -15,12 +15,7 @@ pminfo proc.nprocs >/dev/null 2>&1 || _notrun "proc PMDA not installed" [ $PCP_PLATFORM = linux ] || _notrun "Linux proc test, only works with Linux" -case `pmprobe -v hinv.machine | sed -e 's/"$//' -e 's/.*"//'` -in - i?86) - _notrun "Need 64-bit machine to match /proc test data" - ;; -esac +_check_64bit_platform "Test needs 64-bit machine to match /proc test data" status=1 # failure is the default! $sudo rm -rf $tmp.* $seq.full diff -Nru pcp-5.3.1/qa/983 pcp-5.3.2/qa/983 --- pcp-5.3.1/qa/983 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/983 2021-07-30 04:05:06.000000000 +0000 @@ -27,7 +27,6 @@ && _notrun "Someone already listening on IPv6 port $port2" # (technically, this is a TOCTTOU race condition) - status=1 # failure is the default! $sudo rm -rf $tmp.* $seq.full @@ -37,7 +36,9 @@ { [ -z "$pmcd_pid" ] || $sudo $signal $pmcd_pid [ -z "$socat_pid" ] || $sudo $signal $socat_pid + export PMCD_PORT=$port1 _wait_pmcd_end + unset PMCD_PORT _service pcp restart 2>&1 \ | _filter_pcp_start \ | sed -e '/Waiting for pmcd to terminate/d' @@ -67,12 +68,11 @@ # see also qa/283 for "pmcd -p" testing. _service pmcd stop >/dev/null 2>&1 -# allow time to cleanup and close all sockets -sleep 3 +# wait for cleanup and closing all sockets +_wait_pmcd_end rm -f $seq.full - echo "=== starting pmcd on port $port1 ===" |tee -a $seq.full cat >$tmp.sh <$tmp.tmp` cat $tmp.tmp 1>&2 -sleep 1 - +export PMCD_PORT=$port1 +_wait_for_pmcd +unset PMCD_PORT echo "=== starting socat on port $port2 ===" |tee -a $seq.full # Filter the stderr of this using a temp file socat -d -d TCP-LISTEN:$port2,fork TCP:localhost:$port1 2>$tmp.socat & socat_pid=$! -sleep 1 +rm -f $tmp.socat +i=0 +while [ ! -f $tmp.socat -a $i -lt 10 ] +do + if $PCP_BINADM_DIR/telnet-probe -cv localhost $port1 2>>$seq.full + then + touch $tmp.socat + else + sleep 1 + i=`expr $i + 1` + fi +done +if [ ! -f $tmp.socat ] +then + echo "Failed to get socat started ... see $seq.full" + exit +fi cat >$tmp.pmie <$tmp.config +log mandatory on 1 sec { + mmv.qa +} +End-of-File + +rm -f mmv.help.index mmv.help.meta mmv.help.0 +pmlogger -c $tmp.config -s 10 mmv.help diff -Nru pcp-5.3.1/qa/archives/mk.pmproxy pcp-5.3.2/qa/archives/mk.pmproxy --- pcp-5.3.1/qa/archives/mk.pmproxy 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/archives/mk.pmproxy 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Recreate pmproxy archive +# + +tmp=/var/tmp/$$ +trap "rm -f $tmp.*; exit 0" 0 1 2 3 15 + +cat <$tmp.config +log mandatory on 1 sec { + pmproxy +} +End-of-File + +rm -f pmproxy.index pmproxy.meta pmproxy.0 +pmlogger -c $tmp.config -s 10 pmproxy Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/mmv.help.0 and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/mmv.help.0 differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/mmv.help.index and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/mmv.help.index differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/mmv.help.meta and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/mmv.help.meta differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/pcp-ss.0.xz and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/pcp-ss.0.xz differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/pcp-ss.index and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/pcp-ss.index differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/pcp-ss.meta.xz and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/pcp-ss.meta.xz differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/pmproxy.0 and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/pmproxy.0 differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/pmproxy.index and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/pmproxy.index differ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/archives/pmproxy.meta and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/archives/pmproxy.meta differ diff -Nru pcp-5.3.1/qa/common pcp-5.3.2/qa/common --- pcp-5.3.1/qa/common 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/common 2021-07-30 04:05:06.000000000 +0000 @@ -132,11 +132,8 @@ else _log_fyi $PCP_LOG_DIR/pmcd/pmcd.log $agentlog echo "Restarting PMCD ..." - SAVE_PCPQA_SYSTEMD=$PCPQA_SYSTEMD - unset PCPQA_SYSTEMD _service pmcd restart _wait_for_pmcd - export PCPQA_SYSTEMD=$SAVE_PCPQA_SYSTEMD restart=true fi if $reinstall @@ -223,8 +220,6 @@ # restart after a package install ... just going one step # at a time, carefully ... # - SAVE_PCPQA_SYSTEMD=$PCPQA_SYSTEMD - unset PCPQA_SYSTEMD _pid=`_get_pids_by_name -a 'pmlogger.*-P'` _service pmlogger stop if [ -n "$_pid" ] @@ -239,7 +234,6 @@ _wait_for_pmcd _service pmlogger start _wait_for_pmlogger - export PCPQA_SYSTEMD=$SAVE_PCPQA_SYSTEMD fi } @@ -306,11 +300,8 @@ ;; esac $sudo chown root:$grp $PCPQA_PMCDOPTIONS - SAVE_PCPQA_SYSTEMD=$PCPQA_SYSTEMD - unset PCPQA_SYSTEMD _service pmcd restart _wait_for_pmcd - export PCPQA_SYSTEMD=$SAVE_PCPQA_SYSTEMD fi } @@ -527,6 +518,8 @@ check options -c check configuration files [off] -C color mode output [off] + -CI run in CI environment => set $PCPQA_IN_CI in environment + and -x x11 -x remote -x not_in_ci -g group include tests from these groups (multiple flags allowed) -G report groups and number of tests per group -l line mode diff [xdiff] @@ -559,6 +552,12 @@ xpand=false ;; + -CI) # run in CI environment + # TODO still need -x x11 -x remote -x not_in_ci + export PCPQA_IN_CI=yes + xpand=false + ;; + -d) # directory for show-me snarf=d xpand=false @@ -841,11 +840,8 @@ if grep '^[^#]*PMCD_LOCAL=1' $PCP_SYSCONFIG_DIR/pmcd >/dev/null then _haveremote - SAVE_PCPQA_SYSTEMD=$PCPQA_SYSTEMD - unset PCPQA_SYSTEMD _service pmcd restart _wait_for_pmcd - export PCPQA_SYSTEMD=$SAVE_PCPQA_SYSTEMD x=`pminfo -h $QA_HOST -v pmcd.control.timeout 2>&1` [ -z "$x" ] && touch $tmp.ok fi diff -Nru pcp-5.3.1/qa/common.avahi pcp-5.3.2/qa/common.avahi --- pcp-5.3.1/qa/common.avahi 2020-04-24 00:15:07.000000000 +0000 +++ pcp-5.3.2/qa/common.avahi 2021-07-30 04:05:06.000000000 +0000 @@ -76,14 +76,15 @@ hostname=`hostname | sed -e 's/\..*//'` echo "hostname=$hostname" >>$here/$seq.full echo "avahi-browse -rt -d local _$service._tcp" >> $here/$seq.full - avahi-browse -rt -d local "_$service._tcp" > $tmp.out + avahi-browse -rt -d local "_$service._tcp" > $tmp.out 2> $tmp.err # sometimes we need a fair bit of time for avahi to register for i in 0.1 0.3 1 2 3 do [ -s $tmp.out ] && break pmsleep $i - avahi-browse -rt -d local "_$service._tcp" > $tmp.out + avahi-browse -rt -d local "_$service._tcp" > $tmp.out 2> $tmp.err done + cat $tmp.err >>$here/$seq.full cat $tmp.out | \ tee -a $here/$seq.full | \ sed -n \ diff -Nru pcp-5.3.1/qa/common.bpftrace pcp-5.3.2/qa/common.bpftrace --- pcp-5.3.1/qa/common.bpftrace 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/qa/common.bpftrace 2021-07-30 04:05:06.000000000 +0000 @@ -86,7 +86,7 @@ wait_iter=`expr $wait_sec \* 2` for i in `seq 1 $wait_iter` do - if pminfo -f $1 2>/dev/null | grep -q "value $value_regex"; then + if pminfo -f $1 2>/dev/null | tee -a $here/$seq.full | grep -q "value $value_regex"; then echo "found metric $1 with matching value $value_regex" return fi diff -Nru pcp-5.3.1/qa/common.check pcp-5.3.2/qa/common.check --- pcp-5.3.1/qa/common.check 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/common.check 2021-07-30 04:05:06.000000000 +0000 @@ -144,7 +144,7 @@ _save_config $PCP_SYSTEMDUNIT_DIR/$1.service sed -e 's/Restart=always/Restart=no/' <$PCP_SYSTEMDUNIT_DIR/$1.service >$tmp.tmp $sudo cp $tmp.tmp $PCP_SYSTEMDUNIT_DIR/$1.service - if `which systemctl >/dev/null 2>&1` + if [ "$PCPQA_SYSTEMD" = yes ] then $sudo systemctl daemon-reload else @@ -159,7 +159,7 @@ if [ -n "$PCP_SYSTEMDUNIT_DIR" -a -f $PCP_SYSTEMDUNIT_DIR/$1.service.$seq ] then _restore_config $PCP_SYSTEMDUNIT_DIR/$1.service - if `which systemctl >/dev/null 2>&1` + if [ "$PCPQA_SYSTEMD" = yes ] then $sudo systemctl daemon-reload else @@ -192,7 +192,7 @@ # don't ever use systemctl $_verbose && echo "_service: no systemctl, PCPQA_SYSTEMD=$PCPQA_SYSTEMD" else - which systemctl >/dev/null 2>&1 && _do_systemctl=true + [ "$PCPQA_SYSTEMD" = yes ] && _do_systemctl=true if $_do_systemctl then case "$1" @@ -231,12 +231,24 @@ # not a systemd service but a wrapper for the pmcd and pmlogger # services, so a little different ... # + + # if service is failed, need reset-failed before trying + # anything else + # + for svc in pmlogger pmcd + do + if $sudo systemctl show --property=ActiveState $svc.service 2>&1 \ + | grep '=failed$' >/dev/null + then + $_verbose && echo "_service: using systemctl: reset-failed $svc" + $sudo systemctl reset-failed $svc.service 2>>$here/$seq.full + fi + done + if [ "$2" = start -o "$2" = restart ] then $_verbose && echo "_service: using systemctl $2 $pmcd.service then pmlogger.service" - $sudo systemctl reset-failed pmcd.service 2>>$here/$seq.full $sudo systemctl $2 pmcd.service - $sudo systemctl reset-failed pmlogger.service 2>>$here/$seq.full $sudo systemctl $2 pmlogger.service else $_verbose && echo "_service: using systemctl $2 pmlogger.service then pmcd.service" @@ -244,30 +256,55 @@ $sudo systemctl $2 pmcd.service if [ "$2" = stop ] then - # stop pmlogger_check ... it gets started as a - # by-product of start pmlogger, but is not stopped + # stop pmlogger_check (if active) ... it gets started + # as a by-product of start pmlogger, but is not stopped # by stop pmlogger (there is a long and complicated # good reason for this) + # ditto for pmlogger_daily and pmlogger_daily-poll # - $_verbose && echo "_service: also stop pmlogger_check" - $sudo systemctl stop pmlogger_check.timer pmlogger_check.service + for svc in pmlogger_check pmlogger_daily pmlogger_daily-poll + do + if $sudo systemctl show --property=ActiveState $svc.timer 2>&1 \ + | grep '=active$' >/dev/null + then + $_verbose && echo "_service: also stop $svc" + $sudo systemctl stop $svc.timer $svc.service + fi + done fi fi + _systemctl_status pmcd >>$here/$seq.full + _systemctl_status pmlogger >>$here/$seq.full ;; *) - $_verbose && echo "_service: using systemctl $2 $1.service" - if [ "$2" = start -o "$2" = restart ] + # if service is failed, need reset-failed before trying + # anything else + # + if $sudo systemctl show --property=ActiveState $1.service 2>&1 \ + | grep '=failed$' >/dev/null then + $_verbose && echo "_service: using systemctl: reset-failed $1" $sudo systemctl reset-failed $1.service 2>>$here/$seq.full fi + + $_verbose && echo "_service: using systemctl $2 $1.service" $sudo systemctl $2 $1.service if [ "$1" = pmlogger -a "$2" = stop ] then - # stop pmlogger_check ... see note above + # ensure pmlogger_check, pmlogger_daily and + # pmlogger_daily-poll are stopped ... see note above # - $_verbose && echo "_service: also stop pmlogger_check" - $sudo systemctl stop pmlogger_check.timer pmlogger_check.service + for svc in pmlogger_check pmlogger_daily pmlogger_daily-poll + do + if $sudo systemctl show --property=ActiveState $svc.timer 2>&1 \ + | grep '=active$' >/dev/null + then + $_verbose && echo "_service: also stop $svc.timer and $scv.service" + $sudo systemctl stop $svc.timer $svc.service + fi + done fi + _systemctl_status $1 >>$here/$seq.full ;; esac elif [ -f $PCP_RC_DIR/$1 ] @@ -572,6 +609,23 @@ esac } +# if systemctl is in play, see if there is any additional info +# from systemctl for the $1 service +# +_systemctl_status() +{ + if [ $# -ne 1 ] + then + echo "_systemctl_status: botch: usage #args=$# not 1 as expected" + return + fi + + if [ "$PCPQA_SYSTEMD" = yes ] + then + $sudo systemctl status "$1.service" + fi +} + # wait_for_pmcd [maxdelay [host]] # _wait_for_pmcd() @@ -629,14 +683,15 @@ cat $PCP_LOG_DIR/pmcd/pmcd.log echo "likely looking processes ..." - ps "$PCP_PS_ALL_FLAGS" | egrep "[p]m|[P]ID" + $PCP_PS_PROG "$PCP_PS_ALL_FLAGS" | egrep "[p]m|[P]ID" ;; *) # assume a remote PMCD # - ssh pcpqa@$_host "sh -c '. \$PCP_DIR/etc/pcp.env; echo; echo "=== pmcd.log ==="; [ -f \$PCP_LOG_DIR/pmcd/pmcd.log ] && cat \$PCP_LOG_DIR/pmcd/pmcd.log; [ -f \$PCP_LOG_DIR/pmcd.log ] && cat \$PCP_LOG_DIR/pmcd.log; echo; echo likely looking processes ...; ( ps \$PCP_PS_ALL_FLAGS | egrep \"[p]m|[P]ID\" )'" >$tmp._wait_for_pmlogger.pmlc + $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep "([p]mlogger|[P]ID)" >>$tmp._wait_for_pmlogger.pmlc echo "pmlc $_pid" >>$tmp._wait_for_pmlogger.pmlc # May need sudo -u pcp here in case we're doing credentials checks # in pmlogger and this is the primary pmlogger (started by user @@ -830,7 +886,8 @@ done echo echo "Likely looking processes ..." - ps $PCP_PS_ALL_FLAGS | egrep '([p]m)|([P]ID)' + $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '([p]m)|([P]ID)' + _systemctl_status pmlogger status=0 exit $status fi @@ -884,6 +941,7 @@ if [ "$_i" -ge 100 ] then echo "_wait_pmlogger_end: failed to see $PCP_TMP_DIR/pmlogger/$_pid removed after 100 iterations" + _systemctl_status pmlogger #debug# set +x return fi @@ -922,6 +980,7 @@ else echo "_wait_pmlogger_end: failed to see pid $_pid exit after 100 iterations" fi + _systemctl_status pmlogger #debug# set +x return fi @@ -971,6 +1030,7 @@ if [ "$_i" -ge 100 ] then echo "_wait_pmcd_end: failed to see pid $_pid exit after 100 iterations" + _systemctl_status pmcd #debug# set +x return fi @@ -999,6 +1059,7 @@ if [ "$_i" -ge 100 ] then echo "_wait_for_pmie: failed to see pmie start after 100 iterations" + _systemctl_status pmie #debug# set +x return fi @@ -1056,6 +1117,7 @@ then echo "_wait_pmie_end: failed to see pid(s) $_pidlist exit after 100 iterations" $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep '[P]ID|[p]mie' + _systemctl_status pmie #debug# set +x break fi @@ -1113,6 +1175,7 @@ else echo "pmproxy logfile ($_logfile) not created" fi + _systemctl_status pmproxy status=0 exit $status fi @@ -1120,6 +1183,70 @@ done } +# Wait for pmproxy server metrics. This should always be called after +# _wait_for_pmproxy. Note: some platforms might not have pmproxy metrics. +# +_wait_for_pmproxy_metrics() +{ + _n=0 + while true; do + pminfo -f pmproxy.pid pmproxy.cpu pmproxy.webgroup.instmap.size >/dev/null 2>&1 && return 0 + sleep 0.25 + _n=$expr $_n + 1 + [ $_n -lt 20 ] && continue + done + echo _wait_for_pmproxy_metrics failed after 20 iterations + return 1 +} + +# Wait for pmproxy to end +# +_wait_pmproxy_end() +{ + #debug# set -x + + _pid=`cat $PCP_RUN_DIR/pmroxy.pid 2>/dev/null` + if [ -z "$_pid" ] + then + # no $PCP_RUN_DIR/proxy.pid file, try ps(1) the hard way + # + _pid=`$PCP_PS_PROG $PCP_PS_ALL_FLAGS \ + | sed -n -e '/\[p]mproxy /{ +s/^[^ ]*// +s/^[ ]*// +s/[ ].*// +p +}'` + fi + if [ -z "$_pid" ] + then + #debug# set +x + return + fi + + _i=0 + while true + do + if sudo kill -s 0 $_pid 2>/dev/null + then + # process still exists + _i=`expr $_i + 1` + if [ "$_i" -ge 100 ] + then + echo "_wait_proxy_end: failed to see pid $_pid exit after 100 iterations" + _systemctl_status proxy + #debug# set +x + return + fi + pmsleep 0.1 + else + # process has really exited + #debug# set +x + return + fi + done +} + # ensure primary logger allows pmlc state changes # _writable_primary_logger() @@ -1279,6 +1406,26 @@ [ $? -eq 0 ] || _notrun "No purify binary found" } +# check that test is not running on a 32 bit environment +_check_64bit_platform() +{ + _message="$@" + [ -z "$_message" ] && _message="Test requires 64-bit platform" + # + # use src/sizeof not hinv.machine (or uname -m) to avoid confusion + # when the environment is a 32-bit container running on a 64-bit + # host, like test-ubuntu1804i386-container in CI + # + eval `$here/src/sizeof ptr` + echo "ptr=$ptr" >>$here/seq.full + case "$ptr" + in + 4) + _notrun "$_message" + ;; + esac +} + # # check we have pmseries, redis-cli and redis-server installed. # Note: use _check_redis_server to test if redis is running locally. @@ -2125,7 +2272,7 @@ [ "$1" = "verbose" ] && pat="" _have_systemctl=false - which systemctl >/dev/null 2>&1 && _have_systemctl=true + [ "$PCPQA_SYSTEMD" = yes ] && _have_systemctl=true if [ -z "$pat" ] then _have_service=true @@ -2310,7 +2457,7 @@ esac _have_systemctl=false - which systemctl >/dev/null 2>&1 && _have_systemctl=true + [ "$PCPQA_SYSTEMD" = yes ] && _have_systemctl=true if [ -z "$pat" ] then _have_service=true diff -Nru pcp-5.3.1/qa/common.filter pcp-5.3.2/qa/common.filter --- pcp-5.3.1/qa/common.filter 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/common.filter 2021-07-30 04:05:06.000000000 +0000 @@ -260,6 +260,7 @@ -e '/pmdabrocade/d' \ -e '/pmdacisco/d' \ -e '/pmdadbping/d' \ + -e '/pmdadenki/d' \ -e '/pmdadm/d' \ -e '/pmdadmf/d' \ -e '/pmdadocker/d' \ @@ -269,6 +270,7 @@ -e '/pmdaespping/d' \ -e '/pmdagfs2/d' \ -e '/pmdagluster/d' \ + -e '/pmdahacluster/d' \ -e '/pmdahippi/d' \ -e '/pmdahotproc/d' \ -e '/pmdaib/d' \ @@ -326,6 +328,7 @@ -e '/pmda_simple/d' \ -e '/pmdasimple/d' \ -e '/pmdasmart/d' \ + -e '/pmdasockets/d' \ -e '/pmdasnia/d' \ -e '/pmdasnmp/d' \ -e '/pmdasmart/d' \ @@ -834,7 +837,19 @@ # proc metric /"$/ && line_num > 0 { line[line_num++] = $0 - print_line() + # count quotes (") ... need to end on an even number ... + # this could easily be defeated by backslash quoting or + # even nested quoting, but these are unlikely in proc + # metric values, even for psinfo.environ or psinfo.psargs + # + nq = 0 + for (x = 0; x < line_num; x++) { + nq += gsub(/"/, "\"", line[x]) + } + if ((nq % 2) == 0) { + # balanced quotes we are done accumulating + print_line() + } next } ( (/proc\./ && /numval/ && /valfmt/) || /^proc\./ ) \ @@ -876,6 +891,7 @@ -e '/^ cihb /d' \ -e '/^ cms /d' \ -e '/^ cxfs /d' \ + -e '/^ denki /d' \ -e '/^ ds389 /d' \ -e '/^ dynamic /d' \ -e '/^ engr /d' \ Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/denki/bigsystem.tgz and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/denki/bigsystem.tgz differ diff -Nru pcp-5.3.1/qa/denki/GNUmakefile pcp-5.3.2/qa/denki/GNUmakefile --- pcp-5.3.1/qa/denki/GNUmakefile 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/denki/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,15 @@ +TOPDIR = ../.. +include $(TOPDIR)/src/include/builddefs + +TESTDIR = $(PCP_VAR_DIR)/testsuite/denki +ROOTFILES = bigsystem.tgz Thinkpad_L480_bat_busy.tgz + +default setup default_pcp: + +install install_pcp: + $(INSTALL) -m 755 -d $(TESTDIR) + $(INSTALL) -m 644 -f $(ROOTFILES) $(TESTDIR) + $(INSTALL) -m 644 -f GNUmakefile.install $(TESTDIR)/GNUmakefile + +include $(BUILDRULES) + diff -Nru pcp-5.3.1/qa/denki/GNUmakefile.install pcp-5.3.2/qa/denki/GNUmakefile.install --- pcp-5.3.1/qa/denki/GNUmakefile.install 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/denki/GNUmakefile.install 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1 @@ +default setup install clean check: Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/qa/denki/Thinkpad_L480_bat_busy.tgz and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/qa/denki/Thinkpad_L480_bat_busy.tgz differ diff -Nru pcp-5.3.1/qa/GNUmakefile pcp-5.3.2/qa/GNUmakefile --- pcp-5.3.1/qa/GNUmakefile 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -19,7 +19,7 @@ SUBDIRS = src pmdas cisco gluster pconf sadist collectl nfsclient named \ archives badarchives views qt linux unbound cifs gpfs lustre ganglia \ java mmv postfix perl json slurm tmparch sheet smart admin hacluster \ - sockets + sockets denki ifeq "$(PMDA_PERFEVENT)" "true" SUBDIRS += perfevent diff -Nru pcp-5.3.1/qa/GNUmakefile.install pcp-5.3.2/qa/GNUmakefile.install --- pcp-5.3.1/qa/GNUmakefile.install 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/GNUmakefile.install 2021-07-30 04:05:06.000000000 +0000 @@ -16,7 +16,7 @@ SUBDIRS = src pmdas cisco gluster pconf sadist collectl nfsclient named \ archives badarchives views qt linux unbound cifs gpfs lustre ganglia \ - java mmv postfix perl json slurm tmparch sheet smart hacluster + java mmv postfix perl json slurm tmparch sheet smart hacluster denki ifeq "$(PMDA_PERFEVENT)" "true" SUBDIRS += perfevent endif diff -Nru pcp-5.3.1/qa/group pcp-5.3.2/qa/group --- pcp-5.3.1/qa/group 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/group 2021-07-30 04:05:06.000000000 +0000 @@ -202,6 +202,7 @@ pmda.cifs pmda.cisco pmda.dm +pmda.denki pmda.docker pmda.ds389 pmda.elasticsearch @@ -596,7 +597,7 @@ 152 pmda.pmcd pmval local 153 folio local sanity 154 pmda.cisco help local sanity -155 pmcd pmstore pmda.sample local sanity +155 pmcd pmstore pmda.sample local sanity help 156 pmda.sample pmda.proc local pmcd_wait pmda.install 157 pmlogger local 158 pmval pmie local kernel @@ -654,7 +655,7 @@ 210 pmns local pmval pmie sanity pmdumplog 211 pmns local pmval pmie pmdumplog 212:retired pmda pmda.cisco local -213 dbpmda pmns local pmda.sample pmda.mmv sanity +213 dbpmda pmns local pmda.sample pmda.mmv sanity help 214 pmlogextract local pmdumplog timezone 215 other pmsocks pmval remote pmdumplog 216 pmda.linux local @@ -783,7 +784,7 @@ 339 pmie local kernel 340 pmcd remote pmstore 341 pmda local -342 other remote +342 other remote dbpmda 343 pmlogreduce local pmdumplog 344 context_local local pmval pmprobe 345 pmns derive local sanity @@ -950,7 +951,7 @@ 506 pmlogrewrite local slow 507 pcp local kernel 508 archive pmlogreduce local pmval kernel -509 derive pmns local pmda.sample +509 derive pmns local pmda.sample dbpmda 510 pmlogger pmlc local 511 pmimport pmdumplog pmlogsummary perl local 512 threads pminfo pmlogger pmlogextract pmdumplog dbpmda local fault @@ -1087,8 +1088,8 @@ 643 pmda.trivial pmns local 644 pmns local 645 pmlogger local kernel -646 pmda.mmv local sanity -647 pmda.mmv local +646 pmda.mmv local sanity help +647 pmda.mmv local help 648 pmda.mmv local 649 pmda.mmv local 650 pmlogger local pmdumplog @@ -1195,7 +1196,7 @@ 751:retired pmda.rpm local pmdumplog pmlogrewrite 752 libpcp local pmval timezone 753 derive local pmval pmstore kernel -754 pmda.unbound local python +754 pmda.unbound local python dbpmda 755 pmda.apache pmda.install local 756 pmda.perfevent local 757 pmda.perfevent pmda.install local @@ -1220,12 +1221,12 @@ 776 pmfind local 777 derive pmprobe pmie local pmval 778 pmda.postgresql pmie local -779 pmda local +779 pmda local dbpmda 780 pmproxy local 781 logutil local 782:retired pmwebd local 783:retired pmda.rpm local valgrind -784 pmda.mic python local +784 pmda.mic python local dbpmda 785 pcp atop local 786 context context_local libpcp local 787 archive local pmie pmlogrewrite pmdumplog pmval flakey kernel @@ -1241,7 +1242,7 @@ 797 pmlogrewrite local pmdumplog 798 pmda.nfsclient local python dbpmda 799 pmlogrewrite local -800 pmda.proc pmda.hotproc local +800 pmda.proc pmda.hotproc local dbpmda 801 pmda.netfilter local 802 pmda valgrind dbpmda local 803 libpcp derive local kernel @@ -1396,7 +1397,7 @@ 952 threads valgrind local helgrind 953 libpcp threads local 954 libpcp threads derive local -955:retired pmda.linux local kernel +955:retired pmda.linux local kernel dbpmda 956 pmcd local 957 pmda.linux local valgrind 958 archive local pmdumplog @@ -1472,9 +1473,9 @@ 1028 pmdumptext local kernel x11 1029 libpcp_qmc local pmstore x11 1030 pmda.linux local -1031 pmda.slurm perl local +1031 pmda.slurm perl local dbpmda 1032 pmproxy containers local python -1033 pmda.named local +1033 pmda.named local dbpmda 1034 pmda.named local 1035 pmda.oracle local pmstore 1036 pmclient archive multi-archive local pmlogextract python @@ -1493,7 +1494,7 @@ 1049 pmie pmieconf local 1050 pmieconf local 1051 pmieconf #696008 local -1052 pmda.json local python +1052 pmda.json local python dbpmda 1053 pmda.json pmda.install local python 1054 pmlogger pmcpp local pmdumplog kernel 1055 pmlogger local pmdumplog pmstore folio @@ -1593,7 +1594,7 @@ 1149 pmlogrewrite local 1150 pmda.bcc local python 1151 pmda.bcc local python -1152 pmda.bcc local python +1152:retired pmda.bcc local python 1153 pmda.bcc local python 1154 pmda.bcc local python 1155 pmda.bcc local python @@ -1696,7 +1697,7 @@ 1252 derive local 1253 derive local valgrind 1254 derive local -1255 libpcp local kernel +1255 libpcp local kernel dbpmda 1256 derive valgrind local 1257 libpcp python local 1258 pmda.linux local valgrind @@ -1769,8 +1770,12 @@ 1325 pmdumplog local 1326 pmstore pmda.pmcd local 1327 pmdumplog local valgrind +1328 pmda.pmcd local +1329 pminfo pmda.mmv libpcp local help 1330 pmda.openmetrics local python 1331 verify local +1332 archive pmdumplog local +1333 archive pmdumplog local valgrind 1337 pmda.mssql local 1338 pmlogrewrite labels pmdumplog local 1340 pmcd pmda.pmcd pmstore local @@ -1786,10 +1791,10 @@ 1358 pmda.podman local 1359 libpcp local pmdbg 1362 pmda.postgresql local -1367 labels pmda.simple local python +1367 labels pmda.simple local python dbpmda 1368 labels help pmlogger pmdumplog local sanity 1369 labels pmcd pmlogger pmdumplog local -1370:reserved man local +1370 man local 1372 pmie local 1379 pmproxy local 1383 pmlogrewrite labels pmdumplog local @@ -1818,7 +1823,7 @@ 1436 pmda.postgresql local 1437 pmda.kvm local 1455 pmlogrewrite labels pmdumplog local -1457 pmproxy local +1457 pmproxy libpcp_web threads secure local 1480 pmda.lmsensors local 1489 python pmrep pmimport local 1490 python local labels @@ -1849,8 +1854,13 @@ 1613 pmda.linux kernel local 1622 selinux local 1623 libpcp_import collectl local +1626 pmproxy libpcp_web local +1627 libpcp_import local +1628 libpcp_import valgrind local +1633 python pmda.sockets local 1634 pmda.sockets local 1644 pmda.perfevent local +1653 pmda.denki local 1660 libpcp labels local 1661 pmproxy libpcp_web pmlogger local 1671 multi-archive archive libpcp pmrep local python @@ -1891,6 +1901,7 @@ 1723 pmda.bpftrace local python 1724 pmda.bpftrace local python 1725 pmda.bpftrace local python +1727:reserved pmproxy libpcp_web local 1740 pmda.proc local 1745 pmlogger libpcp pmval local 1748 atop local @@ -1899,6 +1910,7 @@ 1768 pmfind local 1769 pmda.linux local 1773 pmseries pmproxy libpcp_web local +1774:reserved pmproxy libpcp_web local 1775 pmdumptext archive local 1793 pmrep pcp2xxx python local 1801 dstat python pcp local @@ -1919,6 +1931,7 @@ 1874 pmseries pmproxy local 1876 pmcd secure local 1886 pmseries libpcp_web local +1893 pmda.proc local 1896 pmlogger logutil pmlc local 1897 pmda.hacluster local valgrind 1899 fetch local diff -Nru pcp-5.3.1/qa/new pcp-5.3.2/qa/new --- pcp-5.3.1/qa/new 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/qa/new 2021-07-30 04:05:06.000000000 +0000 @@ -12,7 +12,9 @@ # generic initialization . ./common.rc -min=1600 +# use ./new-seqs to help refine min and max +# +min=1300 max=1999 max_probes=200 diff -Nru pcp-5.3.1/qa/README.vm pcp-5.3.2/qa/README.vm --- pcp-5.3.1/qa/README.vm 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/README.vm 2021-07-30 04:05:06.000000000 +0000 @@ -87,6 +87,17 @@ $ sudo dnf system-upgrade reboot # and then watch the console window ... + # recipe below works (at least) for Fedora 34 + # setting up a static IP addr using nmcli (assume interface enp1s0) + $ sudo connection modify IPv4.address 192.168.178.226/24 + ^^^ 200 + vm ordinal, e.g vm26 here + $ sudo nmcli connection modify enp1s0 IPv4.gateway 192.168.178.1 + $ sudo nmcli connection modify enp1s0 IPv4.dns 192.168.178.100 + $ sudo nmcli connection modify enp1s0 IPv4.dns-search localdomain + $ sudo nmcli connection modify enp1s0 IPv4.method manual + $ sudo nmcli connection down enp1s0 + $ sudo nmcli connection up enp1s0 + RedHat https://access.redhat.com/articles/3078 17 Nov 2015: 5.0-5.11, 6.0-6.7, 7.0-7.1 @@ -439,15 +450,18 @@ https://rbgeek.wordpress.com/2013/01/27/how-to-extend-the-root-partition-in-lvm/ Assume device-mapper vgname fedora-server Assume partiton to add is partiton 1 of /dev/vdb - $ sudo cfdisk /dev/vdb <- make 1 partition, all of the disk - $ sudo pvcreate /dev/vdb1 <- initialize partition for use with LVM + $ disk=/dev/vdb + $ sudo cfdisk $disk <- make 1 partition, all of the disk + $ sudo pvcreate ${disk}1 <- initialize partition for use with LVM $ sudo vgdisplay <- get volume group name - $ sudo vgextend /dev/fedora-server /dev/vdb1 <- extend the volume group - $ sudo lvextend -l +100%FREE /dev/fedora-server/root <- extend LVM + $ vg= <- from above will be "fedora-server" or + "centos" or similar + $ sudo vgextend /dev/$vg ${disk}1 <- extend the volume group + $ sudo lvextend -l +100%FREE /dev/$vg/root <- extend LVM # for ext2 - $ sudo resize2fs /dev/fedora-server/root <- extend filesystem + $ sudo resize2fs /dev/$vg/root <- extend filesystem # for xfs - $ sudo xfs_growfs / + $ sudo xfs_growfs / <- extend filesytem Just remember that if you're using XFS, you need xfs_growfs instead of resize2fs. diff -Nru pcp-5.3.1/qa/show-me pcp-5.3.2/qa/show-me --- pcp-5.3.1/qa/show-me 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/qa/show-me 2021-07-30 04:05:06.000000000 +0000 @@ -14,19 +14,24 @@ QA_USER= QA_DIR= -if which gdiff >/dev/null 2>&1 +if [ -n "$PCPQA_DIFF" ] then - DIFF=gdiff + DIFF="$PCPQA_DIFF" else - if which meld >/dev/null 2>&1 + if which gdiff >/dev/null 2>&1 then - DIFF=meld + DIFF=gdiff else - if which xxdiff >/dev/null 2>&1 + if which meld >/dev/null 2>&1 then - DIFF=xxdiff + DIFF=meld else - DIFF="diff -c" + if which xxdiff >/dev/null 2>&1 + then + DIFF=xxdiff + else + DIFF="diff -c" + fi fi fi fi diff -Nru pcp-5.3.1/qa/sockets/ss_noemitauOH.txt pcp-5.3.2/qa/sockets/ss_noemitauOH.txt --- pcp-5.3.1/qa/sockets/ss_noemitauOH.txt 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/qa/sockets/ss_noemitauOH.txt 2021-07-30 04:05:06.000000000 +0000 @@ -1,3 +1,4 @@ +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process udp ESTAB 0 0 10.0.0.10:49693 74.125.68.189:443 uid:1024 ino:28605309 sk:976e cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem:(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) udp UNCONN 0 0 192.168.1.169:58624 0.0.0.0:* uid:1024 ino:19693830 sk:3154 cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem:(r0,rb212992,t0,tb212992,f4096,w0,o0,bl0,d0) udp ESTAB 0 0 10.0.0.10:42866 142.250.70.142:443 uid:1024 ino:28615973 sk:976f cgroup:/user.slice/user-1024.slice/session-2.scope <-> skmem:(r0,rb425984,t0,tb58080,f4096,w0,o0,bl0,d0) diff -Nru pcp-5.3.1/qa/sockets/ss_noemitauOH_ubuntu.txt pcp-5.3.2/qa/sockets/ss_noemitauOH_ubuntu.txt --- pcp-5.3.1/qa/sockets/ss_noemitauOH_ubuntu.txt 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/qa/sockets/ss_noemitauOH_ubuntu.txt 2021-07-30 04:05:06.000000000 +0000 @@ -1,3 +1,4 @@ +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process udp UNCONN 0 0 0.0.0.0:5353 0.0.0.0:* uid:117 ino:177686 sk:9 <-> skmem:(r0,rb212992,t0,tb212992,f4096,w0,o144,bl0,d0) udp UNCONN 0 0 0.0.0.0:38162 0.0.0.0:* uid:117 ino:177688 sk:a <-> skmem:(r0,rb212992,t0,tb212992,f0,w0,o0,bl0,d0) udp UNCONN 0 0 192.168.123.1:53 0.0.0.0:* ino:187421 sk:b <-> skmem:(r0,rb212992,t0,tb212992,f0,w0,o0,bl0,d0) diff -Nru pcp-5.3.1/qa/src/check_pmi_errconv.c pcp-5.3.2/qa/src/check_pmi_errconv.c --- pcp-5.3.1/qa/src/check_pmi_errconv.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/src/check_pmi_errconv.c 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * check error handling with pmiWrite after PM_ERR_CONV. + * + * Copyright (c) 2021 Red Hat. All Rights Reserved. + */ + +#include +#include + +int +main(int argc, char **argv) +{ + pmInDom indom = pmInDom_build(245, 0); + pmID pmid = pmID_build(245, 0, 0); + int sts; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(2); + } + + if ((sts = pmiStart(argv[1], 0)) < 0) { + fprintf(stderr, "pmiStart: %s - %s\n", argv[1], pmiErrStr(sts)); + exit(1); + } + if ((sts = pmiSetTimezone("UTC")) < 0) { + fprintf(stderr, "pmiSetTimezone(UTC): %s\n", pmiErrStr(sts)); + exit(1); + } + + if ((sts = pmiAddMetric("my.metric.int", pmid, PM_TYPE_32, + indom, PM_SEM_INSTANT, pmiUnits(0,0,0,0,0,0))) < 0) { + fprintf(stderr, "pmiAddMetric: %s\n", pmiErrStr(sts)); + exit(1); + } + if ((sts = pmiAddInstance(indom, "0", 0)) < 0) { + fprintf(stderr, "pmiAddInstance(0): %s\n", pmiErrStr(sts)); + exit(1); + } + if ((sts = pmiAddInstance(indom, "1", 1)) < 0) { + fprintf(stderr, "pmiAddInstance(1): %s\n", pmiErrStr(sts)); + exit(1); + } + + /* FALLTHROUGH on all error paths now to exercise the problem */ + + if ((sts = pmiPutValue("my.metric.int", "0", "1234.5678")) < 0) + fprintf(stderr, "pmiPutValue: inst 0: %s\n", pmiErrStr(sts)); + + if ((sts = pmiPutValue("my.metric.int", "1", "123.45678")) < 0) + fprintf(stderr, "pmiPutValue: inst 1: %s\n", pmiErrStr(sts)); + + /* TZ=UTC date --date='@1547483647' */ + if ((sts = pmiWrite(1547483647, 0)) < 0) + fprintf(stderr, "pmiWrite: %s\n", pmiErrStr(sts)); + + if ((sts = pmiEnd()) < 0) + fprintf(stderr, "pmiEnd: %s\n", pmiErrStr(sts)); + + return 0; +} diff -Nru pcp-5.3.1/qa/src/.gitignore pcp-5.3.2/qa/src/.gitignore --- pcp-5.3.1/qa/src/.gitignore 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/src/.gitignore 2021-07-30 04:05:06.000000000 +0000 @@ -26,6 +26,7 @@ check_import_name check_import.pl check_pmiend_fdleak +check_pmi_errconv checkstructs chkacc1 chkacc2 @@ -118,6 +119,7 @@ mergelabelsets mkfiles mmv_genstats +mmv_help mmv_instances mmv_noinit mmv_nostats @@ -212,6 +214,7 @@ scanmeta semstr sha1int2ext +sizeof slow_af sortinst spawn diff -Nru pcp-5.3.1/qa/src/GNUlocaldefs pcp-5.3.2/qa/src/GNUlocaldefs --- pcp-5.3.1/qa/src/GNUlocaldefs 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/src/GNUlocaldefs 2021-07-30 04:05:06.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012-2020 Red Hat. +# Copyright (c) 2012-2021 Red Hat. # Copyright (c) 2009 Aconex. All Rights Reserved. # Copyright (c) 1997-2002 Silicon Graphics, Inc. All Rights Reserved. # @@ -42,15 +42,15 @@ username.c rtimetest.c getcontexthost.c badpmda.c chkputlogresult.c \ churnctx.c badUnitsStr_r.c units-parse.c rootclient.c derived.c \ lookupnametest.c getversion.c pdubufbounds.c statvfs.c storepmcd.c \ - github-50.c archfetch.c sortinst.c fetchgroup.c \ + github-50.c archfetch.c sortinst.c fetchgroup.c loadconfig2.c \ loadderived.c sum16.c badmmv.c multictx.c mmv_simple.c \ - httpfetch.c json_test.c check_pmiend_fdleak.c loadconfig2.c \ + httpfetch.c json_test.c check_pmiend_fdleak.c check_pmi_errconv.c \ archctl_segfault.c debug.c int2pmid.c int2indom.c exectest.c \ unpickargs.c hanoi.c progname.c countmark.c \ indom2int.c pmid2int.c scanmeta.c traverse_return_codes.c \ timeshift.c checkstructs.c bcc_profile.c sha1int2ext.c \ getdomainname.c profilecrash.c store_and_fetch.c test_service_notify.c \ - ctx_derive.c pmstrn.c pmfstring.c pmfg-derived.c + ctx_derive.c pmstrn.c pmfstring.c pmfg-derived.c mmv_help.c sizeof.c ifeq ($(shell test -f ../localconfig && echo 1), 1) include ../localconfig @@ -307,6 +307,9 @@ bcc_profile: bcc_profile.c $(CCF) $(CDEFS) -g -fno-omit-frame-pointer -o $@ bcc_profile.c +sizeof: sizeof.c + $(CCF) $(CDEFS) -o $@ $< + # --- need libpcp # @@ -537,6 +540,10 @@ rm -f $@ $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) -lpcp_import +check_pmi_errconv: check_pmi_errconv.c + rm -f $@ + $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) -lpcp_import + # --- need libpcp_web # diff -Nru pcp-5.3.1/qa/src/mmv2_genstats.c pcp-5.3.2/qa/src/mmv2_genstats.c --- pcp-5.3.1/qa/src/mmv2_genstats.c 2016-09-08 05:04:49.000000000 +0000 +++ pcp-5.3.2/qa/src/mmv2_genstats.c 2021-07-30 04:05:06.000000000 +0000 @@ -39,7 +39,7 @@ .semantics = MMV_SEM_COUNTER, .dimension = MMV_UNITS(0,0,1,0,0,PM_COUNT_ONE), .shorttext = "test counter metric", - .helptext = "Yes, this is a test counter metric", + .helptext = "Yes\n" "This is a test counter metric", }, { .name = "discrete", .item = 2, @@ -47,7 +47,7 @@ .semantics = MMV_SEM_DISCRETE, .dimension = MMV_UNITS(0,0,0,0,0,0), .shorttext = "test discrete metric", - .helptext = "Yes, this is a test discrete metric", + .helptext = "Yes\n" "This is a test discrete metric", }, { .name = "indom", .item = 3, @@ -79,7 +79,7 @@ .dimension = MMV_UNITS(0,0,0,0,0,0), .indom = 1, .shorttext = "test string metrics", - .helptext = "Yes, this is a test string metric with instances", + .helptext = "Yes\n" "This is a test string metric with instances", }, }; diff -Nru pcp-5.3.1/qa/src/mmv3_genstats.c pcp-5.3.2/qa/src/mmv3_genstats.c --- pcp-5.3.1/qa/src/mmv3_genstats.c 2018-12-21 00:50:34.000000000 +0000 +++ pcp-5.3.2/qa/src/mmv3_genstats.c 2021-07-30 04:05:06.000000000 +0000 @@ -37,7 +37,7 @@ .semantics = MMV_SEM_COUNTER, .dimension = MMV_UNITS(0,0,1,0,0,PM_COUNT_ONE), .shorttext = "test counter metric", - .helptext = "Yes, this is a test counter metric", + .helptext = "Yes!\n" "This is a test counter metric", }, { .name = "discrete", .item = 2, @@ -45,7 +45,7 @@ .semantics = MMV_SEM_DISCRETE, .dimension = MMV_UNITS(0,0,0,0,0,0), .shorttext = "test discrete metric", - .helptext = "Yes, this is a test discrete metric", + .helptext = "Yes!\n" "This is a test discrete metric", }, { .name = "indom", .item = 3, @@ -77,7 +77,7 @@ .dimension = MMV_UNITS(0,0,0,0,0,0), .indom = 1, .shorttext = "test string metrics", - .helptext = "Yes, this is a test string metric with instances", + .helptext = "Yes!\n" "This is a test string metric with instances", }, }; diff -Nru pcp-5.3.1/qa/src/mmv_genstats.c pcp-5.3.2/qa/src/mmv_genstats.c --- pcp-5.3.1/qa/src/mmv_genstats.c 2015-08-06 05:46:37.000000000 +0000 +++ pcp-5.3.2/qa/src/mmv_genstats.c 2021-07-30 04:05:06.000000000 +0000 @@ -38,7 +38,7 @@ .semantics = MMV_SEM_COUNTER, .dimension = MMV_UNITS(0,0,1,0,0,PM_COUNT_ONE), .shorttext = "test counter metric", - .helptext = "Yes, this is a test counter metric", + .helptext = "Yes\n" "This is a test counter metric", }, { .name = "discrete", .item = 2, @@ -46,7 +46,7 @@ .semantics = MMV_SEM_DISCRETE, .dimension = MMV_UNITS(0,0,0,0,0,0), .shorttext = "test discrete metric", - .helptext = "Yes, this is a test discrete metric", + .helptext = "Yes\n" "This is a test discrete metric", }, { .name = "indom", .item = 3, @@ -78,7 +78,7 @@ .dimension = MMV_UNITS(0,0,0,0,0,0), .indom = 1, .shorttext = "test string metrics", - .helptext = "Yes, this is a test string metric with instances", + .helptext = "Yes\n" "This is a test string metric with instances", }, }; diff -Nru pcp-5.3.1/qa/src/mmv_help.c pcp-5.3.2/qa/src/mmv_help.c --- pcp-5.3.1/qa/src/mmv_help.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/src/mmv_help.c 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,101 @@ +/* + * Setup an mmv PMDA file to exercise various help text code paths. + * Based on mmv3_genstats.c + * + * Copyright (c) 2018 Guillem Lopez Paradis. All Rights Reserved. + * Copyright (c) 2021 Ken McDonell. All Rights Reserved. + */ + +#include +#include + +static mmv_metric2_t metrics[] = { + { .name = "nohelp", + .item = 1, + .type = MMV_TYPE_U32, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = NULL, + .helptext = NULL + }, + { .name = "oneline", + .item = 2, + .type = MMV_TYPE_U32, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "oneline", + .helptext = NULL + }, + { .name = "both", + .item = 3, + .type = MMV_TYPE_U32, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "foo", + .helptext = "bar" + }, + { .name = "verbose", + .item = 4, + .type = MMV_TYPE_U32, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "wordy", + .helptext = "One, two, three, four, five,\n" +"Once I caught a fish alive,\n" +"Six, seven, eight, nine, ten,\n" +"Then I let go again.\n" +"\n" +"Why did you let it go?\n" +"Because it bit my finger so.\n" +"Which finger did it bite?\n" +"This little finger on the right" + }, + { .name = "help_empty", + .item = 5, + .type = MMV_TYPE_U32, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "foobar", + .helptext = "" + }, + { .name = "both_empty", + .item = 6, + .type = MMV_TYPE_U32, + .semantics = MMV_SEM_DISCRETE, + .dimension = MMV_UNITS(0,0,0,0,0,0), + .shorttext = "", + .helptext = "" + }, +}; + +int +main(int ac, char * av[]) +{ + int i; + void *addr; + char * file = (ac > 1) ? av[1] : "mmv_help"; + /* choose cluster to avoid collisions, 322 seems safe */ + mmv_registry_t *registry = mmv_stats_registry(file, 322, 0); + + if (!registry) { + fprintf(stderr, "mmv_stats_registry: %s - %s\n", file, strerror(errno)); + return 1; + } + + for (i = 0; i < sizeof(metrics) / sizeof(metrics[0]); i++) { + mmv_stats_add_metric(registry, + metrics[i].name, metrics[i].item, metrics[i].type, + metrics[i].semantics, metrics[i].dimension, metrics[i].indom, + metrics[i].shorttext, metrics[i].helptext); + } + + addr = mmv_stats_start(registry); + + if (!addr) { + fprintf(stderr, "mmv_stats_start: %s - %s\n", file, strerror(errno)); + return 1; + } + + /* just exit ... the task here is to create the mmv file */ + return 0; +} diff -Nru pcp-5.3.1/qa/src/multithread14.c pcp-5.3.2/qa/src/multithread14.c --- pcp-5.3.1/qa/src/multithread14.c 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/src/multithread14.c 2021-07-30 04:05:06.000000000 +0000 @@ -109,14 +109,14 @@ pthread_exit("botch A.6"); } - write(f, "Answer: ", strlen("Answer: ")); + (void)write(f, "Answer: ", strlen("Answer: ")); lastc = EOF; while (read(fileno(fp), &c, 1) == 1) { - write(f, &c, 1); + (void)write(f, &c, 1); lastc = c; } if (lastc != '\n') - write(f, "\n", 1); + (void)write(f, "\n", 1); if ((sts = __pmProcessPipeClose(fp) < 0)) { fprintf(stderr, "[tid %d] Error: func_A: __pmProcessPipeClose() -> %s\n", iam, pmErrStr_r(sts, strbuf, sizeof(strbuf))); pthread_exit("botch A.7"); @@ -214,14 +214,14 @@ pthread_exit("botch B.7"); } - write(f, "Answer: ", strlen("Answer: ")); + (void)write(f, "Answer: ", strlen("Answer: ")); lastc = EOF; while (read(fd, &c, 1) == 1) { - write(f, &c, 1); + (void)write(f, &c, 1); lastc = c; } if (lastc != '\n') - write(f, "\n", 1); + (void)write(f, "\n", 1); close(fd); if (argp != NULL) { fprintf(stderr, "[tid %d] Error: func_B: argp not NULL after __pmProcessExec()\n", iam); @@ -273,14 +273,14 @@ pthread_exit("botch C.3"); } - write(f, "Answer: ", strlen("Answer: ")); + (void)write(f, "Answer: ", strlen("Answer: ")); lastc = EOF; while ((c = fgetc(fp)) != EOF) { - write(f, (char *)&c, 1); + (void)write(f, (char *)&c, 1); lastc = c; } if (lastc != '\n') - write(f, "\n", 1); + (void)write(f, "\n", 1); if ((sts = __pmProcessPipeClose(fp) < 0)) { fprintf(stderr, "[tid %d] Warning: func_C: __pmProcessPipeClose() -> %s\n", iam, pmErrStr_r(sts, strbuf, sizeof(strbuf))); } @@ -363,14 +363,14 @@ pthread_exit("botch D.6"); } - write(f, "Answer: ", strlen("Answer: ")); + (void)write(f, "Answer: ", strlen("Answer: ")); lastc = EOF; while (read(fileno(fp), &c, 1) == 1) { - write(f, &c, 1); + (void)write(f, &c, 1); lastc = c; } if (lastc != '\n') { - write(f, "\n", 1); + (void)write(f, "\n", 1); } if ((sts = __pmProcessPipeClose(fp) < 0)) { fprintf(stderr, "[tid %d] Error: func_D: __pmProcessPipeClose() -> %s\n", iam, pmErrStr_r(sts, strbuf, sizeof(strbuf))); diff -Nru pcp-5.3.1/qa/src/parsehostattrs.c pcp-5.3.2/qa/src/parsehostattrs.c --- pcp-5.3.1/qa/src/parsehostattrs.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/src/parsehostattrs.c 2021-06-15 01:03:49.000000000 +0000 @@ -22,7 +22,7 @@ char *msg; char buffer[512]; __pmHashCtl attrs; - pmHostSpec *hosts; + __pmHostSpec *hosts; int count, sts, i, j; if (argc != 2) { diff -Nru pcp-5.3.1/qa/src/parsehostspec.c pcp-5.3.2/qa/src/parsehostspec.c --- pcp-5.3.1/qa/src/parsehostspec.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/qa/src/parsehostspec.c 2021-06-15 01:03:49.000000000 +0000 @@ -6,7 +6,7 @@ main(int argc, char **argv) { char *msg, buffer[512]; - pmHostSpec *hosts; + __pmHostSpec *hosts; int count, sts, i, j; if (argc != 2) { diff -Nru pcp-5.3.1/qa/src/sizeof.c pcp-5.3.2/qa/src/sizeof.c --- pcp-5.3.1/qa/src/sizeof.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/qa/src/sizeof.c 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * print sizeof() some common types + * + * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2021 Ken McDonell. All Rights Reserved. + */ + +#include +#include + +int +main(int argc, char **argv) +{ + while (argc > 1) { + if (strcmp(argv[1], "char") == 0) + printf("char=%zd\n", sizeof(char)); + else if (strcmp(argv[1], "short") == 0) + printf("short=%zd\n", sizeof(short)); + else if (strcmp(argv[1], "int") == 0) + printf("int=%zd\n", sizeof(int)); + else if (strcmp(argv[1], "long") == 0) + printf("long=%zd\n", sizeof(long)); + else if (strcmp(argv[1], "long long") == 0) + printf("long long=%zd\n", sizeof(long long)); + else if (strcmp(argv[1], "float") == 0) + printf("float=%zd\n", sizeof(float)); + else if (strcmp(argv[1], "double") == 0) + printf("double=%zd\n", sizeof(long)); + else if (strcmp(argv[1], "ptr") == 0) + printf("ptr=%zd\n", sizeof(void *)); + else { + printf("Botch: don't grok type \"%s\"\n", argv[1]); + return 1; + } + argc--; + argv++; + } + + return 0; +} diff -Nru pcp-5.3.1/qa/src/tztest.c pcp-5.3.2/qa/src/tztest.c --- pcp-5.3.1/qa/src/tztest.c 2019-02-26 21:38:22.000000000 +0000 +++ pcp-5.3.2/qa/src/tztest.c 2021-07-30 04:05:06.000000000 +0000 @@ -1,20 +1,40 @@ #include #include #include +#include #include #include "libpcp.h" -int main() +/* + * this is a real hack ... we need to redefine the libc version + * of time() so that when we pick a timezone for the old-style + * DST TZ settings we do so deterministically ... this happens + * in the bowels of libpcp in __pmSquashTZ() which is what this + * test is really exercising. + */ +time_t now = 24 * 3600; /* day 2 ! */ + +time_t +time(time_t *tloc) { - time_t sep = (30*365.25+244)*24*3600; /* 1 September 2000 */ - time_t mar = (30*365.25+60)*24*3600; /* 1 March 2000 */ + if (tloc != NULL) + *tloc = now; + return now; +} - /* Two sets of timezone strings - one works for the first half - * of the year, another for the second. Make sure that in the case - * where we cannot reduce the timezone string and have to re-write it - * same timezone is choosen */ - char *zones[][8] = { - { +int main(int argc, char **argv) +{ + int sts; + time_t sep; + time_t mar; + struct tm init; + + /* Test timezone strings. + * Make sure that in the case where we cannot reduce the timezone + * string and have to re-write it the same timezone offset + * is choosen + */ + char *zones[] = { "ABC-10", "ABC-10:01:02XYZ-11:03:04,M12.5.0/3:04:05,M7.1.0/2:06:07", "ABC-10:00:00XYZ-11:00:00,M12.5.0/3:00:00,M7.5.0/2:00:00", @@ -23,40 +43,68 @@ "ABC-10", ":Someplace/Somewhere", NULL - }, - { - "ABC-10", - "XYZ-11:03:04ABC-10:01:02,M12.5.0/3:04:05,M7.1.0/2:06:07", - "ABC-10:00:00XYZ-11:00:00,M12.5.0/3:00:00,M7.5.0/2:00:00", - "ABC-10XYZ-11,M12.5.0/3:00:00,M7.1.0/2:00:00", - "XYZ-11ABC-10,M12.5.0/3:01:02,M7.1.0/2:03:04", - "ABC-10", - ":Someplace/Somewhere", - NULL - }}; - char * tz = getenv("TZ"); + }; + char *tz; + + /* + * quick and dirty, only -D supported + */ + if (argc >= 2 && strncmp(argv[1], "-D", 2) == 0) { + char *spec = NULL; + if (argv[1][2] != '\0') + spec = &argv[1][2]; + else if (argc >= 3) + spec = argv[2]; + if (spec != NULL) + sts = pmSetDebug(spec); + else + sts = -1; + printf("pmSetDebug(\"%s\") -> %d\n", spec, sts); + } + + tz = getenv("TZ"); + + putenv("TZ=UTC"); + /* mar == 12:00:00 1 Mar 2000 UTC */ + memset(&init, 0, sizeof(init)); + init.tm_hour = 12; + init.tm_mday = 1; + init.tm_mon = 2; + init.tm_year = 2000 - 1900; + mar = mktime(&init); + + /* sep == 12:00:00 1 Sep 2000 UTC */ + memset(&init, 0, sizeof(init)); + init.tm_hour = 12; + init.tm_mday = 1; + init.tm_mon = 8; + init.tm_year = 2000 - 1900; + sep = mktime(&init); if (tz == NULL) { printf("Debug: Mar time_t %ld -> %s", (long)mar, ctime(&mar)); printf("Debug: Sep time_t %ld -> %s", (long)sep, ctime(&sep)); puts("Timezone is not set, abort the test"); } else { - int i; - time_t now = time(NULL); - struct tm * today = localtime(&now); - int which = today->tm_mon / 6; - char tb[256]; - char * newtz = __pmTimezone(); + int i; + char tb[256]; + char *newtz; + + /* restore $TZ from environment at the start of main() */ + pmsprintf(tb, sizeof(tb), "TZ=%s", tz); + putenv(tb); + + newtz = __pmTimezone(); printf("%s -> %s\n", tz, newtz); - for (i=0; zones[which][i] != NULL; i++) { + for (i=0; zones[i] != NULL; i++) { char * tz; struct tm *tmp; char tstr[64]; int dst; - pmsprintf(tb, sizeof(tb), "TZ=%s", zones[which][i]); + pmsprintf(tb, sizeof(tb), "TZ=%s", zones[i]); putenv(tb); tzset(); tz = getenv("TZ"); diff -Nru pcp-5.3.1/qa/valgrind-suppress-3.15.0 pcp-5.3.2/qa/valgrind-suppress-3.15.0 --- pcp-5.3.1/qa/valgrind-suppress-3.15.0 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/qa/valgrind-suppress-3.15.0 2021-07-30 04:05:06.000000000 +0000 @@ -184,3 +184,49 @@ ... } +# qa/720 on test-ubuntu2004-direct +# Conditional jump or move depends on uninitialised value(s) +# at 0x4D02AC8: sasl_strlower (in /usr/lib/x86_64-linux-gnu/libsasl2.so.2.0.25) +# by 0x4D02B22: ??? (in /usr/lib/x86_64-linux-gnu/libsasl2.so.2.0.25) +# by 0x4CFC291: sasl_client_new (in /usr/lib/x86_64-linux-gnu/libsasl2.so.2.0.25) +# by 0x48D000C: __pmSecureClientHandshake (in /usr/lib/libpcp.so.3) +# by 0x4877432: ??? (in /usr/lib/libpcp.so.3) +# by 0x4877D00: ??? (in /usr/lib/libpcp.so.3) +# by 0x487ACAA: pmNewContext (in /usr/lib/libpcp.so.3) +# by 0x10AF80: ??? (in /usr/bin/pminfo) +# by 0x49390B2: (below main) (libc-start.c:308) +{ + sasl_strlower() + Memcheck:Cond + fun:sasl_strlower + ... + fun:sasl_client_new + fun:__pmSecureClientHandshake + ... + fun:pmNewContext + ... +} + +# qa/720 on test-ubuntu2004-direct +# Conditional jump or move depends on uninitialised value(s) +# at 0x483F0B7: strcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) +# by 0x4CFDFAD: ??? (in /usr/lib/x86_64-linux-gnu/libsasl2.so.2.0.25) +# by 0x4CFC2AA: sasl_client_new (in /usr/lib/x86_64-linux-gnu/libsasl2.so.2.0.25) +# by 0x48D000C: __pmSecureClientHandshake (in /usr/lib/libpcp.so.3) +# by 0x4877432: ??? (in /usr/lib/libpcp.so.3) +# by 0x4877D00: ??? (in /usr/lib/libpcp.so.3) +# by 0x487ACAA: pmNewContext (in /usr/lib/libpcp.so.3) +# by 0x10AF80: ??? (in /usr/bin/pminfo) +# by 0x49390B2: (below main) (libc-start.c:308) +{ + sasl_client_new + strcpy + Memcheck:Cond + fun:strcpy + ... + fun:sasl_client_new + fun:__pmSecureClientHandshake + ... + fun:pmNewContext + ... +} + diff -Nru pcp-5.3.1/README.md pcp-5.3.2/README.md --- pcp-5.3.1/README.md 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/README.md 2021-07-30 04:05:06.000000000 +0000 @@ -7,7 +7,7 @@ [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1872/badge)](https://bestpractices.coreinfrastructure.org/projects/1872) [![Mailing List](https://img.shields.io/badge/Mailing%20List-pcp-blue.svg)](https://groups.io/g/pcp) [![Slack Team](https://img.shields.io/badge/Slack-pcp-blue.svg)](https://h7zo83mvt1.execute-api.us-west-2.amazonaws.com/Express/) -[![IRC #pcp](https://img.shields.io/badge/IRC-pcp-blue.svg)](https://webchat.freenode.net/#pcp) +[![IRC #pcp](https://img.shields.io/badge/IRC-pcp-blue.svg)](https://web.libera.chat/#pcp) [![Github Release](https://img.shields.io/github/release/performancecopilot/pcp.svg)](https://github.com/performancecopilot/pcp/releases/latest) Performance Co-Pilot (PCP) provides a framework and services to support diff -Nru pcp-5.3.1/src/bashrc/pcp_completion.sh pcp-5.3.2/src/bashrc/pcp_completion.sh --- pcp-5.3.1/src/bashrc/pcp_completion.sh 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/bashrc/pcp_completion.sh 2021-07-30 04:05:06.000000000 +0000 @@ -44,8 +44,12 @@ all_args="ahLKcCeVHGASTOstRrIijJ4589nNvP0qQbByYgpXExl" arg_regex="-[ahKceASTOstiJ489NP0qQbByYgpXEx]" ;; + pmclient) + all_args="AahnOPSsTtVZz" + arg_regex="-[AahnOSsTtZz]" + ;; pmdumplog) - all_args="adehiLlMmnrSsTtVvxZz" + all_args="adehIiLlMmnrSsTtVvxZz" arg_regex="-[nSTvZ]" ;; pmdumptext) @@ -202,4 +206,4 @@ fi fi } -complete -F _pcp_complete -o default pcp2elasticsearch pcp2graphite pcp2influxdb pcp2json pcp2spark pcp2xlsx pcp2xml pcp2zabbix pmdumplog pmdumptext pmevent pmfind pmie pmie2col pmiectl pminfo pmjson pmlc pmlogcheck pmlogctl pmlogextract pmlogger pmloglabel pmlogpaste pmlogreduce pmlogsize pmlogsummary pmprobe pmrep pmseries pmstat pmstore pmval +complete -F _pcp_complete -o default pcp2elasticsearch pcp2graphite pcp2influxdb pcp2json pcp2spark pcp2xlsx pcp2xml pcp2zabbix pmclient pmdumplog pmdumptext pmevent pmfind pmie pmie2col pmiectl pminfo pmjson pmlc pmlogcheck pmlogctl pmlogextract pmlogger pmloglabel pmlogpaste pmlogreduce pmlogsize pmlogsummary pmprobe pmrep pmseries pmstat pmstore pmval diff -Nru pcp-5.3.1/src/dbpmda/src/gram.y pcp-5.3.2/src/dbpmda/src/gram.y --- pcp-5.3.1/src/dbpmda/src/gram.y 2020-12-17 22:46:06.000000000 +0000 +++ pcp-5.3.2/src/dbpmda/src/gram.y 2021-07-30 04:05:06.000000000 +0000 @@ -106,6 +106,7 @@ PATHNAME MACRO STRING + NEGNAME %term COMMA EQUAL OPEN CLOSE DESC GETDESC GETINAME FETCH INSTANCE PROFILE HELP @@ -706,7 +707,10 @@ $$ = 0; } | flag { - sts = pmSetDebug($1); + if ($1[0] == '-') + sts = pmClearDebug(&$1[1]); + else + sts = pmSetDebug($1); if (sts < 0) { pmsprintf(warnStr, MYWARNSTRSZ, "Bad debug flag (%s)", $1); yyerror(warnStr); @@ -737,7 +741,10 @@ $$ = 0; } | debug flag { - sts = pmSetDebug($2); + if ($2[0] == '-') + sts = pmClearDebug(&$2[1]); + else + sts = pmSetDebug($2); if (sts < 0) { pmsprintf(warnStr, MYWARNSTRSZ, "Bad debug flag (%s)", $2); yyerror(warnStr); @@ -746,7 +753,10 @@ $$ = 0; } | debug COMMA flag { - sts = pmSetDebug($3); + if ($3[0] == '-') + sts = pmClearDebug(&$3[1]); + else + sts = pmSetDebug($3); if (sts < 0) { pmsprintf(warnStr, MYWARNSTRSZ, "Bad debug flag (%s)", $3); yyerror(warnStr); @@ -762,6 +772,7 @@ * lexer for type NAME */ flag : NAME { $$ = $1; } + | NEGNAME { $$ = $1; } | FETCH { $$ = strdup("fetch"); gc_add($$); } | PROFILE { $$ = strdup("profile"); gc_add($$); } | CTXT { $$ = strdup("context"); gc_add($$); } diff -Nru pcp-5.3.1/src/dbpmda/src/lex.l pcp-5.3.2/src/dbpmda/src/lex.l --- pcp-5.3.1/src/dbpmda/src/lex.l 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/dbpmda/src/lex.l 2021-07-30 04:05:06.000000000 +0000 @@ -117,6 +117,13 @@ return NAME; } +-[A-Za-z][A-Za-z0-9_\./:-]* { + yylval.y_str = (char *)malloc(yyleng+1); + strcpy(yylval.y_str, yytext); + gc_add(yylval.y_str); + return NEGNAME; + } + \$[A-Za-z][A-Za-z0-9_-]* { yylval.y_str = (char *)malloc(yyleng+1); strcpy(yylval.y_str, yytext); diff -Nru pcp-5.3.1/src/dbpmda/src/util.c pcp-5.3.2/src/dbpmda/src/util.c --- pcp-5.3.1/src/dbpmda/src/util.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/dbpmda/src/util.c 2021-07-30 04:05:06.000000000 +0000 @@ -303,7 +303,7 @@ break; case DBG: puts("debug all | none"); - puts("debug option [ option ... ] (option is a symbolic name or a decimal number)"); + puts("debug [-]flag [ [-]flag ... ] (- prefix to clear)"); break; case DESC: puts("desc metric"); diff -Nru pcp-5.3.1/src/hacks/delta-indom-stats-all pcp-5.3.2/src/hacks/delta-indom-stats-all --- pcp-5.3.1/src/hacks/delta-indom-stats-all 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/hacks/delta-indom-stats-all 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Do delta-indom-stats for all the archives you can find under +# the sun. +# + +dirs="$@" +if [ -z "$dirs" ]; then + echo "Usage: delta-indom-stats-all [path]..." + exit 1 +fi + +make delta-indom-stats + +find $dirs \( -name "*.meta.*" -o -name "*.meta" \) \ +| while read arch +do + case "$arch" + in + */qa/badarchives/*|*/qa/*.full) + ;; + *) + ./delta-indom-stats "$arch" 2>&1 + ;; + esac +done >report.full + +( sed -n 1024*1024 { print; big++; next } +small == 0 { print "More than 1Mb saving for " big " archives" } + { small++ } +END { print "And less than 1Mb saving for " small " archives" }' + +grep '\(no change\)' report.full \ +| wc -l \ +| sed -e 's/ *//g' -e 's/.*/No change for & archives./' + +echo "See report.full for chapter and verse ..." diff -Nru pcp-5.3.1/src/hacks/delta-indom-stats.c pcp-5.3.2/src/hacks/delta-indom-stats.c --- pcp-5.3.1/src/hacks/delta-indom-stats.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/hacks/delta-indom-stats.c 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,522 @@ +/* + * Produce metadata stats summary for delta-indom proposal and V3 archives + * + * Copyright (c) 2021 Ken McDonell. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include +#include +#include +#include +#include +#include "../libpcp/src/internal.h" + +typedef struct { + int inst; + char *name; +} sortrec_t; + +/* one per indom */ +typedef struct { + pmInDom indom; + int first_numinst; + int added; + int dropped; + int numinst; + int all_numinst; + size_t v2_size; + size_t v3_size; + int *tbuf; + sortrec_t *ctl; +} stats_t; + +/* indom table */ +static stats_t *stats = NULL; +static int numstats = 0; + +/* strings for external instance names */ +static size_t v2_str; +static size_t v3_str; +static int v2_count; +static int v3_count; + +/* lazy loading */ +static size_t v2_maps; +static size_t v3_maps; + +static int +compar(const void *a, const void *b) +{ + return ((sortrec_t *)a)->inst - ((sortrec_t *)b)->inst; +} + +static int +is_sorted(int numinst, sortrec_t *ctl) +{ + int i; + + for (i = 1; i < numinst; i++) { + if (ctl[i].inst < ctl[i-1].inst) { + fprintf(stderr, "[%d] %d < [%d] %d\n", i, ctl[i].inst, i-1, ctl[i-1].inst); + return 0; + } + } + return 1; +} + +static void +report(void) +{ + stats_t *sp; + int unchanged = 0; + + for (sp = stats; sp < &stats[numstats]; sp++) { + if (sp->added + sp->dropped == 0) { + unchanged++; + continue; + } + printf("InDom: %s", pmInDomStr(sp->indom)); + printf(" logged instances:"); + printf(" (V2) %d (V3) %d [%d + %d - %d = %d", + sp->all_numinst, + sp->first_numinst + sp->added + sp->dropped, + sp->first_numinst, sp->added, sp->dropped, + sp->numinst); + if (sp->first_numinst + sp->added - sp->dropped != sp->numinst) + printf(" botch: != %d", + sp->first_numinst + sp->added - sp->dropped); + printf("]\n"); + } + if (unchanged) { + if (unchanged != numstats) + printf("Plus "); + printf("%d static InDoms (no change)\n", unchanged); + } + + if (unchanged == numstats) + exit(0); + +} + +static stats_t +*find(pmInDom indom) +{ + int i; + stats_t *tmp; + + for (i = 0; i < numstats; i++) { + if (stats[i].indom == indom) + return &stats[i]; + } + + /* first time for this indom alloc and initialize */ + numstats++; + + tmp = (stats_t *)realloc(stats, numstats * sizeof(stats_t)); + if (tmp == NULL) { + } + stats = tmp; + + memset(&stats[numstats-1], 0, sizeof(stats_t)); + stats[numstats-1].indom = indom; + + return &stats[numstats-1]; +} + +static char +*pr_size(size_t n) +{ + static char buf[10]; + + if (n < 10*1024) + sprintf(buf, "%7zd ", n); + else if (n < 10*1024*1024) + sprintf(buf, "%6.2fKb", n / (double)1024); + else if (n < 10*1024*1024*1024L) + sprintf(buf, "%6.2fMb", n / (double)(1024*1024)); + else + sprintf(buf, "%6.2fGb", n / (double)(1024*1024*1024L)); + + return buf; +} + +int +main(int argc, char **argv) +{ + int c; + int sts; + int n; + int rlen; + int check; + int i; + int j; + size_t v2_size; + size_t v3_size; + __pmContext *ctxp; + __pmFILE *f; + __pmLogHdr h; + int count[5] = { 0,0,0,0,0 }; + char *types[5] = { "?", "DESC", "INDOM", "LABEL", "TEXT" }; + size_t bytes[5] = { 0,0,0,0,0 }; + stats_t *sp; + struct stat sbuf; + + while ((c = getopt(argc, argv, "D:")) != EOF) { + switch (c) { + case 'D': + sts = pmSetDebug(optarg); + if (sts < 0) { + fprintf(stderr, "Bad debug options (%s)\n", optarg); + exit(1); + } + } + } + + if (optind != argc-1) { + fprintf(stderr, "Usage: delta-indom-stats [-D flags] archive\n"); + return(1); + } + + if ((sts = pmNewContext(PM_CONTEXT_ARCHIVE, argv[optind])) < 0) { + fprintf(stderr, "pmNewContext(%s): %s\n", argv[optind], pmErrStr(sts)); + exit(1); + } + + + if ((ctxp = __pmHandleToPtr(sts)) == NULL) { + fprintf(stderr, " __pmHandleToPtr(%d) returns NULL!\n", sts); + exit(1); + } + + /* single threaded, release context lock */ + PM_UNLOCK(ctxp->c_lock); + + printf("%s:\n", ctxp->c_archctl->ac_log->l_name); + + f = ctxp->c_archctl->ac_log->l_mdfp; + + /* + * snarfed from __pmLogLoadMeta() in logmeta.c + */ + __pmFseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); + for ( ; ; ) { + n = (int)__pmFread(&h, 1, sizeof(__pmLogHdr), f); + + /* swab hdr */ + h.len = ntohl(h.len); + h.type = ntohl(h.type); + + if (n != sizeof(__pmLogHdr) || h.len <= 0) { + if (__pmFeof(f)) { + __pmClearerr(f); + sts = 0; + break; + } + if (pmDebugOptions.logmeta) { + fprintf(stderr, "header read -> %d: expected: %d or h.len (%d) <= 0\n", + n, (int)sizeof(__pmLogHdr), h.len); + } + if (__pmFerror(f)) { + __pmClearerr(f); + sts = -oserror(); + } + else + sts = PM_ERR_LOGREC; + break; + } + rlen = h.len - (int)sizeof(__pmLogHdr) - (int)sizeof(int); + count[h.type]++; + bytes[h.type] += h.len; + if (h.type == TYPE_INDOM) { + pmTimeval *tv; + //pmTimespec when; + pmInResult in; + char *namebase; + int *tbuf, *stridx; + sortrec_t *ctl; + int i, k, allinbuf = 0; + + if ((tbuf = (int *)malloc(rlen)) == NULL) { + fprintf(stderr, "tbuf: malloc failed: %d\n", rlen); + exit(1); + } + if ((n = (int)__pmFread(tbuf, 1, rlen, f)) != rlen) { + if (pmDebugOptions.logmeta) { + fprintf(stderr, "__pmFread: indom read -> %d: expected: %d\n", + n, rlen); + } + if (__pmFerror(f)) { + __pmClearerr(f); + sts = -oserror(); + } + else + sts = PM_ERR_LOGREC; + free(tbuf); + goto end; + } + + k = 0; + tv = (pmTimeval *)&tbuf[k]; + //when.tv_sec = ntohl(tv->tv_sec); + //when.tv_nsec = ntohl(tv->tv_usec) * 1000; + k += sizeof(*tv)/sizeof(int); + in.indom = __ntohpmInDom((unsigned int)tbuf[k++]); + in.numinst = ntohl(tbuf[k++]); + sp = find((pmInDom)in.indom); + if (sp->ctl == NULL) { + /* first time */ + sp->all_numinst = sp->first_numinst = in.numinst; + } + else { + sp->all_numinst += in.numinst; + } + sp->v2_size += h.len; + sp->v3_size += sizeof(__pmLogHdr) /* log record header */ + + sizeof(in.indom) + + sizeof(in.numinst) + + sizeof(int); /* log record trailer */ + if (in.numinst > 0) { + in.instlist = &tbuf[k]; + k += in.numinst; + stridx = &tbuf[k]; +#if defined(HAVE_32BIT_PTR) + in.namelist = (char **)stridx; + allinbuf = 1; /* allocation is all in tbuf */ +#else + allinbuf = 0; /* allocation for namelist + tbuf */ + /* need to allocate to hold the pointers */ + in.namelist = (char **)malloc(in.numinst * sizeof(char*)); + if (in.namelist == NULL) { + fprintf(stderr, "in.namelist: malloc failed: %zd\n", in.numinst * sizeof(char*)); + exit(1); + } +#endif + k += in.numinst; + namebase = (char *)&tbuf[k]; + for (i = 0; i < in.numinst; i++) { + in.instlist[i] = ntohl(in.instlist[i]); + in.namelist[i] = &namebase[ntohl(stridx[i])]; + } + + /* build a control structure for sorting */ + ctl = (sortrec_t *)malloc(in.numinst * sizeof(sortrec_t)); + for (i = 0; i < in.numinst; i++) { + ctl[i].inst = in.instlist[i]; + ctl[i].name = in.namelist[i]; + } + + if (in.numinst > 1) { + qsort((void *)ctl, in.numinst, sizeof(sortrec_t), compar); + } + /* just being sure that our qsort use produces a sorted indom */ + if (!is_sorted(in.numinst, ctl)) { + printf("not sorted\n"); + break; + } + if (in.namelist != NULL && !allinbuf) + free(in.namelist); + + + if (sp->ctl != NULL) { + /* + * 2nd or later record for the indom ... + * find what's added, what's dropped and what's the same + */ + for (i = 0, j = 0; i < sp->numinst || j < in.numinst; ) { + if ((i < sp->numinst && j == in.numinst) || + (i < sp->numinst && j < in.numinst && sp->ctl[i].inst < ctl[j].inst)) { + if (pmDebugOptions.appl0) + printf("dropped %d -> %-29.29s\n", sp->ctl[i].inst, sp->ctl[i].name); + sp->dropped++; + sp->v3_size += 2*sizeof(int); + v3_maps += sizeof(int) + sizeof(char *); + v3_count++; + i++; + } + else if ((i == sp->numinst && j < in.numinst) || + (i < sp->numinst && j < in.numinst && sp->ctl[i].inst > ctl[j].inst)) { + if (pmDebugOptions.appl0) + printf("added %d -> %-29.29s\n", ctl[j].inst, ctl[j].name); + sp->added++; + sp->v3_size += 2*sizeof(int) + strlen(ctl[j].name) + 1; + v3_str += strlen(ctl[j].name) + 1; + v3_maps += sizeof(int) + sizeof(char *); + v3_count++; + j++; + } + else if (sp->ctl[i].inst == ctl[j].inst) { + // printf("same %d -> %-29.29s ... %-29.29s\n", sp->ctl[i].inst, sp->ctl[i].name, ctl[j].name); + i++; + j++; + } + else { + printf("botch: i=%d sp->numist=%d j=%d in.numinst=%d\n", i, sp->numinst, j, in.numinst); + exit(1); + } + } + free(sp->tbuf); + free(sp->ctl); + } + else { + /* first time, all instance names needed */ + for (i = 0; i < in.numinst; i++) + v3_str += strlen(ctl[i].name) + 1; + v3_maps += in.numinst * (sizeof(int) + sizeof(char *)); + v3_count += in.numinst; + } + + sp->numinst = in.numinst; + sp->tbuf = tbuf; + sp->ctl = ctl; + } + else { + /* no instances, or an error */ + free(tbuf); + } + } + else { + /* skip this record, not TYPE_INDOM */ + __pmFseek(f, (long)rlen, SEEK_CUR); + } + n = (int)__pmFread(&check, 1, sizeof(check), f); + check = ntohl(check); + if (n != sizeof(check) || h.len != check) { + if (__pmFerror(f)) { + __pmClearerr(f); + sts = -oserror(); + } + else + sts = PM_ERR_LOGREC; + break; + } + } + +end: + report(); + + putchar('\n'); + printf("On disk analysis ...\n"); + printf("%8s %8s %9s %9s %9s\n", "Type", "Count", "V2 Size", "V3 Size", "Saving"); + printf("%8s %8s %9s %9s %9s\n", "", "", " (uncompressed)", "", ""); + /* add in label record */ + v2_size = v3_size = sizeof(__pmLogLabel) + 2*sizeof(int); + for (sp = stats; sp < &stats[numstats]; sp++) { + v2_size += sp->v2_size; + v3_size += sp->v3_size; + } + bytes[0] = count[0] = 0; + for (i = 1; i < sizeof(types)/sizeof(types[0]); i++) { + printf("%8s %8d %9s", types[i], count[i], pr_size(bytes[i])); + count[0] += count[i]; + if (i == TYPE_INDOM) { + printf(" %9s", pr_size(v3_size)); + printf(" %9s (%.1f%%)\n", pr_size(v2_size - v3_size), + 100.0*((long)v2_size - (long)v3_size) / v2_size); + } + else { + printf(" %9s\n", pr_size(bytes[i])); + bytes[0] += bytes[i]; + } + } + v2_size += bytes[0]; + v3_size += bytes[0]; + printf("%8s %8d %9s", "All meta", count[0], pr_size(v2_size)); + printf(" %9s", pr_size(v3_size)); + printf(" %9s (%.1f%%)\n", pr_size(v2_size - v3_size), + 100.0*((long)v2_size - (long)v3_size) / v2_size); + + /* now the temporal index (optional) */ + if (ctxp->c_archctl->ac_log->l_tifp) { + if ((sts = __pmFstat(ctxp->c_archctl->ac_log->l_tifp, &sbuf)) < 0) { + fprintf(stderr, "__pmFstat: %s\n", pmErrStr(sts)); + exit(1); + } + printf("%8s %8zd %9s", "Index", + (sbuf.st_size-sizeof(__pmLogLabel))/sizeof(__pmLogTI), + pr_size(sbuf.st_size)); + printf(" %9s\n", pr_size(sbuf.st_size)); + v2_size += sbuf.st_size; + v3_size += sbuf.st_size; + } + + /* and finally each data volume */ + for (i = ctxp->c_archctl->ac_log->l_minvol; i <= ctxp->c_archctl->ac_log->l_maxvol; i++) { + char fname[MAXPATHLEN+1]; + pmsprintf(fname, sizeof(fname), "%s.%d", ctxp->c_archctl->ac_log->l_name, i); + if ((f = __pmFopen(fname, "r")) == NULL) { + fprintf(stderr, "__pmFopen(%s): %s\n", fname, pmErrStr(-oserror())); + continue; + } + if ((sts = __pmFstat(f, &sbuf)) < 0) { + fprintf(stderr, "__pmFstat(%s): %s\n", fname, pmErrStr(sts)); + exit(1); + } + printf("%5s.%2d %8s %9s", "Data", i, "", pr_size(sbuf.st_size)); + printf(" %9s\n", pr_size(sbuf.st_size)); + v2_size += sbuf.st_size; + v3_size += sbuf.st_size; + } + + printf("%8s %8s %9s", "Total", "", pr_size(v2_size)); + printf(" %9s", pr_size(v3_size)); + printf(" %9s (%.1f%%) %s\n", pr_size(v2_size - v3_size), + 100.0*((long)v2_size - (long)v3_size) / v2_size, + ctxp->c_archctl->ac_log->l_name); + + putchar('\n'); + v2_size = v3_size = 0; + printf("Memory footprint analysis ...\n"); + printf("%12s %9s %9s %9s %9s %9s\n", "Type", "V2 Count", "V2 Size", "V3 Count", "V3 Size", "Saving"); + + /* + * need to get v2_maps and v2_str from loaded instance domains + * ... "dup" indom handling in __pmLogLoadMeta() (see + * __pmLogAddInDom() and PMLOGPUTINDOM_DUP) means there may be + * fewer loaded than appear in the .meta file + */ + for (i = 0; i < ctxp->c_archctl->ac_log->l_hashindom.hsize; i++) { + __pmHashNode *hp; + __pmLogInDom *idp; + for (hp = ctxp->c_archctl->ac_log->l_hashindom.hash[i]; hp != NULL; hp = hp->next) { + for (idp = (__pmLogInDom *)hp->data; idp != NULL; idp =idp->next) { + v2_maps += idp->numinst * (sizeof(int) + sizeof(char *)); + v2_count += idp->numinst; + for (j = 0; j < idp->numinst; j++) { + v2_str += strlen(idp->namelist[j])+1; + } + } + } + } + + printf("%12s %9d %9s", "Inst names", v2_count, pr_size(v2_str)); + v2_size += v2_str; + printf(" %9d %9s", v3_count, pr_size(v3_str)); + v3_size += v3_str; + printf(" %9s (%.1f%%)\n", pr_size(v2_str - v3_str), + 100.0*(long)(v2_str - v3_str)/(long)(v2_str)); + + printf("%12s %9s %9s", "Lazy load", "", pr_size(v2_maps)); + v2_size += v2_maps; + printf(" %9s %9s", "", pr_size(v3_maps)); + v3_size += v3_maps; + printf(" %9s (%.1f%%)\n", pr_size(v2_maps - v3_maps), + 100.0*(long)(v2_maps - v3_maps)/(long)(v2_maps)); + + printf("%12s %9s %9s", "Total", "", pr_size(v2_size)); + printf(" %9s %9s", "", pr_size(v3_size)); + printf(" %9s (%.1f%%) %s\n", pr_size(v2_size - v3_size), + 100.0*(long)(v2_size - v3_size)/(long)(v2_size), + ctxp->c_archctl->ac_log->l_name); + + + return(sts); +} diff -Nru pcp-5.3.1/src/hacks/.gitignore pcp-5.3.2/src/hacks/.gitignore --- pcp-5.3.1/src/hacks/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/hacks/.gitignore 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,2 @@ +delta-indom-stats +report.full diff -Nru pcp-5.3.1/src/hacks/GNUmakefile pcp-5.3.2/src/hacks/GNUmakefile --- pcp-5.3.1/src/hacks/GNUmakefile 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/hacks/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,21 @@ +# + +TOPDIR = ../.. +include $(TOPDIR)/src/include/builddefs + +LLDLIBS = $(PCPLIB) +EXEC = delta-indom-stats +LDIRT = $(EXEC) + +default: $(EXEC) + +include $(BUILDRULES) + +# just to be sure ... +# +default_pcp: +install: +install_pcp: +check:: + +delta-indom-stats: delta-indom-stats.c diff -Nru pcp-5.3.1/src/hacks/README pcp-5.3.2/src/hacks/README --- pcp-5.3.1/src/hacks/README 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/hacks/README 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,6 @@ +PCP Developer Hacks + +These are quick and dirty apps and tools to aid development or debugging. + +The build does not descend here, so nothing in this directory is ever +shipped. diff -Nru pcp-5.3.1/src/include/builddefs.in pcp-5.3.2/src/include/builddefs.in --- pcp-5.3.1/src/include/builddefs.in 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/include/builddefs.in 2021-07-30 04:05:06.000000000 +0000 @@ -117,9 +117,10 @@ CFLAGS_ABI = @cflags_abi@ CFLAGS_OPT = @optimization@ +CFLAGS_SANITIZER = @sanitizer@ CFLAGS += -I$(TOPDIR)/src/include -I$(TOPDIR)/src/include/pcp \ -DPCP_VERSION=\"$(PCP_VERSION)\" \ - $(PCFLAGS) $(LCFLAGS) $(WARN_OFF) $(CFLAGS_OPT) + $(PCFLAGS) $(LCFLAGS) $(WARN_OFF) $(CFLAGS_OPT) $(CFLAGS_SANITIZER) PIECFLAGS = @PIECFLAGS@ PIELDFLAGS = @PIELDFLAGS@ @@ -138,7 +139,10 @@ SRCFILES = GNUmakefile $(HFILES) $(CFILES) $(CXXFILES) $(MFILES) \ $(LSRCFILES) $(LFILES) $(YFILES) $(PYFILES) -LDLIBS = $(LLDLIBS) $(PLDLIBS) +GPERFTOOLS_LIBS = @gperftools_LIBS@ + +# tcmalloc of gperftools must be linked last +LDLIBS = $(LLDLIBS) $(PLDLIBS) $(GPERFTOOLS_LIBS) MAKEOPTS = --no-print-directory ifdef PROJECT @@ -346,6 +350,10 @@ HAVE_LIBUV = @HAVE_LIBUV@ LIB_FOR_LIBUV = @libuv_LIBS@ +HAVE_LIBBPF = @HAVE_LIBBPF@ +LIB_FOR_LIBBPF = @libbpf_LIBS@ +HAVE_LIBELF = @HAVE_LIBELF@ +LIB_FOR_LIBELF = @libelf_LIBS@ HAVE_OPENSSL = @HAVE_OPENSSL@ LIB_FOR_OPENSSL = @openssl_LIBS@ HAVE_NCURSES = @HAVE_NCURSES@ diff -Nru pcp-5.3.1/src/include/pcp/libpcp.h pcp-5.3.2/src/include/pcp/libpcp.h --- pcp-5.3.1/src/include/pcp/libpcp.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/include/pcp/libpcp.h 2021-06-15 01:03:49.000000000 +0000 @@ -24,13 +24,6 @@ #ifndef PCP_LIBPCP_H #define PCP_LIBPCP_H -/* - * TODO - * demote names from pm... to __pm... for - * - pmHostSpec - * - pmTimeZone - */ - #ifdef __cplusplus extern "C" { #endif @@ -521,9 +514,9 @@ char *name; /* hostname (always valid) */ int *ports; /* array of host port numbers */ int nports; /* number of ports in host port array */ -} pmHostSpec; -PCP_CALL extern int __pmParseHostSpec(const char *, pmHostSpec **, int *, char **); -PCP_CALL extern int __pmUnparseHostSpec(pmHostSpec *, int, char *, size_t); +} __pmHostSpec; +PCP_CALL extern int __pmParseHostSpec(const char *, __pmHostSpec **, int *, char **); +PCP_CALL extern int __pmUnparseHostSpec(__pmHostSpec *, int, char *, size_t); /* * unfortunately, in this version, PCP archives are limited to no @@ -600,8 +593,8 @@ typedef struct { int pc_fd; /* socket for comm with pmcd */ /* ... -1 means no connection */ - pmHostSpec *pc_hosts; /* pmcd and proxy host specifications */ - int pc_nhosts; /* number of pmHostSpec entries */ + __pmHostSpec *pc_hosts; /* pmcd and proxy host specifications */ + int pc_nhosts; /* number of hostspec entries */ int pc_timeout; /* set if connect times out */ int pc_tout_sec; /* timeout for __pmGetPDU */ time_t pc_again; /* time to try again */ @@ -1220,13 +1213,6 @@ PCP_CALL extern void __pmSetLocalContextTable(pmOptions *, char *); PCP_CALL extern void __pmEndOptions(pmOptions *); -/* real pmTimeZone declaration */ -typedef struct { - char *label; /* label to name tz */ - char *tz; /* env $TZ */ - int handle; /* handle from pmNewZone() */ -} pmTimeZone; - /* work out local timezone */ PCP_CALL extern char *__pmTimezone(void); /* NOT thread-safe */ PCP_CALL extern char *__pmTimezone_r(char *, int); @@ -1312,9 +1298,9 @@ } __pmAttrKey; PCP_CALL extern __pmAttrKey __pmLookupAttrKey(const char *, size_t); PCP_CALL extern int __pmParseHostAttrsSpec( - const char *, pmHostSpec **, int *, __pmHashCtl *, char **); + const char *, __pmHostSpec **, int *, __pmHashCtl *, char **); PCP_CALL extern int __pmUnparseHostAttrsSpec( - pmHostSpec *, int, __pmHashCtl *, char *, size_t); + __pmHostSpec *, int, __pmHashCtl *, char *, size_t); /* SSL/TLS/IPv6 support via NSS/NSPR */ PCP_CALL extern int __pmSecureServerCertificateSetup(const char *, const char *, const char *); @@ -1333,8 +1319,8 @@ /* free malloc'd data structures */ PCP_CALL extern void __pmFreeAttrsSpec(__pmHashCtl *); -PCP_CALL extern void __pmFreeHostAttrsSpec(pmHostSpec *, int, __pmHashCtl *); -PCP_CALL extern void __pmFreeHostSpec(pmHostSpec *, int); +PCP_CALL extern void __pmFreeHostAttrsSpec(__pmHostSpec *, int, __pmHashCtl *); +PCP_CALL extern void __pmFreeHostSpec(__pmHostSpec *, int); PCP_CALL extern void __pmFreeInResult(pmInResult *); PCP_CALL extern void __pmFreePMNS(__pmnsTree *); PCP_CALL extern void __pmFreeProfile(pmProfile *); diff -Nru pcp-5.3.1/src/include/pcp/pmapi.h pcp-5.3.2/src/include/pcp/pmapi.h --- pcp-5.3.1/src/include/pcp/pmapi.h 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/include/pcp/pmapi.h 2021-07-30 04:05:06.000000000 +0000 @@ -1140,6 +1140,7 @@ * New style ... * Note that comments are important ... these are extracted and * built into pmdbg.h. + * For the "add a new debug flag" recipe, see ../../libpcp/src/mk.pmdbg */ typedef struct { int pdu; /* PDU traffic at the Xmit and Recv level */ @@ -1187,6 +1188,9 @@ int search; /* Text search tracing */ int query; /* libpcp_web query parsing and evaulation */ int compress; /* Archive compress/decompress operations */ + int dev0; /* Developer flag 0 */ + int dev1; /* Developer flag 1 */ + int dev2; /* Developer flag 2 */ } pmdebugoptions_t; PCP_DATA extern pmdebugoptions_t pmDebugOptions; diff -Nru pcp-5.3.1/src/include/pcp/pmwebapi.h pcp-5.3.2/src/include/pcp/pmwebapi.h --- pcp-5.3.1/src/include/pcp/pmwebapi.h 2020-12-17 22:46:06.000000000 +0000 +++ pcp-5.3.2/src/include/pcp/pmwebapi.h 2021-07-30 04:05:06.000000000 +0000 @@ -169,6 +169,12 @@ extern int pmSeriesQuery(pmSeriesSettings *, sds, pmSeriesFlags, void *); extern int pmSeriesLoad(pmSeriesSettings *, sds, pmSeriesFlags, void *); +/* libpcp_web timer list interface - global, thread-safe */ +typedef void (*pmWebTimerCallBack)(void *); +extern int pmWebTimerSetMetricRegistry(struct mmv_registry *); /* for generic server metrics */ +extern int pmWebTimerRegister(pmWebTimerCallBack, void *); +extern int pmWebTimerRelease(int); /* deregister one timer */ + /* * Asynchronous archive location and contents discovery services */ diff -Nru pcp-5.3.1/src/libpcp/src/AF.c pcp-5.3.2/src/libpcp/src/AF.c --- pcp-5.3.1/src/libpcp/src/AF.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/AF.c 2021-06-15 01:03:49.000000000 +0000 @@ -124,7 +124,8 @@ } #else /* POSIX */ -static void AFsetitimer(struct timeval *interval) +static void +AFsetitimer(struct timeval *interval) { struct itimerval val; @@ -133,49 +134,31 @@ setitimer(ITIMER_REAL, &val, NULL); } -#if !defined(HAVE_SIGHOLD) -static int -sighold(int sig) +static void +AFhold(void) { sigset_t s; sigemptyset(&s); - sigaddset(&s, sig); + sigaddset(&s, SIGALRM); sigprocmask(SIG_BLOCK, &s, NULL); - - return 0; } -#else -/* - * for Linux the prototype is hidden, even though the function is in - * libc - */ -extern int sighold(int); -#endif - -#if !defined(HAVE_SIGRELSE) -static int -sigrelse(int sig) + +static void +AFrelse(void) { sigset_t s; sigemptyset(&s); - sigaddset(&s, sig); + sigaddset(&s, SIGALRM); sigprocmask(SIG_UNBLOCK, &s, NULL); - return 0; } -#else -/* - * for Linux the prototype is hidden, even though the function is in - * libc - */ -extern int sigrelse(int); -#endif - -static void AFhold(void) { sighold(SIGALRM); } -static void AFrelse(void) { sigrelse(SIGALRM); } -static void AFrearm(void) { signal(SIGALRM, onalarm); } +static void +AFrearm(void) +{ + signal(SIGALRM, onalarm); +} #endif /* POSIX */ diff -Nru pcp-5.3.1/src/libpcp/src/connect.c pcp-5.3.2/src/libpcp/src/connect.c --- pcp-5.3.1/src/libpcp/src/connect.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/connect.c 2021-06-15 01:03:49.000000000 +0000 @@ -332,7 +332,7 @@ } static void -load_proxy_hostspec(pmHostSpec *proxy) +load_proxy_hostspec(__pmHostSpec *proxy) { char errmsg[PM_MAXERRMSGLEN]; char *envstr; @@ -362,7 +362,7 @@ } void -__pmConnectGetPorts(pmHostSpec *host) +__pmConnectGetPorts(__pmHostSpec *host) { PM_INIT_LOCKS(); PM_LOCK(connect_lock); @@ -378,7 +378,7 @@ } int -__pmConnectPMCD(pmHostSpec *hosts, int nhosts, int ctxflags, __pmHashCtl *attrs) +__pmConnectPMCD(__pmHostSpec *hosts, int nhosts, int ctxflags, __pmHashCtl *attrs) { int sts = -1; int fd = -1; /* Fd for socket connection to pmcd */ @@ -387,10 +387,10 @@ int portIx; int version = -1; int proxyport; - pmHostSpec *proxyhost; + __pmHostSpec *proxyhost; static int first_time = 1; - static pmHostSpec proxy; + static __pmHostSpec proxy; PM_INIT_LOCKS(); PM_LOCK(connect_lock); diff -Nru pcp-5.3.1/src/libpcp/src/context.c pcp-5.3.2/src/libpcp/src/context.c --- pcp-5.3.1/src/libpcp/src/context.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/context.c 2021-06-15 01:03:49.000000000 +0000 @@ -1114,7 +1114,7 @@ if (new->c_type == PM_CONTEXT_HOST) { __pmHashCtl *attrs = &new->c_attrs; - pmHostSpec *hosts = NULL; + __pmHostSpec *hosts = NULL; int nhosts; char *errmsg; diff -Nru pcp-5.3.1/src/libpcp/src/fetch.c pcp-5.3.2/src/libpcp/src/fetch.c --- pcp-5.3.1/src/libpcp/src/fetch.c 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/fetch.c 2021-07-30 04:05:06.000000000 +0000 @@ -458,6 +458,7 @@ /* assume PM_CONTEXT_ARCHIVE */ if (l_mode == PM_MODE_INTERP || l_mode == PM_MODE_FORW || l_mode == PM_MODE_BACK) { + int lsts; if (when != NULL) { /* * special case of NULL for timestamp @@ -468,7 +469,18 @@ } ctxp->c_mode = mode; ctxp->c_delta = delta; - __pmLogSetTime(ctxp); + lsts = __pmLogSetTime(ctxp); + if (lsts < 0) { + /* + * most unlikely; not much we can do here but expect + * PMAPI error to be returned once pmFetch's start + */ + if (pmDebugOptions.log) { + char errmsg[PM_MAXERRMSGLEN]; + fprintf(stderr, "pmSetMode: __pmLogSetTime failed: %s\n", + pmErrStr_r(lsts, errmsg, sizeof(errmsg))); + } + } __pmLogResetInterp(ctxp); sts = 0; } diff -Nru pcp-5.3.1/src/libpcp/src/help.c pcp-5.3.2/src/libpcp/src/help.c --- pcp-5.3.1/src/libpcp/src/help.c 2020-08-06 23:53:45.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/help.c 2021-07-30 04:05:06.000000000 +0000 @@ -70,6 +70,9 @@ if ((ctxp = __pmHandleToPtr(ctx)) == NULL) return PM_ERR_NOCONTEXT; + /* not set on all PDU error paths and fallbacktext() checks this ... */ + *buffer = NULL; + if (ctxp->c_type == PM_CONTEXT_HOST) { tout = ctxp->c_pmcd->pc_tout_sec; fd = ctxp->c_pmcd->pc_fd; @@ -80,9 +83,15 @@ else { PM_FAULT_POINT("libpcp/" __FILE__ ":1", PM_FAULT_TIMEOUT); sts = __pmRecvText(fd, ctxp, tout, buffer); - if (sts == 0 && ((type = fallbacktext(type, *buffer)) != 0)) { - free(*buffer); - goto again_host; + if (sts != 0 || *buffer[0] == '\0') { + /* failed help text request, maybe try for one-line */ + if ((type = fallbacktext(type, *buffer)) != 0) { + if (*buffer != NULL) { + free(*buffer); + *buffer = NULL; + } + goto again_host; + } } } } @@ -98,19 +107,24 @@ pmda->version.four.ext->e_context = ctx; again_local: sts = pmda->version.any.text(ident, type, buffer, pmda->version.any.ext); - if (sts == 0 && ((type = fallbacktext(type, *buffer)) != 0)) - goto again_local; + if (sts != 0 || *buffer[0] == '\0') { + /* failed help text request, maybe try for one-line */ + if ((type = fallbacktext(type, *buffer)) != 0) + goto again_local; + } if (sts == 0) /* Points into PMDAs local text - return a copy */ *buffer = strdup(*buffer); } } else { - *buffer = NULL; again_archive: sts = __pmLogLookupText(ctxp->c_archctl, ident, type, buffer); - if (sts == PM_ERR_TEXT && (type = fallbacktext(type, *buffer)) != 0) - goto again_archive; + if (sts != 0 || *buffer[0] == '\0') { + /* failed help text request, maybe try for one-line */ + if ((type = fallbacktext(type, *buffer)) != 0) + goto again_archive; + } if (sts == 0) /* Points into archive hash tables - return a copy */ *buffer = strdup(*buffer); diff -Nru pcp-5.3.1/src/libpcp/src/internal.h pcp-5.3.2/src/libpcp/src/internal.h --- pcp-5.3.1/src/libpcp/src/internal.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/internal.h 2021-07-30 04:05:06.000000000 +0000 @@ -390,14 +390,14 @@ extern __pmSockAddr *__pmSockAddrFirstSubnetAddr(const __pmSockAddr *, int) _PCP_HIDDEN; extern __pmSockAddr *__pmSockAddrNextSubnetAddr(__pmSockAddr *, int) _PCP_HIDDEN; -extern int __pmConnectPMCD(pmHostSpec *, int, int, __pmHashCtl *) _PCP_HIDDEN; +extern int __pmConnectPMCD(__pmHostSpec *, int, int, __pmHashCtl *) _PCP_HIDDEN; extern int __pmConnectLocal(__pmHashCtl *) _PCP_HIDDEN; extern int __pmAuxConnectPMCD(const char *) _PCP_HIDDEN; extern int __pmAuxConnectPMCDUnixSocket(const char *) _PCP_HIDDEN; -extern int __pmAddHostPorts(pmHostSpec *, int *, int) _PCP_HIDDEN; -extern void __pmDropHostPort(pmHostSpec *) _PCP_HIDDEN; -extern void __pmConnectGetPorts(pmHostSpec *) _PCP_HIDDEN; +extern int __pmAddHostPorts(__pmHostSpec *, int *, int) _PCP_HIDDEN; +extern void __pmDropHostPort(__pmHostSpec *) _PCP_HIDDEN; +extern void __pmConnectGetPorts(__pmHostSpec *) _PCP_HIDDEN; extern int __pmLogOpen(const char *, __pmContext *) _PCP_HIDDEN; extern int __pmLogReopen(const char *, __pmContext *) _PCP_HIDDEN; @@ -407,7 +407,7 @@ extern int __pmLogFetchInterp(__pmContext *, int, pmID *, pmResult **) _PCP_HIDDEN; extern int __pmGetArchiveLabel(__pmLogCtl *, pmLogLabel *) _PCP_HIDDEN; extern pmTimeval *__pmLogStartTime(__pmArchCtl *) _PCP_HIDDEN; -extern void __pmLogSetTime(__pmContext *) _PCP_HIDDEN; +extern int __pmLogSetTime(__pmContext *) _PCP_HIDDEN; extern void __pmLogResetInterp(__pmContext *) _PCP_HIDDEN; extern void __pmArchCtlFree(__pmArchCtl *) _PCP_HIDDEN; extern int __pmLogChangeArchive(__pmContext *, int) _PCP_HIDDEN; diff -Nru pcp-5.3.1/src/libpcp/src/interp.c pcp-5.3.2/src/libpcp/src/interp.c --- pcp-5.3.1/src/libpcp/src/interp.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/interp.c 2021-07-30 04:05:06.000000000 +0000 @@ -1312,7 +1312,9 @@ } /* get to the last remembered place */ - __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + sts = __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + if (sts < 0) + goto all_done; __pmFseek(ctxp->c_archctl->ac_mfp, ctxp->c_archctl->ac_offset, SEEK_SET); seen_mark = 0; /* interested in records seen from here on */ @@ -1397,7 +1399,9 @@ * at least one metric requires a bound from earlier in the log ... * position ourselves, ... and search */ - __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + sts = __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + if (sts < 0) + goto all_done; __pmFseek(ctxp->c_archctl->ac_mfp, ctxp->c_archctl->ac_offset, SEEK_SET); done = 0; @@ -1542,7 +1546,9 @@ * at least one metric requires a bound from later in the log ... * position ourselves ... and search */ - __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + sts = __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + if (sts < 0) + goto all_done; __pmFseek(ctxp->c_archctl->ac_mfp, ctxp->c_archctl->ac_offset, SEEK_SET); done = 0; diff -Nru pcp-5.3.1/src/libpcp/src/logutil.c pcp-5.3.2/src/libpcp/src/logutil.c --- pcp-5.3.1/src/libpcp/src/logutil.c 2021-04-20 00:16:37.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/logutil.c 2021-07-30 04:05:06.000000000 +0000 @@ -1992,7 +1992,9 @@ all_derived = check_all_derived(numpmid, pmidlist); /* re-establish position */ - __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + sts = __pmLogChangeVol(ctxp->c_archctl, ctxp->c_archctl->ac_vol); + if (sts < 0) + goto func_return; __pmFseek(ctxp->c_archctl->ac_mfp, (long)ctxp->c_archctl->ac_offset, SEEK_SET); @@ -2007,7 +2009,9 @@ * no serial access, so need to make sure we are * starting in the correct place */ - __pmLogSetTime(ctxp); + sts = __pmLogSetTime(ctxp); + if (sts < 0) + goto func_return; ctxp->c_archctl->ac_offset = __pmFtell(ctxp->c_archctl->ac_mfp); ctxp->c_archctl->ac_vol = ctxp->c_archctl->ac_curvol; /* @@ -2296,7 +2300,7 @@ return PM_ERR_EOL; } -void +int __pmLogSetTime(__pmContext *ctxp) { __pmArchCtl *acp = ctxp->c_archctl; @@ -2353,6 +2357,7 @@ if (lcp->l_numti) { /* we have a temporal index, use it! */ int j = -1; + int try; int toobig = 0; int match = 0; int vol; @@ -2403,9 +2408,13 @@ acp->ac_serial = 1; if (match) { + try = j; j = VolSkip(acp, mode, j); - if (j < 0) - return; + if (j < 0) { + if (pmDebugOptions.log) + fprintf(stderr, "__pmLogSetTime: VolSkip mode=%d vol=%d failed #1\n", mode, try); + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)lcp->l_ti[j].ti_log, SEEK_SET); if (mode == PM_MODE_BACK) acp->ac_serial = 0; @@ -2415,9 +2424,13 @@ } } else if (j < 1) { + try = 0; j = VolSkip(acp, PM_MODE_FORW, 0); - if (j < 0) - return; + if (j < 0) { + if (pmDebugOptions.log) + fprintf(stderr, "__pmLogSetTime: VolSkip mode=%d vol=%d failed #2\n", PM_MODE_FORW, try); + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)lcp->l_ti[j].ti_log, SEEK_SET); if (pmDebugOptions.log) { fprintf(stderr, " before start ti@"); @@ -2425,9 +2438,13 @@ } } else if (j == numti) { + try = numti-1; j = VolSkip(acp, PM_MODE_BACK, numti-1); - if (j < 0) - return; + if (j < 0) { + if (pmDebugOptions.log) + fprintf(stderr, "__pmLogSetTime: VolSkip mode=%d vol=%d failed #3\n", PM_MODE_BACK, try); + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)lcp->l_ti[j].ti_log, SEEK_SET); if (mode == PM_MODE_BACK) acp->ac_serial = 0; @@ -2447,9 +2464,13 @@ t_hi = __pmTimevalSub(&lcp->l_ti[j].ti_stamp, &ctxp->c_origin); t_lo = __pmTimevalSub(&ctxp->c_origin, &lcp->l_ti[j-1].ti_stamp); if (t_hi <= t_lo && !toobig) { + try = j; j = VolSkip(acp, mode, j); - if (j < 0) - return; + if (j < 0) { + if (pmDebugOptions.log) + fprintf(stderr, "__pmLogSetTime: VolSkip mode=%d vol=%d failed #4\n", mode, try); + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)lcp->l_ti[j].ti_log, SEEK_SET); if (mode == PM_MODE_FORW) acp->ac_serial = 0; @@ -2459,9 +2480,13 @@ } } else { + try = j-1; j = VolSkip(acp, mode, j-1); - if (j < 0) - return; + if (j < 0) { + if (pmDebugOptions.log) + fprintf(stderr, "__pmLogSetTime: VolSkip mode=%d vol=%d failed #5\n", mode, try); + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)lcp->l_ti[j].ti_log, SEEK_SET); if (mode == PM_MODE_BACK) acp->ac_serial = 0; @@ -2487,12 +2512,37 @@ } else { /* index either not available, or not useful */ + int j; if (mode == PM_MODE_FORW) { - __pmLogChangeVol(acp, lcp->l_minvol); + for (j = lcp->l_minvol; j <= lcp->l_maxvol; j++) { + if (__pmLogChangeVol(acp, j) >= 0) + break; + } + if (j > lcp->l_maxvol) { + /* no volume found */ + if (pmDebugOptions.log) + fprintf(stderr, " index not useful, no volume between %d...%d\n", + lcp->l_minvol, lcp->l_maxvol); + acp->ac_curvol = -1; + acp->ac_mfp = NULL; + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); } else if (mode == PM_MODE_BACK) { - __pmLogChangeVol(acp, lcp->l_maxvol); + for (j = lcp->l_maxvol; j >= lcp->l_minvol; j--) { + if (__pmLogChangeVol(acp, j) >= 0) + break; + } + if (j < lcp->l_minvol) { + /* no volume found */ + if (pmDebugOptions.log) + fprintf(stderr, " index not useful, no volume between %d...%d\n", + lcp->l_maxvol, lcp->l_minvol); + acp->ac_curvol = -1; + acp->ac_mfp = NULL; + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)0, SEEK_END); } @@ -2508,6 +2558,8 @@ acp->ac_offset = __pmFtell(acp->ac_mfp); assert(acp->ac_offset >= 0); acp->ac_vol = acp->ac_curvol; + + return 0; } /* Read the label of the current archive. */ @@ -3095,6 +3147,7 @@ pmTimeval save_origin; int save_mode; int sts; + int j; /* * Check whether there is a previous archive to switch to. @@ -3140,11 +3193,23 @@ } /* Set up to scan backwards from the end of the archive. */ - __pmLogChangeVol(acp, lcp->l_maxvol); + for (j = lcp->l_maxvol; j >= lcp->l_minvol; j--) { + if (__pmLogChangeVol(acp, j) >= 0) + break; + } + if (j < lcp->l_minvol) { + /* no volume found */ + if (pmDebugOptions.log) + fprintf(stderr, "LogChangeToPreviousArchive: no volume between %d...%d\n", + lcp->l_maxvol, lcp->l_minvol); + acp->ac_curvol = -1; + acp->ac_mfp = NULL; + return PM_ERR_LOGFILE; + } __pmFseek(acp->ac_mfp, (long)0, SEEK_END); - ctxp->c_archctl->ac_offset = __pmFtell(acp->ac_mfp); - assert(ctxp->c_archctl->ac_offset >= 0); - ctxp->c_archctl->ac_vol = ctxp->c_archctl->ac_curvol; + acp->ac_offset = __pmFtell(acp->ac_mfp); + assert(acp->ac_offset >= 0); + acp->ac_vol = acp->ac_curvol; /* * Check for temporal overlap here. Do this last in case the API client diff -Nru pcp-5.3.1/src/libpcp/src/mk.pmdbg pcp-5.3.2/src/libpcp/src/mk.pmdbg --- pcp-5.3.1/src/libpcp/src/mk.pmdbg 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/mk.pmdbg 2021-07-30 04:05:06.000000000 +0000 @@ -30,10 +30,14 @@ # 3. $ sudo make install # 4. $ cd ../../pmdbg # $ make clean +# $ make # $ ./pmdbg -l # - Check new flag appears # $ sudo make install -# 5. $ cd ../../qa +# 5. $ cd ../pmdbg +# $ make clean +# $ sudo make install +# 6. $ cd ../../qa # $ ./check -g pmdbg # - Expect that at least 1277, 1278 and 1359 will need to be remade # diff -Nru pcp-5.3.1/src/libpcp/src/spec.c pcp-5.3.2/src/libpcp/src/spec.c --- pcp-5.3.1/src/libpcp/src/spec.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/spec.c 2021-06-15 01:03:49.000000000 +0000 @@ -343,14 +343,14 @@ return s; } -static pmHostSpec * -hostAdd(pmHostSpec *specp, int *count, const char *name, int namelen) +static __pmHostSpec * +hostAdd(__pmHostSpec *specp, int *count, const char *name, int namelen) { int n = *count; char *host; host = hostStrndup(name, namelen); - if (!host || (specp = realloc(specp, sizeof(pmHostSpec) * (n+1))) == NULL) { + if (!host || (specp = realloc(specp, sizeof(__pmHostSpec) * (n+1))) == NULL) { if (host != NULL) free(host); *count = 0; @@ -365,7 +365,7 @@ } int -__pmAddHostPorts(pmHostSpec *specp, int *ports, int nports) +__pmAddHostPorts(__pmHostSpec *specp, int *ports, int nports) { int *portlist; @@ -382,7 +382,7 @@ } void -__pmDropHostPort(pmHostSpec *specp) +__pmDropHostPort(__pmHostSpec *specp) { specp->nports--; memmove(&specp->ports[0], &specp->ports[1], specp->nports*sizeof(int)); @@ -421,11 +421,11 @@ parseHostSpec( const char *spec, char **position, /* parse this string, return end char */ - pmHostSpec **rslt, /* result allocated and returned here */ + __pmHostSpec **rslt, /* result allocated and returned here */ int *count, char **errmsg) /* error message */ { - pmHostSpec *hsp = NULL; + __pmHostSpec *hsp = NULL; const char *s, *start, *next; int nhosts = 0, sts = 0; @@ -511,9 +511,9 @@ parseSocketPath( const char *spec, char **position, /* parse this string, return end char */ - pmHostSpec **rslt) /* result allocated and returned here */ + __pmHostSpec **rslt) /* result allocated and returned here */ { - pmHostSpec *hsp = NULL; + __pmHostSpec *hsp = NULL; const char *s, *start, *path; char absolute_path[MAXPATHLEN]; size_t len; @@ -570,7 +570,7 @@ int __pmParseHostSpec( const char *spec, /* parse this string */ - pmHostSpec **rslt, /* result allocated and returned here */ + __pmHostSpec **rslt, /* result allocated and returned here */ int *count, /* number of host specs returned here */ char **errmsg) /* error message */ { @@ -591,7 +591,7 @@ } static int -unparseHostSpec(pmHostSpec *hostp, int count, char *string, size_t size, int prefix) +unparseHostSpec(__pmHostSpec *hostp, int count, char *string, size_t size, int prefix) { int off = 0, len = size; /* offset in string and space remaining */ int i, j, sts; @@ -656,13 +656,13 @@ } int -__pmUnparseHostSpec(pmHostSpec *hostp, int count, char *string, size_t size) +__pmUnparseHostSpec(__pmHostSpec *hostp, int count, char *string, size_t size) { return unparseHostSpec(hostp, count, string, size, 1); } void -__pmFreeHostSpec(pmHostSpec *specp, int count) +__pmFreeHostSpec(__pmHostSpec *specp, int count) { int i; @@ -694,7 +694,7 @@ } void -__pmFreeHostAttrsSpec(pmHostSpec *hosts, int count, __pmHashCtl *attrs) +__pmFreeHostAttrsSpec(__pmHostSpec *hosts, int count, __pmHashCtl *attrs) { __pmFreeHostSpec(hosts, count); __pmFreeAttrsSpec(attrs); @@ -903,7 +903,7 @@ int __pmParseHostAttrsSpec( const char *spec, /* the original, complete string to parse */ - pmHostSpec **host, /* hosts result allocated and returned here */ + __pmHostSpec **host, /* hosts result allocated and returned here */ int *count, __pmHashCtl *attributes, char **errmsg) /* error message */ @@ -1043,7 +1043,7 @@ int __pmUnparseHostAttrsSpec( - pmHostSpec *hosts, + __pmHostSpec *hosts, int count, __pmHashCtl *attrs, char *string, diff -Nru pcp-5.3.1/src/libpcp/src/tz.c pcp-5.3.2/src/libpcp/src/tz.c --- pcp-5.3.1/src/libpcp/src/tz.c 2020-12-17 22:46:06.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/tz.c 2021-07-30 04:05:06.000000000 +0000 @@ -108,6 +108,9 @@ PM_ASSERT_IS_LOCKED(__pmLock_extcall); + if (pmDebugOptions.context) + fprintf(stderr, "__pmSquashTZ(%s)", tzbuffer); + tzset(); t = localtime(&now); /* THREADSAFE */ @@ -151,6 +154,8 @@ strncpy(tzbuffer, tzn, PM_TZ_MAXLEN); tzbuffer[PM_TZ_MAXLEN] = '\0'; } + if (pmDebugOptions.context) + fprintf(stderr, " -> %s\n", tzbuffer); setenv("TZ", tzbuffer, 1); /* THREADSAFE */ return; @@ -177,6 +182,9 @@ wchar_t *src; div_t d; + if (pmDebugOptions.context) + fprintf(stderr, "__pmSquashTZ(%s)", tzbuffer); + GetTimeZoneInformation(&tz); dst = cp = tzbuf; off = tzoff; @@ -260,6 +268,8 @@ tzn = tzname[(t->tm_isdst > 0)]; pmsprintf(tzbuffer, PM_TZ_MAXLEN, "%s%s", tzn, tzoff); + if (pmDebugOptions.context) + fprintf(stderr, " -> %s\n", tzbuffer); setenv("TZ", tzbuffer, 1); /* THREADSAFE */ return; diff -Nru pcp-5.3.1/src/libpcp/src/util.c pcp-5.3.2/src/libpcp/src/util.c --- pcp-5.3.1/src/libpcp/src/util.c 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/libpcp/src/util.c 2021-07-30 04:05:06.000000000 +0000 @@ -1150,9 +1150,8 @@ pmNoMem(const char *where, size_t size, int fatal) { char errmsg[PM_MAXERRMSGLEN]; - pmNotifyErr(fatal ? LOG_ERR : LOG_WARNING, - "%s: malloc(%d) failed: %s", - where, (int)size, osstrerror_r(errmsg, sizeof(errmsg))); + pmNotifyErr(fatal ? LOG_ERR : LOG_WARNING, "%s: malloc(%zu) failed: %s", + where, size, osstrerror_r(errmsg, sizeof(errmsg))); if (fatal == PM_FATAL_ERR) exit(1); } diff -Nru pcp-5.3.1/src/libpcp_import/src/stuff.c pcp-5.3.2/src/libpcp_import/src/stuff.c --- pcp-5.3.1/src/libpcp_import/src/stuff.c 2018-05-11 02:15:56.000000000 +0000 +++ pcp-5.3.2/src/libpcp_import/src/stuff.c 2021-07-30 04:05:06.000000000 +0000 @@ -39,13 +39,10 @@ if (current->result == NULL) { /* first time */ - current->result = (pmResult *)malloc(sizeof(pmResult)); + current->result = (pmResult *)calloc(1, sizeof(pmResult)); if (current->result == NULL) { - pmNoMem("_pmi_stuff_value: result malloc:", sizeof(pmResult), PM_FATAL_ERR); + pmNoMem("_pmi_stuff_value: result calloc", sizeof(pmResult), PM_FATAL_ERR); } - current->result->numpmid = 0; - current->result->timestamp.tv_sec = 0; - current->result->timestamp.tv_usec = 0; } rp = current->result; @@ -60,19 +57,26 @@ } if (i == rp->numpmid) { rp->numpmid++; - size = sizeof(pmResult) + (rp->numpmid - 1)*sizeof(pmValueSet *); + size = sizeof(pmResult) + (rp->numpmid-1)*sizeof(pmValueSet *); rp = current->result = (pmResult *)realloc(current->result, size); if (current->result == NULL) { - pmNoMem("_pmi_stuff_value: result realloc:", size, PM_FATAL_ERR); + pmNoMem("_pmi_stuff_value: result realloc", size, PM_FATAL_ERR); } rp->vset[rp->numpmid-1] = (pmValueSet *)malloc(sizeof(pmValueSet)); if (rp->vset[rp->numpmid-1] == NULL) { - pmNoMem("_pmi_stuff_value: vset alloc:", sizeof(pmValueSet), PM_FATAL_ERR); + pmNoMem("_pmi_stuff_value: vset alloc", sizeof(pmValueSet), PM_FATAL_ERR); } vsp = rp->vset[rp->numpmid-1]; vsp->pmid = pmid; vsp->numval = 1; } + else if (rp->vset[i]->numval < 0) { + /* + * This metric is already under an error condition - do + * not attempt to add additional instances / values now. + */ + return rp->vset[i]->numval; + } else { int j; for (j = 0; j < rp->vset[i]->numval; j++) { @@ -84,7 +88,7 @@ size = sizeof(pmValueSet) + (rp->vset[i]->numval-1)*sizeof(pmValue); vsp = rp->vset[i] = (pmValueSet *)realloc(rp->vset[i], size); if (rp->vset[i] == NULL) { - pmNoMem("_pmi_stuff_value: vset realloc:", size, PM_FATAL_ERR); + pmNoMem("_pmi_stuff_value: vset realloc", size, PM_FATAL_ERR); } } vp = &vsp->vlist[vsp->numval-1]; @@ -92,75 +96,82 @@ dsize = -1; switch (mp->desc.type) { case PM_TYPE_32: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_INSITU; vp->value.lval = (__int32_t)strtol(value, &end, 10); if (*end != '\0') { - vsp->numval = PM_ERR_CONV; + if (vsp->numval == 1) vsp->numval = PM_ERR_CONV; + else rp->vset[i]->numval--; return PM_ERR_CONV; } + if (vsp->numval == 1) vsp->valfmt = PM_VAL_INSITU; break; case PM_TYPE_U32: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_INSITU; vp->value.lval = (__uint32_t)strtoul(value, &end, 10); if (*end != '\0') { - vsp->numval = PM_ERR_CONV; + if (vsp->numval == 1) vsp->numval = PM_ERR_CONV; + else rp->vset[i]->numval--; return PM_ERR_CONV; } + if (vsp->numval == 1) vsp->valfmt = PM_VAL_INSITU; break; case PM_TYPE_64: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; ll = strtoint64(value, &end, 10); if (*end != '\0') { - vsp->numval = PM_ERR_CONV; + if (vsp->numval == 1) vsp->numval = PM_ERR_CONV; + else rp->vset[i]->numval--; return PM_ERR_CONV; } dsize = sizeof(ll); data = (void *)≪ + if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; break; case PM_TYPE_U64: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; ull = strtouint64(value, &end, 10); if (*end != '\0') { - vsp->numval = PM_ERR_CONV; + if (vsp->numval == 1) vsp->numval = PM_ERR_CONV; + else rp->vset[i]->numval--; return PM_ERR_CONV; } dsize = sizeof(ull); data = (void *)&ull; + if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; break; case PM_TYPE_FLOAT: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; f = strtof(value, &end); if (*end != '\0') { - vsp->numval = PM_ERR_CONV; + if (vsp->numval == 1) vsp->numval = PM_ERR_CONV; + else rp->vset[i]->numval--; return PM_ERR_CONV; } dsize = sizeof(f); data = (void *)&f; + if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; break; case PM_TYPE_DOUBLE: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; d = strtod(value, &end); if (*end != '\0') { - vsp->numval = PM_ERR_CONV; + if (vsp->numval == 1) vsp->numval = PM_ERR_CONV; + else rp->vset[i]->numval--; return PM_ERR_CONV; } dsize = sizeof(d); data = (void *)&d; + if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; break; case PM_TYPE_STRING: - if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; dsize = strlen(value)+1; data = (void *)value; + if (vsp->numval == 1) vsp->valfmt = PM_VAL_DPTR; break; default: - vsp->numval = PM_ERR_TYPE; + if (vsp->numval == 1) vsp->numval = PM_ERR_TYPE; + else rp->vset[i]->numval--; return PM_ERR_TYPE; } @@ -170,7 +181,7 @@ vp->value.pval = (pmValueBlock *)malloc(need < sizeof(pmValueBlock) ? sizeof(pmValueBlock) : need); if (vp->value.pval == NULL) { - pmNoMem("_pmi_stuff_value: pmValueBlock:", need < sizeof(pmValueBlock) ? sizeof(pmValueBlock) : need, PM_FATAL_ERR); + pmNoMem("_pmi_stuff_value: pmValueBlock", need < sizeof(pmValueBlock) ? sizeof(pmValueBlock) : need, PM_FATAL_ERR); } vp->value.pval->vlen = (int)need; vp->value.pval->vtype = mp->desc.type; diff -Nru pcp-5.3.1/src/libpcp_web/src/discover.c pcp-5.3.2/src/libpcp_web/src/discover.c --- pcp-5.3.1/src/libpcp_web/src/discover.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/discover.c 2021-07-30 04:05:06.000000000 +0000 @@ -33,9 +33,6 @@ #define PM_DISCOVER_HASHTAB_SIZE 32 static pmDiscover *discover_hashtable[PM_DISCOVER_HASHTAB_SIZE]; -/* pmlogger_daily log-roll lock count */ -static int logrolling = 0; - /* number of archives or directories currently being monitored */ static int n_monitored = 0; @@ -426,28 +423,6 @@ return ret; } -static int -check_for_locks() -{ - int i; - pmDiscover *p; - char sep = pmPathSeparator(); - char path[MAXNAMELEN]; - - for (i=0; i < PM_DISCOVER_HASHTAB_SIZE; i++) { - for (p = discover_hashtable[i]; p; p = p->next) { - if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { - pmsprintf(path, sizeof(path), "%s%c%s", p->context.name, sep, "lock"); - if (access(path, F_OK) == 0) - return 1; - } - } - } - - /* no locks */ - return 0; -} - static void check_deleted(pmDiscover *p) { @@ -465,37 +440,8 @@ pmDiscover *p; char *s; sds path; - int locksfound = 0; struct stat statbuf; - /* - * check if logs are currently being rolled by pmlogger_daily et al - * in any of the directories we are tracking. For mutex, the log control - * scripts use a 'lock' file in each directory as it is processed. - */ - locksfound = check_for_locks(); - - if (!logrolling && locksfound) { - /* log-rolling has started */ - if (pmDebugOptions.discovery) - fprintf(stderr, "%s discovery callback: log-rolling in progress\n", stamp()); - logrolling = locksfound; - return; - } - - if (logrolling && locksfound) { - logrolling = locksfound; - return; /* still in progress */ - } - - if (logrolling && !locksfound) { - /* log-rolling is finished: check what got deleted, and then purge */ - if (pmDebugOptions.discovery) - fprintf(stderr, "%s discovery callback: finished log-rolling\n", stamp()); - pmDiscoverTraverse(PM_DISCOVER_FLAGS_META|PM_DISCOVER_FLAGS_DATAVOL, check_deleted); - } - logrolling = locksfound; - uv_fs_event_getpath(handle, buffer, &bytes); path = sdsnewlen(buffer, bytes); @@ -1037,6 +983,17 @@ pmDiscoverInvokeSourceCallBacks(p, ×tamp); } +static char * +archive_dir_lock_path(pmDiscover *p) +{ + char path[MAXNAMELEN], lockpath[MAXNAMELEN]; + int sep = pmPathSeparator(); + + strncpy(path, p->context.name, sizeof(path)-1); + pmsprintf(lockpath, sizeof(lockpath), "%s%c%s", dirname(path), sep, "lock"); + return strndup(lockpath, sizeof(lockpath)); +} + /* * Process metadata records until EOF. That can span multiple * callbacks if we get a partial record read. @@ -1059,6 +1016,7 @@ __pmLogHdr hdr; sds msg, source; static uint32_t *buf = NULL; + char *lock_path; int deleted; struct stat sbuf; static int buflen = 0; @@ -1073,7 +1031,10 @@ fprintf(stderr, "process_metadata: %s in progress %s\n", p->context.name, pmDiscoverFlagsStr(p)); pmDiscoverStatsAdd(p->module, "metadata.callbacks", NULL, 1); + lock_path = archive_dir_lock_path(p); for (;;) { + if (lock_path && access(lock_path, F_OK) == 0) + break; pmDiscoverStatsAdd(p->module, "metadata.loops", NULL, 1); off = lseek(p->fd, 0, SEEK_CUR); nb = read(p->fd, &hdr, sizeof(__pmLogHdr)); @@ -1090,6 +1051,7 @@ /* rewind so we can wait for more data on the next change CallBack */ lseek(p->fd, off, SEEK_SET); partial = 1; + pmDiscoverStatsAdd(p->module, "metadata.partial_reads", NULL, 1); continue; } @@ -1099,6 +1061,7 @@ /* rewind and wait for more data, as above */ lseek(p->fd, off, SEEK_SET); partial = 1; + pmDiscoverStatsAdd(p->module, "metadata.partial_reads", NULL, 1); continue; } @@ -1121,6 +1084,7 @@ /* rewind and wait for more data, as above */ lseek(p->fd, off, SEEK_SET); partial = 1; + pmDiscoverStatsAdd(p->module, "metadata.partial_reads", NULL, 1); continue; } @@ -1240,6 +1204,9 @@ /* flag that all available metadata has now been read */ p->flags &= ~PM_DISCOVER_FLAGS_META_IN_PROGRESS; + if (lock_path) + free(lock_path); + if (pmDebugOptions.discovery) fprintf(stderr, "%s: completed, partial=%d %s %s\n", "process_metadata", partial, p->context.name, pmDiscoverFlagsStr(p)); @@ -1266,14 +1233,18 @@ process_logvol(pmDiscover *p) { int sts; - pmResult *r; + pmResult *r = NULL; pmTimespec ts; int oldcurvol; __pmContext *ctxp; __pmArchCtl *acp; + char *lock_path; pmDiscoverStatsAdd(p->module, "logvol.callbacks", NULL, 1); + lock_path = archive_dir_lock_path(p); for (;;) { + if (lock_path && access(lock_path, F_OK) == 0) + break; pmDiscoverStatsAdd(p->module, "logvol.loops", NULL, 1); pmUseContext(p->ctx); ctxp = __pmHandleToPtr(p->ctx); @@ -1312,6 +1283,7 @@ } /* we are done - return and wait for another callback */ + r = NULL; break; } @@ -1328,14 +1300,15 @@ } /* - * TODO: persistently save current timestamp, so after being restarted, - * pmproxy can resume where it left off for each archive. + * TODO (perhaps): persistently save current timestamp, so after being + * restarted, pmproxy can resume where it left off for each archive. */ ts.tv_sec = r->timestamp.tv_sec; ts.tv_nsec = r->timestamp.tv_usec * 1000; bump_logvol_decode_stats(p, r); pmDiscoverInvokeValuesCallBack(p, &ts, r); pmFreeResult(r); + r = NULL; } if (r) { @@ -1348,6 +1321,9 @@ /* datavol is now up-to-date and at EOF */ p->flags &= ~PM_DISCOVER_FLAGS_DATAVOL_READY; + + if (lock_path) + free(lock_path); } static void @@ -1357,6 +1333,10 @@ sds msg; sds metaname; + check_deleted(p); + if (p->flags & PM_DISCOVER_FLAGS_DELETED) + return; /* ignore deleted archive */ + if (p->ctx < 0) { /* * once off initialization on the first event @@ -1366,16 +1346,23 @@ /* create the PMAPI context (once off) */ if ((sts = pmNewContext(p->context.type, p->context.name)) < 0) { - /* - * Likely an early callback on a new (still empty) archive. - * If so, just ignore the callback and don't log any scary - * looking messages. We'll get another CB soon. - */ - if (sts != PM_ERR_NODATA || pmDebugOptions.desperate) { - infofmt(msg, "pmNewContext failed for %s: %s\n", - p->context.name, pmErrStr(sts)); - moduleinfo(p->module, PMLOG_ERROR, msg, p->data); + if (sts == -ENOENT) { + /* newly deleted archive */ + p->flags |= PM_DISCOVER_FLAGS_DELETED; } + else { + /* + * Likely an early callback on a new (still empty) archive. + * If so, just ignore the callback and don't log any scary + * looking messages. We'll get another CB soon. + */ + if (sts != PM_ERR_NODATA || pmDebugOptions.desperate) { + infofmt(msg, "pmNewContext failed for %s: %s\n", + p->context.name, pmErrStr(sts)); + moduleinfo(p->module, PMLOG_ERROR, msg, p->data); + } + } + /* no further processing for this archive */ return; } pmDiscoverStatsAdd(p->module, "logvol.new_contexts", NULL, 1); @@ -1410,8 +1397,12 @@ metaname = sdsnew(p->context.name); metaname = sdscat(metaname, ".meta"); if ((p->fd = open(metaname, O_RDONLY)) < 0) { - infofmt(msg, "open failed for %s: %s\n", metaname, osstrerror()); - moduleinfo(p->module, PMLOG_ERROR, msg, p->data); + if (p->fd == -ENOENT) + p->flags |= PM_DISCOVER_FLAGS_DELETED; + else { + infofmt(msg, "open failed for %s: %s\n", metaname, osstrerror()); + moduleinfo(p->module, PMLOG_ERROR, msg, p->data); + } sdsfree(metaname); return; } diff -Nru pcp-5.3.1/src/libpcp_web/src/exports pcp-5.3.2/src/libpcp_web/src/exports --- pcp-5.3.1/src/libpcp_web/src/exports 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/exports 2021-07-30 04:05:06.000000000 +0000 @@ -228,3 +228,10 @@ redisSlotsSetupMetrics; redisSlotsSetMetricRegistry; } PCP_WEB_1.15; + +PCP_WEB_1.17 { + global: + pmWebTimerSetMetricRegistry; + pmWebTimerRegister; + pmWebTimerRelease; +} PCP_WEB_1.16; diff -Nru pcp-5.3.1/src/libpcp_web/src/GNUmakefile pcp-5.3.2/src/libpcp_web/src/GNUmakefile --- pcp-5.3.1/src/libpcp_web/src/GNUmakefile 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -51,7 +51,7 @@ LCFLAGS += $(C99_CFLAGS) -DJSMN_PARENT_LINKS=1 -DJSMN_STRICT=1 -DHTTP_PARSER_STRICT=0 -Ideps ifeq "$(HAVE_LIBUV)" "true" -CFILES += discover.c webgroup.c +CFILES += discover.c webgroup.c timer.c LCFLAGS += $(LIBUVCFLAGS) -DHAVE_LIBUV=1 LLDLIBS += $(LIB_FOR_LIBUV) else diff -Nru pcp-5.3.1/src/libpcp_web/src/load.c pcp-5.3.2/src/libpcp_web/src/load.c --- pcp-5.3.1/src/libpcp_web/src/load.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/load.c 2021-07-30 04:05:06.000000000 +0000 @@ -924,14 +924,24 @@ } static void -setup_source_services(void *arg) +setup_pmapi_source_service(void *arg) { seriesLoadBaton *baton = (seriesLoadBaton *)arg; - seriesBatonCheckMagic(baton, MAGIC_LOAD, "setup_source_services"); - seriesBatonReferences(baton, 2, "setup_source_services"); + seriesBatonCheckMagic(baton, MAGIC_LOAD, "setup_pmapi_source_service"); + seriesBatonReferences(baton, 1, "setup_pmapi_source_service"); connect_pmapi_source_service(baton); +} + +static void +setup_redis_source_service(void *arg) +{ + seriesLoadBaton *baton = (seriesLoadBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_LOAD, "setup_redis_source_service"); + seriesBatonReferences(baton, 1, "setup_redis_source_service"); + connect_redis_source_service(baton); } @@ -1014,7 +1024,9 @@ /* ordering of async operations */ i = 0; baton->current = &baton->phases[i]; - baton->phases[i++].func = setup_source_services; + /* Coverity CID341699 - split pmapi and redis setup to avoid use after free */ + baton->phases[i++].func = setup_pmapi_source_service; + baton->phases[i++].func = setup_redis_source_service; /* assign source/host string map (series_source_mapping) */ baton->phases[i++].func = series_source_mapping; /* write source info into schema (series_cache_source) */ @@ -1303,6 +1315,12 @@ if (pmDebugOptions.discovery) fprintf(stderr, "%s: result numpmids=%d\n", "pmSeriesDiscoverValues", result->numpmid); + if (data == NULL) { + /* calloc failed in getDiscoverModuleData() */ + baton->error = -ENOMEM; + return; + } + if (baton == NULL || baton->slots == NULL || baton->slots->setup == 0) return; @@ -1335,12 +1353,14 @@ infofmt(msg, "%s: failed indom discovery (domain %u)", "pmSeriesDiscoverInDom", pmInDom_domain(id)); moduleinfo(event->module, PMLOG_ERROR, msg, arg); + baton->error = -ENOMEM; return; } if ((indom = pmwebapi_add_indom(context, domain, id)) == NULL) { infofmt(msg, "%s: failed indom discovery (indom %s)", "pmSeriesDiscoverInDom", pmInDomStr(id)); moduleinfo(event->module, PMLOG_ERROR, msg, arg); + baton->error = -ENOMEM; return; } for (i = 0; i < in->numinst; i++) { @@ -1350,6 +1370,8 @@ "pmSeriesDiscoverInDom", pmInDomStr(id), in->instlist[i], in->namelist[i]); moduleinfo(event->module, PMLOG_ERROR, msg, arg); + /* Coverity CID:328046 - resource leak from earlier pmwebapi_add_instance calls. */ + baton->error = -ENOMEM; return; } } diff -Nru pcp-5.3.1/src/libpcp_web/src/maps.c pcp-5.3.2/src/libpcp_web/src/maps.c --- pcp-5.3.1/src/libpcp_web/src/maps.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/maps.c 2021-07-30 04:05:06.000000000 +0000 @@ -160,6 +160,12 @@ void redisMapInsert(redisMap *map, sds key, sds value) { + redisMapEntry *entry = redisMapLookup(map, key); + + if (entry) { + /* fix for Coverity CID323605 Resource Leak */ + dictDelete(map, key); + } dictAdd(map, key, value); } diff -Nru pcp-5.3.1/src/libpcp_web/src/nowebgroup.c pcp-5.3.2/src/libpcp_web/src/nowebgroup.c --- pcp-5.3.1/src/libpcp_web/src/nowebgroup.c 2019-10-11 02:20:53.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/nowebgroup.c 2021-07-30 04:05:06.000000000 +0000 @@ -103,3 +103,24 @@ { (void)module; } + +int +pmWebTimerSetMetricRegistry(struct mmv_registry *registry) +{ + (void)registry; + return -EOPNOTSUPP; +} + +int +pmWebTimerRegister(pmWebTimerCallBack callback, void *data) +{ + (void)data; (void)callback; + return -EOPNOTSUPP; +} + +int +pmWebTimerRelease(int seq) +{ + (void)seq; + return -EOPNOTSUPP; +} diff -Nru pcp-5.3.1/src/libpcp_web/src/query.c pcp-5.3.2/src/libpcp_web/src/query.c --- pcp-5.3.1/src/libpcp_web/src/query.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/query.c 2021-07-30 04:05:06.000000000 +0000 @@ -201,6 +201,11 @@ { seriesModuleData *data = getSeriesModuleData(&settings->module); + if (data == NULL) { + /* calloc failed in getSeriesModuleData */ + baton->error = -ENOMEM; + return; + } initSeriesBatonMagic(baton, MAGIC_QUERY); baton->callbacks = &settings->callbacks; baton->info = settings->module.on_info; @@ -995,6 +1000,7 @@ infofmt(msg, "out of memory (%s, %" FMT_INT64 " bytes)", "pattern reply", (__int64_t)bytes); batoninfo(baton, PMLOG_REQUEST, msg); + sdsfree(key); /* Coverity CID328038 */ return -ENOMEM; } matches[np->nmatches++] = key; @@ -1645,11 +1651,14 @@ /* calloc nseries samples store space */ if ((np->value_set.series_values = (series_sample_set_t *)calloc(nseries, sizeof(series_sample_set_t))) == NULL) { - /* TODO: error report here */ baton->error = -ENOMEM; + return; } for (i = 0; i < nseries; i++, series += SHA1SZ) { - sid = calloc(1, sizeof(seriesGetSID)); + if ((sid = (seriesGetSID *)calloc(1, sizeof(seriesGetSID))) == NULL) { + baton->error = -ENOMEM; + return; + } pmwebapi_hash_str(series, hashbuf, sizeof(hashbuf)); initSeriesGetSID(sid, hashbuf, 1, baton); np->value_set.series_values[i].baton = baton; @@ -2207,8 +2216,10 @@ /* calloc nseries samples store space */ if ((np->value_set.series_values = (series_sample_set_t *)calloc(nseries, sizeof(series_sample_set_t))) == NULL) { - /* TODO: error report here */ baton->error = -ENOMEM; + sdsfree(start); + sdsfree(end); + return; } /* @@ -3641,8 +3652,10 @@ series_extract_value(*otype, l_data->data, l_val); /* Convert scale to larger one */ - pmConvScale(*otype, l_val, l_units, l_val, large_units); - pmConvScale(*otype, r_val, r_units, r_val, large_units); + if (pmConvScale(*otype, l_val, l_units, l_val, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); + if (pmConvScale(*otype, r_val, r_units, r_val, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); if ((*operator)(otype, l_val, r_val, &res) != 0) { sdsfree(l_data->data); @@ -3911,9 +3924,7 @@ return 0; if ((sts = series_calculate(baton, np->left, level+1)) < 0) return sts; - if (sts > 0) - series_calculate(baton, np->right, level+1); - else if ((sts = series_calculate(baton, np->right, level+1)) < 0) + if ((sts = series_calculate(baton, np->right, level+1)) < 0) return sts; np->baton = baton; @@ -4014,7 +4025,8 @@ for (j = 0; j < set0->num_samples; j++) { for (k = 0; k < set0->series_sample[j].num_instances; k++) { series_extract_value(type0, set0->series_sample[j].series_instance[k].data, &val0); - pmConvScale(type0, &val0, units0, &val0, large_units); + if (pmConvScale(type0, &val0, units0, &val0, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); sdsfree(set0->series_sample[j].series_instance[k].data); str_len = series_pmAtomValue_conv_str(type0, str_val, &val0, sizeof(str_val)); set0->series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); @@ -4032,7 +4044,8 @@ for (j = 0; j < set1->num_samples; j++) { for (k = 0; k < set1->series_sample[j].num_instances; k++) { series_extract_value(type1, set1->series_sample[j].series_instance[k].data, &val1); - pmConvScale(type1, &val1, units1, &val1, large_units); + if (pmConvScale(type1, &val1, units1, &val1, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); sdsfree(set1->series_sample[j].series_instance[k].data); str_len = series_pmAtomValue_conv_str(type1, str_val, &val1, sizeof(str_val)); set1->series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); @@ -4073,12 +4086,36 @@ baton->error = -EPROTO; continue; } + + if (strncmp(np->value_set.series_values[i].series_desc.units, "none", 4) == 0) + memset(&units0, 0, sizeof(units0)); + else if (pmParseUnitsStr(np->value_set.series_values[i].series_desc.units, + &units0, &mult, &errmsg) != 0) { + np->value_set.series_values[i].compatibility = 0; + infofmt(msg, "Invalid units string: %s\n", + np->value_set.series_values[i].series_desc.units); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + free(errmsg); + break; + } + for (j = 0; j < num_series; j++) { if (!np->value_set.series_values[j].compatibility || i == j) continue; - pmParseUnitsStr(np->value_set.series_values[i].series_desc.units, &units0, &mult, &errmsg); - pmParseUnitsStr(np->value_set.series_values[j].series_desc.units, &units1, &mult, &errmsg); + if (strncmp(np->value_set.series_values[j].series_desc.units, "none", 4) == 0) + memset(&units1, 0, sizeof(units1)); + else if (pmParseUnitsStr(np->value_set.series_values[j].series_desc.units, + &units1, &mult, &errmsg) != 0) { + np->value_set.series_values[j].compatibility = 0; + infofmt(msg, "Invalid units string: %s\n", + np->value_set.series_values[j].series_desc.units); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + free(errmsg); + break; + } if (check_compatibility(&units0, &units1) != 0) { np->value_set.series_values[j].compatibility = 0; @@ -4233,6 +4270,11 @@ seriesQueryBaton *baton; unsigned int i = 0; + if (root == NULL) { + /* Coverity CID366052 */ + return -ENOMEM; + } + if ((baton = calloc(1, sizeof(seriesQueryBaton))) == NULL) return -ENOMEM; initSeriesQueryBaton(baton, settings, arg); @@ -4554,6 +4596,8 @@ infofmt(msg, "%s - label value lookup OOM", series); batoninfo(baton, PMLOG_ERROR, msg); sts = -ENOMEM; + if (vmap) /* Coverity CID308763 */ + redisMapRelease(vmap); continue; } initSeriesGetLabelMap(labelmap, series, name, vmap, vmapID, vkey, baton); @@ -4949,6 +4993,7 @@ if (extract_sha1(baton, series, elements[i], &sid->name, "series") < 0) { /* TODO: report error */ + freeSeriesGetSID(sid); /* Coverity CID308764 */ continue; } seriesBatonReference(sid, "series_instances_reply"); diff -Nru pcp-5.3.1/src/libpcp_web/src/query.c.orig pcp-5.3.2/src/libpcp_web/src/query.c.orig --- pcp-5.3.1/src/libpcp_web/src/query.c.orig 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/query.c.orig 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,5559 @@ +/* + * Copyright (c) 2017-2021 Red Hat. + * Copyright (c) 2020 Yushan ZHANG. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ + +#include +#include +#include "util.h" +#include "sha1.h" +#include "query.h" +#include "schema.h" +#include "libpcp.h" +#include "slots.h" +#include "maps.h" +#include +#include + +#define SHA1SZ 20 /* internal sha1 hash buffer size in bytes */ +#define QUERY_PHASES 8 + + +typedef struct seriesGetLabelMap { + seriesBatonMagic header; /* MAGIC_LABELMAP */ + redisMap *map; + sds series; + sds name; + sds mapID; + sds mapKey; + void *baton; +} seriesGetLabelMap; + +typedef struct seriesGetLookup { + redisMap *map; + pmSeriesStringCallBack func; + sds pattern; + unsigned int nseries; + seriesGetSID series[0]; +} seriesGetLookup; + +typedef struct seriesGetQuery { + node_t root; + timing_t timing; +} seriesGetQuery; + +typedef struct seriesQueryBaton { + seriesBatonMagic header; /* MAGIC_QUERY */ + seriesBatonPhase *current; + seriesBatonPhase phases[QUERY_PHASES]; + pmSeriesModule *module; + pmSeriesCallBacks *callbacks; + pmLogInfoCallBack info; + void *userdata; + redisSlots *slots; + int error; + union { + seriesGetLookup lookup; + seriesGetQuery query; + } u; +} seriesQueryBaton; + +static void series_pattern_match(seriesQueryBaton *, node_t *); +static int series_union(series_set_t *, series_set_t *); +static int series_intersect(series_set_t *, series_set_t *); +static int series_calculate(seriesQueryBaton *, node_t *, int); +static void series_redis_hash_expression(seriesQueryBaton *, char *, int); +static void series_node_get_metric_name(seriesQueryBaton *, seriesGetSID *, series_sample_set_t *); +static void series_node_get_desc(seriesQueryBaton *, sds, series_sample_set_t *); +static void series_lookup_services(void *); +static void series_lookup_mapping(void *); +static void series_lookup_finished(void *); +static void series_query_mapping(void *arg); +static void series_instances_reply_callback(redisClusterAsyncContext *, void *, void *); + +sds cursorcount; /* number of elements in each SCAN call */ + +static void +initSeriesGetQuery(seriesQueryBaton *baton, node_t *root, timing_t *timing) +{ + seriesBatonCheckMagic(baton, MAGIC_QUERY, "initSeriesGetQuery"); + baton->u.query.root = *root; + baton->u.query.timing = *timing; +} + +static int +skip_free_value_set(node_t *np) +{ + /* return 0 stands for skipping free this node's value_set. */ + if (np->type == N_RATE || np->type == N_RESCALE || np->type == N_ABS + || np->type == N_SQRT || np->type == N_FLOOR || np->type == N_ROUND + || np->type == N_LOG || np->type == N_PLUS || np->type == N_MINUS + || np->type == N_STAR || np->type == N_SLASH || np->type == N_AVG + || np->type == N_SUM) + return 0; + return 1; +} + +static void +freeSeriesQueryNode(node_t *np, int level) +{ + int n_samples; + if (np == NULL) + return; + if (skip_free_value_set(np) != 0) { + int i, j, k; + for (i = 0; i < np->value_set.num_series; i++) { + n_samples = np->value_set.series_values[i].num_samples; + if (n_samples < 0) n_samples = -n_samples; + for (j = 0; j < n_samples; j++) { + for (k=0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].timestamp); + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].series); + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + } + free(np->value_set.series_values[i].series_sample[j].series_instance); + } + sdsfree(np->value_set.series_values[i].sid->name); + free(np->value_set.series_values[i].sid); + free(np->value_set.series_values[i].series_sample); + } + free(np->value_set.series_values); + } + freeSeriesQueryNode(np->left, level+1); + freeSeriesQueryNode(np->right, level+1); + if (level != 0) + free(np); +} + +static void +freeSeriesGetQuery(seriesQueryBaton *baton) +{ + seriesBatonCheckMagic(baton, MAGIC_QUERY, "freeSeriesGetQuery"); + seriesBatonCheckCount(baton, "freeSeriesGetQuery"); + if (baton->error == 0) { + freeSeriesQueryNode(&baton->u.query.root, 0); + } + memset(baton, 0, sizeof(seriesQueryBaton)); + free(baton); +} + +static void +initSeriesGetLabelMap(seriesGetLabelMap *value, sds series, sds name, + redisMap *map, sds mapID, sds mapKey, void *baton) +{ + initSeriesBatonMagic(value, MAGIC_LABELMAP); + value->map = map; + value->series = sdsdup(series); + value->name = sdsdup(name); + value->mapID = sdsdup(mapID); + value->mapKey = sdsdup(mapKey); + value->baton = baton; +} + +static void +freeSeriesGetLabelMap(seriesGetLabelMap *value) +{ + seriesBatonCheckMagic(value, MAGIC_LABELMAP, "freeSeriesGetLabelMap"); + + redisMapRelease(value->map); + sdsfree(value->series); + sdsfree(value->name); + sdsfree(value->mapID); + sdsfree(value->mapKey); + memset(value, 0, sizeof(seriesGetLabelMap)); +} + +static void +initSeriesGetSID(seriesGetSID *sid, const char *name, int needfree, void *baton) +{ + initSeriesBatonMagic(sid, MAGIC_SID); + sid->name = sdsnew(name); + sid->freed = needfree ? 1 : 0; + sid->baton = baton; +} + +static void +freeSeriesGetSID(seriesGetSID *sid) +{ + int needfree; + + seriesBatonCheckMagic(sid, MAGIC_SID, "freeSeriesGetSID"); + sdsfree(sid->name); + needfree = sid->freed; + memset(sid, 0, sizeof(seriesGetSID)); + if (needfree) + free(sid); +} + +static void +initSeriesQueryBaton(seriesQueryBaton *baton, + pmSeriesSettings *settings, void *userdata) +{ + seriesModuleData *data = getSeriesModuleData(&settings->module); + + if (data == NULL) { + /* calloc failed in getSeriesModuleData */ + baton->error = -ENOMEM; + return; + } + initSeriesBatonMagic(baton, MAGIC_QUERY); + baton->callbacks = &settings->callbacks; + baton->info = settings->module.on_info; + baton->slots = data->slots; + baton->module = &settings->module; + baton->userdata = userdata; +} + +static void +initSeriesGetLookup(seriesQueryBaton *baton, int nseries, sds *series, + pmSeriesStringCallBack func, redisMap *map) +{ + seriesGetSID *sid; + unsigned int i; + + /* pattern matching parameter, optional */ + if (nseries == 0 && series != NULL) + baton->u.lookup.pattern = *series; + /* else lookup array of individual sids */ + for (i = 0; i < nseries; i++) { + sid = &baton->u.lookup.series[i]; + initSeriesGetSID(sid, series[i], 0, baton); + } + baton->u.lookup.nseries = nseries; + baton->u.lookup.func = func; + baton->u.lookup.map = map; +} + +static void +freeSeriesGetLookup(seriesQueryBaton *baton) +{ + seriesGetSID *sid; + size_t bytes; + unsigned int i, nseries; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "freeSeriesGetLookup"); + seriesBatonCheckCount(baton, "freeSeriesGetLookup"); + + nseries = baton->u.lookup.nseries; + for (i = 0; i < nseries; i++) { + sid = &baton->u.lookup.series[i]; + sdsfree(sid->name); + } + bytes = sizeof(seriesQueryBaton) + (nseries * sizeof(seriesGetSID)); + memset(baton, 0, bytes); + free(baton); +} + +static void +series_query_finished(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + baton->callbacks->on_done(baton->error, baton->userdata); + freeSeriesGetQuery(baton); +} + +static void +series_query_end_phase(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + char error[PM_MAXERRMSGLEN]; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_end_phase"); + + if (baton->error == 0) { + seriesPassBaton(&baton->current, baton, "series_query_end_phase"); + } else { /* fail after waiting on outstanding I/O */ + if (pmDebugOptions.series || pmDebugOptions.query) { + fprintf(stderr, "%s: ERROR: %d %s\n", "series_query_end_phase", + baton->error, pmErrStr_r(baton->error, error, sizeof(error))); + } + if (seriesBatonDereference(baton, "series_query_end_phase")) + series_query_finished(baton); + } +} + +const char * +series_instance_name(sds key) +{ + size_t length = sdslen(key); + + if (length >= sizeof("instance.") && + strncmp(key, "instance.", sizeof("instance.") - 1) == 0) + return key + sizeof("instance.") - 1; + if (length >= sizeof("inst.") && + strncmp(key, "inst.", sizeof("inst.") - 1) == 0) + return key + sizeof("inst.") - 1; + if (length >= sizeof("i.") && + strncmp(key, "i.", sizeof("i.") - 1) == 0) + return key + sizeof("i.") - 1; + return NULL; +} + +const char * +series_context_name(sds key) +{ + size_t length = sdslen(key); + + if (length >= sizeof("context.") && + strncmp(key, "context.", sizeof("context.") - 1) == 0) + return key + sizeof("context.") - 1; + if (length >= sizeof("source.") && + strncmp(key, "source.", sizeof("source.") - 1) == 0) + return key + sizeof("source.") - 1; + if (length >= sizeof("c.") && + strncmp(key, "c.", sizeof("c.") - 1) == 0) + return key + sizeof("c.") - 1; + if (length >= sizeof("s.") && + strncmp(key, "s.", sizeof("s.") - 1) == 0) + return key + sizeof("s.") - 1; + return NULL; +} + +const char * +series_metric_name(sds key) +{ + size_t length = sdslen(key); + + if (length >= sizeof("metric.") && + strncmp(key, "metric.", sizeof("metric.") - 1) == 0) + return key + sizeof("metric.") - 1; + if (length >= sizeof("m.") && + strncmp(key, "m.", sizeof("m.") - 1) == 0) + return key + sizeof("m.") - 1; + return NULL; +} + +const char * +series_label_name(sds key) +{ + size_t length = sdslen(key); + + if (length >= sizeof("label.") && + strncmp(key, "label.", sizeof("label.") - 1) == 0) + return key + sizeof("label.") - 1; + if (length >= sizeof("l.") && + strncmp(key, "l.", sizeof("l.") - 1) == 0) + return key + sizeof("l.") - 1; + return NULL; +} + +const char * +node_subtype(node_t *np) +{ + switch (np->subtype) { + case N_QUERY: return "query"; + case N_LABEL: return "label"; + case N_METRIC: return "metric"; + case N_CONTEXT: return "context"; + case N_INSTANCE: return "instance"; + default: + break; + } + return NULL; +} + +static int +extract_string(seriesQueryBaton *baton, pmSID series, + redisReply *reply, sds *string, const char *message) +{ + sds msg; + + if (reply->type == REDIS_REPLY_STRING) { + *string = sdscpylen(*string, reply->str, reply->len); + return 0; + } + infofmt(msg, "expected string result for %s of series %s (got %s)", + message, series, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EINVAL; +} + +static int +extract_mapping(seriesQueryBaton *baton, pmSID series, + redisReply *reply, sds *string, const char *message) +{ + redisMapEntry *entry; + sds msg, key; + + if (reply->type == REDIS_REPLY_STRING) { + key = sdsnewlen(reply->str, reply->len); + entry = redisMapLookup(baton->u.lookup.map, key); + sdsfree(key); + if (entry != NULL) { + key = redisMapValue(entry); + *string = sdscpylen(*string, key, sdslen(key)); + return 0; + } + infofmt(msg, "bad mapping for %s of series %s", message, series); + batoninfo(baton, PMLOG_CORRUPT, msg); + return -EINVAL; + } + infofmt(msg, "expected string for %s of series %s", message, series); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; +} + +static int +extract_sha1(seriesQueryBaton *baton, pmSID series, + redisReply *reply, sds *sha, const char *message) +{ + sds msg; + char hashbuf[42]; + + if (reply->type != REDIS_REPLY_STRING) { + infofmt(msg, "expected string result for \"%s\" of series %s got %s", + message, series, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EINVAL; + } + if (reply->len != 20) { + infofmt(msg, "expected sha1 for \"%s\" of series %s, got %ld bytes", + message, series, (long)reply->len); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EINVAL; + } + pmwebapi_hash_str((unsigned char *)reply->str, hashbuf, sizeof(hashbuf)); + *sha = sdscpylen(*sha, hashbuf, 40); + return 0; +} + +/* + * Report a timeseries result - timestamps and (instance) values + */ +static int +series_instance_reply(seriesQueryBaton *baton, sds series, + pmSeriesValue *value, int nelements, redisReply **elements) +{ + char hashbuf[42]; + sds inst; + int i, sts = 0; + + for (i = 0; i < nelements; i += 2) { + inst = value->series; + if (extract_string(baton, series, elements[i], &inst, "series") < 0) { + sts = -EPROTO; + continue; + } + if (sdslen(inst) == 0) { /* no InDom, use series */ + inst = sdscpylen(inst, series, 40); + } else if (sdslen(inst) == 20) { + pmwebapi_hash_str((const unsigned char *)inst, hashbuf, sizeof(hashbuf)); + inst = sdscpylen(inst, hashbuf, 40); + } else { + /* TODO: propagate errors and mark records - separate callbacks? */ + continue; + } + value->series = inst; + + if (extract_string(baton, series, elements[i+1], &value->data, "value") < 0) + sts = -EPROTO; + else + baton->callbacks->on_value(series, value, baton->userdata); + } + return sts; +} + +static int +extract_time(seriesQueryBaton *baton, pmSID series, + redisReply *reply, sds *stamp, pmTimespec *ts) +{ + sds msg, val; + char *point = NULL; + __uint64_t milliseconds, fractions, crossover; + + if (reply->type == REDIS_REPLY_STRING) { + val = sdscpylen(*stamp, reply->str, reply->len); + milliseconds = strtoull(val, &point, 0); + if (point && *point == '-') { + *point = '.'; + fractions = strtoull(point + 1, NULL, 0); + } else { + fractions = 0; + } + crossover = milliseconds % 1000; + ts->tv_sec = milliseconds / 1000; + ts->tv_nsec = (fractions * 1000) + (crossover * 1000000); + *stamp = val; + return 0; + } + infofmt(msg, "expected string timestamp in series %s", series); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; +} + +static inline int +pmTimespec_cmp(pmTimespec *a, pmTimespec *b) +{ + if (a->tv_sec != b->tv_sec) + return (a->tv_sec > b->tv_sec) ? 1 : -1; + if (a->tv_nsec > b->tv_nsec) + return 1; + if (a->tv_nsec < b->tv_nsec) + return -1; + return 0; +} + +static inline void +pmTimespec_add(pmTimespec *t1, pmTimespec *t2) +{ + __int64_t sec = t1->tv_sec + t2->tv_sec; + __int64_t nsec = t1->tv_nsec + t2->tv_nsec; + + if (nsec >= 1000000000) { + nsec -= 1000000000; + sec++; + } + t1->tv_sec = sec; + t1->tv_nsec = nsec; +} + +/* t1 - t2 as a double */ +static inline double +pmTimespec_delta(pmTimespec *t1, pmTimespec *t2) +{ + return (double)(t1->tv_sec - t2->tv_sec) + + (long double)(t1->tv_nsec - t2->tv_nsec) / (long double)1000000000; +} + +typedef struct seriesSampling { + unsigned int setup; /* one-pass calculation flag */ + unsigned int subsampling; /* sample interval requested */ + unsigned int count; /* N sampled values, so far */ + pmSeriesValue value; /* current sample being built */ + pmTimespec goal; /* 'ideal' sample timestamp */ + pmTimespec delta; /* sampling interval (step) */ + pmTimespec next_timespec; /* from the following sample */ + sds next_timestamp; /* from the following sample */ +} seriesSampling; + +static int +use_next_sample(seriesSampling *sampling) +{ + /* if the next timestamp is past our goal, use the current value */ + if (pmTimespec_cmp(&sampling->next_timespec, &sampling->goal) > 0) { + /* selected a value for this interval so move the goal posts */ + pmTimespec_add(&sampling->goal, &sampling->delta); + return 0; + } + return 1; +} + +static void +series_values_reply(seriesQueryBaton *baton, sds series, + int nsamples, redisReply **samples, void *arg) +{ + seriesSampling sampling = {0}; + redisReply *reply, *sample, **elements; + timing_t *tp = &baton->u.query.timing; + int n, sts, next, nelements; + sds msg, save_timestamp; + + sampling.value.timestamp = sdsempty(); + sampling.value.series = sdsempty(); + sampling.value.data = sdsempty(); + + /* iterate over the 'samples' array */ + for (n = 0; n < nsamples; n++) { + sample = samples[n]; + if ((nelements = sample->elements) == 0) + continue; + elements = sample->element; + + /* expecting timestamp:valueset pairs, then instance:value pairs */ + if (nelements % 2) { + infofmt(msg, "expected time:valueset pairs in %s XRANGE", series); + batoninfo(baton, PMLOG_RESPONSE, msg); + sts = -EPROTO; + break; + } + + /* verify the instance:value pairs array before proceeding */ + reply = elements[1]; + if (reply->type != REDIS_REPLY_ARRAY) { + infofmt(msg, "expected value array for series %s %s (type=%s)", + series, XRANGE, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + break; + } + + /* setup state variables used internally during selection process */ + if (sampling.setup == 0 && (tp->delta.tv_sec || tp->delta.tv_usec)) { + /* 'next' is a nanosecond precision time interval to step with */ + sampling.delta.tv_sec = tp->delta.tv_sec; + sampling.delta.tv_nsec = tp->delta.tv_usec * 1000; + + /* extract the first timestamp to kickstart the comparison process */ + if ((sts = extract_time(baton, series, elements[0], + &sampling.value.timestamp, + &sampling.value.ts)) < 0) { + baton->error = sts; + break; + } + /* 'goal' is the first target interval as an absolute timestamp */ + if (tp->start.tv_sec || tp->start.tv_usec) { + sampling.goal.tv_sec = tp->start.tv_sec; + sampling.goal.tv_nsec = tp->start.tv_usec * 1000; + } else { + sampling.goal = sampling.value.ts; + } + sampling.goal.tv_nsec++; /* ensure we use first sample */ + + sampling.next_timestamp = sdsempty(); + sampling.subsampling = 1; + } + sampling.setup = 1; + + if (sampling.subsampling == 0) { + if ((sts = extract_time(baton, series, elements[0], + &sampling.value.timestamp, + &sampling.value.ts)) < 0) { + baton->error = sts; + continue; + } + } else if ((next = n + 1) < nsamples) { + /* + * Compare this point and the next to the ideal based on delta; + * skip over returning this value if the next one looks better. + */ + elements = samples[next]->element; + if ((sts = extract_time(baton, series, elements[0], + &sampling.next_timestamp, + &sampling.next_timespec)) < 0) { + baton->error = sts; + continue; + } else if ((sts = use_next_sample(&sampling)) == 1) { + goto next_sample; + } else if (sts == -1) { /* sampling reached the end */ + goto last_sample; + } /* else falls through and may call user-supplied callback */ + } + + /* check whether a user-requested sample count has been reached */ + if (tp->count && sampling.count++ >= tp->count) + break; + + if ((sts = series_instance_reply(baton, series, &sampling.value, + reply->elements, reply->element)) < 0) { + baton->error = sts; + goto last_sample; + } + + if (sampling.subsampling == 0) + continue; +next_sample: + /* carefully swap time strings to avoid leaking memory */ + save_timestamp = sampling.next_timestamp; + sampling.next_timestamp = sampling.value.timestamp; + sampling.value.timestamp = save_timestamp; + sampling.value.ts = sampling.next_timespec; + } + +last_sample: + if (sampling.setup) + sdsfree(sampling.next_timestamp); + sdsfree(sampling.value.timestamp); + sdsfree(sampling.value.series); + sdsfree(sampling.value.data); +} + +/* + * Save the series hash identifiers contained in a Redis response + * for all series that are not already in this nodes set (union). + * Used at the leaves of the query tree, then merged result sets + * are propagated upward. + */ +static int +node_series_reply(seriesQueryBaton *baton, node_t *np, int nelements, redisReply **elements) +{ + series_set_t set; + unsigned char *series; + redisReply *reply; + char hashbuf[42]; + sds msg; + int i, sts = 0; + + if (nelements <= 0) + return nelements; + + if ((series = (unsigned char *)calloc(nelements, SHA1SZ)) == NULL) { + infofmt(msg, "out of memory (%s, %" FMT_INT64 " bytes)", + "series reply", (__int64_t)nelements * SHA1SZ); + batoninfo(baton, PMLOG_REQUEST, msg); + return -ENOMEM; + } + set.series = series; + set.nseries = nelements; + + for (i = 0; i < nelements; i++) { + reply = elements[i]; + if (reply->type == REDIS_REPLY_STRING) { + memcpy(series, reply->str, SHA1SZ); + if (pmDebugOptions.series) { + pmwebapi_hash_str(series, hashbuf, sizeof(hashbuf)); + fprintf(stderr, " %s\n", hashbuf); + } + series += SHA1SZ; + } else { + infofmt(msg, "expected string in %s set \"%s\" (type=%s)", + node_subtype(np->left), np->left->key, + redis_reply_type(reply)); + batoninfo(baton, PMLOG_REQUEST, msg); + sts = -EPROTO; + } + } + if (sts < 0) { + free(set.series); + return sts; + } + + return series_union(&np->result, &set); +} + +static int +series_compare(const void *a, const void *b) +{ + return memcmp(a, b, SHA1SZ); +} + +/* + * Form resulting set via intersection of two child sets. + * Algorithm: + * - sort the larger set + * - for each identifier in the smaller set + * o bisect to find match in sorted set + * o if matching, add it to the current saved set + * + * Memory from the smaller set is re-used to hold the result, + * its memory is trimmed (via realloc) if the final resulting + * set is smaller, and the larger set is freed on completion. + */ +static int +series_intersect(series_set_t *a, series_set_t *b) +{ + unsigned char *small, *large, *saved, *cp; + int nsmall, nlarge, total, i; + + if (a->nseries >= b->nseries) { + large = a->series; nlarge = a->nseries; + small = b->series; nsmall = b->nseries; + } else { + small = a->series; nsmall = a->nseries; + large = b->series; nlarge = b->nseries; + } + + if (pmDebugOptions.series) + printf("Intersect large(%d) and small(%d) series\n", nlarge, nsmall); + + qsort(large, nlarge, SHA1SZ, series_compare); + + for (i = 0, cp = saved = small; i < nsmall; i++, cp += SHA1SZ) { + if (!bsearch(cp, large, nlarge, SHA1SZ, series_compare)) + continue; /* no match, continue advancing cp only */ + if (saved != cp) + memcpy(saved, cp, SHA1SZ); + saved += SHA1SZ; /* stashed, advance cp & saved pointers */ + } + + if ((total = (saved - small)/SHA1SZ) < nsmall) { + /* shrink the smaller set down further */ + if ((small = realloc(small, total * SHA1SZ)) == NULL) + return -ENOMEM; + } + + if (pmDebugOptions.series && pmDebugOptions.desperate) { + char hashbuf[42]; + + fprintf(stderr, "Intersect result set contains %d series:\n", total); + for (i = 0, cp = small; i < total; cp += SHA1SZ, i++) { + pmwebapi_hash_str(cp, hashbuf, sizeof(hashbuf)); + fprintf(stderr, " %s\n", hashbuf); + } + } + + a->nseries = total; + a->series = small; + b->series = NULL; + b->nseries = 0; + free(large); + return 0; +} + +static int +node_series_intersect(node_t *np, node_t *left, node_t *right) +{ + int sts; + + if ((sts = series_intersect(&left->result, &right->result)) >= 0) + np->result = left->result; + + /* finished with child leaves now, results percolated up */ + right->result.nseries = left->result.nseries = 0; + return sts; +} + +/* + * Form the resulting set from union of two child sets. + * The larger set is realloc-ated to form the result, if we + * need to (i.e. if there are entries in the smaller set not + * in the larger). + * + * Iterates over the smaller set doing a binary search of + * each series identifier, and tracks which ones in the small + * need to be added to the large set. + * At the end, add more space to the larger set if needed and + * append to it. As a courtesy, since all callers need this, + * we free the smaller set as well. + */ +static int +series_union(series_set_t *a, series_set_t *b) +{ + unsigned char *cp, *saved, *large, *small; + int nlarge, nsmall, total, need, i; + + if (a->nseries >= b->nseries) { + large = a->series; nlarge = a->nseries; + small = b->series; nsmall = b->nseries; + } else { + small = a->series; nsmall = a->nseries; + large = b->series; nlarge = b->nseries; + } + + if (pmDebugOptions.series) + fprintf(stderr, "Union of large(%d) and small(%d) series\n", nlarge, nsmall); + + qsort(large, nlarge, SHA1SZ, series_compare); + + for (i = 0, cp = saved = small; i < nsmall; i++, cp += SHA1SZ) { + if (bsearch(cp, large, nlarge, SHA1SZ, series_compare) != NULL) + continue; /* already present, no need to save */ + if (saved != cp) + memcpy(saved, cp, SHA1SZ); + saved += SHA1SZ; /* stashed, advance both cp & saved */ + } + + if ((need = (saved - small) / SHA1SZ) > 0) { + /* grow the larger set to cater for new entries, then add 'em */ + if ((cp = realloc(large, (nlarge + need) * SHA1SZ)) == NULL) + return -ENOMEM; + large = cp; + cp += (nlarge * SHA1SZ); + memcpy(cp, small, need * SHA1SZ); + total = nlarge + need; + } else { + total = nlarge; + } + + if (pmDebugOptions.series && pmDebugOptions.desperate) { + char hashbuf[42]; + + fprintf(stderr, "Union result set contains %d series:\n", total); + for (i = 0, cp = large; i < total; cp += SHA1SZ, i++) { + pmwebapi_hash_str(cp, hashbuf, sizeof(hashbuf)); + fprintf(stderr, " %s\n", hashbuf); + } + } + + a->nseries = total; + a->series = large; + b->series = NULL; + b->nseries = 0; + free(small); + return 0; +} + +static int +node_series_union(node_t *np, node_t *left, node_t *right) +{ + int sts; + + if ((sts = series_union(&left->result, &right->result)) >= 0) + np->result = left->result; + + /* finished with child leaves now, results percolated up */ + right->result.nseries = left->result.nseries = 0; + return sts; +} + +static int +string_pattern_match(node_t *np, sds pattern, char *string, int length) +{ + int sts; + + /* if the string is in double quotes, we want to pattern match */ + if (length > 1 && string[0] == '\"' && string[length-1] == '\"') { + string[length-1] = '\0'; + string++; + } + + if (np->type == N_GLOB) /* match via globbing */ + return fnmatch(pattern, string, 0) == 0; + + /* use either regular expression match or negation */ + sts = regexec((const regex_t *)&np->regex, string, 0, NULL, 0); + if (np->type == N_REQ) + return sts == 0; + if (np->type == N_RNE) + return sts != 0; + return 0; +} + +/* + * Add a node subtree representing glob (N_GLOB) pattern matches. + * Each of these matches are then further evaluated (as if N_EQ). + * Response format is described at https://redis.io/commands/scan + */ +static int +node_pattern_reply(seriesQueryBaton *baton, node_t *np, const char *name, int nelements, + redisReply **elements) +{ + redisReply *reply, *r; + sds msg, key, pattern, *matches; + char buffer[42]; + size_t bytes; + unsigned int i; + + if (nelements != 2) { + infofmt(msg, "expected cursor and results from %s (got %d elements)", + HSCAN, nelements); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + + /* update the cursor in case subsequent calls are needed */ + reply = elements[0]; + if (!reply || reply->type != REDIS_REPLY_STRING) { + infofmt(msg, "expected integer cursor result from %s (got %s)", + HSCAN, reply ? redis_reply_type(reply) : "null"); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + np->cursor = strtoull(reply->str, NULL, 10); + + reply = elements[1]; + if (!reply || reply->type != REDIS_REPLY_ARRAY) { + infofmt(msg, "expected array of results from %s (got %s)", + HSCAN, reply ? redis_reply_type(reply) : "null"); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + + /* result array checking */ + if ((nelements = reply->elements) % 2) { + infofmt(msg, "expected even number of results from %s (not %d)", + HSCAN, nelements); + batoninfo(baton, PMLOG_REQUEST, msg); + return -EPROTO; + } + if (nelements == 0) + goto out; + + for (i = 0; i < nelements; i += 2) { + r = reply->element[i]; + if (r->type != REDIS_REPLY_STRING) { + infofmt(msg, "expected only string results from %s (type=%s)", + HSCAN, redis_reply_type(r)); + batoninfo(baton, PMLOG_REQUEST, msg); + return -EPROTO; + } + } + + /* response is key:value pairs from the scanned hash */ + nelements /= 2; + + /* matching string - either glob or regex */ + pattern = np->right->value; + if (np->type != N_GLOB && + /* TODO: move back to initial tree parsing for error handling */ + regcomp((regex_t *)&np->regex, pattern, REG_EXTENDED|REG_NOSUB) != 0) { + infofmt(msg, "invalid regular expression \"%s\"", pattern); + batoninfo(baton, PMLOG_REQUEST, msg); + return -EINVAL; + } + + for (i = 0; i < nelements; i++) { + r = reply->element[i*2+1]; /* string value */ + if (!string_pattern_match(np, pattern, r->str, r->len)) + continue; + + r = reply->element[i*2]; /* SHA1 hash */ + pmwebapi_hash_str((const unsigned char *)r->str, buffer, sizeof(buffer)); + key = sdsnew("pcp:series:"); + key = sdscatfmt(key, "%s:%s", name, buffer); + + if (pmDebugOptions.series) + fprintf(stderr, "adding pattern-matched result key: %s\n", key); + + bytes = (np->nmatches + 1) * sizeof(sds); + if ((matches = (sds *)realloc(np->matches, bytes)) == NULL) { + infofmt(msg, "out of memory (%s, %" FMT_INT64 " bytes)", + "pattern reply", (__int64_t)bytes); + batoninfo(baton, PMLOG_REQUEST, msg); + sdsfree(key); /* Coverity CID328038 */ + return -ENOMEM; + } + matches[np->nmatches++] = key; + np->matches = matches; + } + +out: + if (np->cursor > 0) /* still more to retrieve - kick off the next batch */ + series_pattern_match(baton, np); + else + regfree((regex_t *)&np->regex); + + return nelements; +} + +static void +series_prepare_maps_pattern_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + node_t *np = (node_t *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + redisReply *reply = r; + const char *name; + node_t *left; + sds msg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_prepare_maps_pattern_reply"); + assert(np->type == N_GLOB || np->type == N_REQ || np->type == N_RNE); + + left = np->left; + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array for %s key \"%s\" (type=%s)", + node_subtype(left), left->key, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else { + name = left->key + sizeof("pcp:map:") - 1; + if (pmDebugOptions.series) + fprintf(stderr, "%s %s\n", node_subtype(np->left), np->key); + if (node_pattern_reply(baton, np, name, reply->elements, reply->element) < 0) + baton->error = -EPROTO; + } + + series_query_end_phase(baton); +} + +static void +series_pattern_match(seriesQueryBaton *baton, node_t *np) +{ + sds cmd, cur, key; + + seriesBatonReference(baton, "series_pattern_match"); + cur = sdscatfmt(sdsempty(), "%U", np->cursor); + key = sdsdup(np->left->key); + cmd = redis_command(5); + cmd = redis_param_str(cmd, HSCAN, HSCAN_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_sds(cmd, cur); /* cursor */ + cmd = redis_param_str(cmd, "COUNT", sizeof("COUNT")-1); + cmd = redis_param_sds(cmd, cursorcount); + sdsfree(cur); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_prepare_maps_pattern_reply, np); + sdsfree(cmd); +} + +/* + * Map human names to internal Redis identifiers. + */ +static int +series_prepare_maps(seriesQueryBaton *baton, node_t *np, int level) +{ + unsigned char hash[20]; + const char *name; + char buffer[42]; + int sts; + + if (np == NULL) + return 0; + + if ((sts = series_prepare_maps(baton, np->left, level+1)) < 0) + return sts; + + switch (np->type) { + case N_NAME: + /* setup any label name map identifiers needed by direct children */ + if ((name = series_instance_name(np->value)) != NULL) { + np->subtype = N_INSTANCE; + np->key = sdsnew("pcp:map:inst.name"); + } else if ((name = series_metric_name(np->value)) != NULL) { + np->subtype = N_METRIC; + np->key = sdsnew("pcp:map:metric.name"); + } else if ((name = series_context_name(np->value)) != NULL) { + np->subtype = N_CONTEXT; + np->key = sdsnew("pcp:map:context.name"); + } else { + np->subtype = N_LABEL; + if ((name = series_label_name(np->value)) == NULL) + name = np->value; + pmwebapi_string_hash(hash, name, strlen(name)); + np->key = sdscatfmt(sdsempty(), "pcp:map:label.%s.value", + pmwebapi_hash_str(hash, buffer, sizeof(buffer))); + } + break; + + case N_GLOB: /* globbing or regular expression lookups */ + case N_REQ: + case N_RNE: + np->baton = baton; + series_pattern_match(baton, np); + break; + + default: + break; + } + + return series_prepare_maps(baton, np->right, level+1); +} + +static sds +series_node_value(node_t *np) +{ + unsigned char hash[20]; + sds val = sdsnewlen(SDS_NOINIT, 40); + + /* special JSON cases still to do: null, true, false */ + if (np->left->type == N_NAME && + np->left->subtype == N_LABEL && + np->right->type == N_STRING) { + np->right->subtype = N_LABEL; + sdsclear(val); + val = sdscatfmt(val, "\"%S\"", np->right->value); + pmwebapi_string_hash(hash, val, sdslen(val)); + } else { + pmwebapi_string_hash(hash, np->right->value, strlen(np->right->value)); + } + sdsclear(val); + return pmwebapi_hash_sds(val, hash); +} + +static void +series_prepare_smembers_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + node_t *np = (node_t *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + redisReply *reply = r; + sds msg; + int sts; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_prepare_smembers_reply"); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array for %s set \"%s\" (type=%s)", + node_subtype(np->left), np->right->value, + redis_reply_type(reply)); + batoninfo(baton, PMLOG_CORRUPT, msg); + baton->error = -EPROTO; + } else { + if (pmDebugOptions.series) + fprintf(stderr, "%s %s\n", node_subtype(np->left), np->key); + sts = node_series_reply(baton, np, reply->elements, reply->element); + if (sts < 0) + baton->error = sts; + } + + if (np->nmatches) + np->nmatches--; /* processed one more from this batch */ + + series_query_end_phase(baton); +} + +static void +series_prepare_smembers(seriesQueryBaton *baton, sds kp, node_t *np) +{ + sds cmd; + + cmd = redis_command(2); + cmd = redis_param_str(cmd, SMEMBERS, SMEMBERS_LEN); + cmd = redis_param_sds(cmd, kp); + redisSlotsRequest(baton->slots, cmd, + series_prepare_smembers_reply, np); + sdsfree(cmd); +} + +static void +series_hmset_function_desc_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + redisSlotsBaton *baton = (redisSlotsBaton *)arg; + redisReply *reply = r; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_hmset_function_desc_callback"); + checkStatusReplyOK(baton->info, baton->userdata, c, reply, + "%s", "pcp:desc"); + series_query_end_phase(baton); +} + +static void +series_hmset_function_desc(seriesQueryBaton *baton, sds key, pmSeriesDesc *desc) +{ + sds cmd; + + seriesBatonReference(baton, "series_hmset_function_desc"); + + cmd = redis_command(14); + cmd = redis_param_str(cmd, HMSET, HMSET_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_str(cmd, "indom", sizeof("indom")-1); + cmd = redis_param_sds(cmd, desc->indom); + cmd = redis_param_str(cmd, "pmid", sizeof("pmid")-1); + cmd = redis_param_sds(cmd, desc->pmid); + cmd = redis_param_str(cmd, "semantics", sizeof("semantics")-1); + cmd = redis_param_sds(cmd, desc->semantics); + cmd = redis_param_str(cmd, "source", sizeof("source")-1); + /* for fabricated SIDs, this is a binary string of 20 zero (NULL) bytes */ + cmd = redis_param_sds(cmd, desc->source); + cmd = redis_param_str(cmd, "type", sizeof("type")-1); + cmd = redis_param_sds(cmd, desc->type); + cmd = redis_param_str(cmd, "units", sizeof("units")-1); + cmd = redis_param_sds(cmd, desc->units); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_hmset_function_desc_callback, baton); + sdsfree(cmd); +} + +static void +series_hmset_function_expr_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + redisSlotsBaton *baton = (redisSlotsBaton *)arg; + redisReply *reply = r; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_hmset_function_expr_callback"); + checkStatusReplyOK(baton->info, baton->userdata, c, reply, + "%s", "pcp:expr"); + series_query_end_phase(baton); +} + +static void +series_hmset_function_expr(seriesQueryBaton *baton, sds key, sds expr) +{ + sds cmd; + + seriesBatonReference(baton, "series_hmset_function_expr"); + + cmd = redis_command(4); + cmd = redis_param_str(cmd, HMSET, HMSET_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_str(cmd, "query", sizeof("query")-1); + cmd = redis_param_sds(cmd, expr); + sdsfree(key); + + redisSlotsRequest(baton->slots, cmd, series_hmset_function_expr_callback, baton); + sdsfree(cmd); +} + +/* + * Prepare evaluation of leaf nodes. + */ +static int +series_prepare_eval(seriesQueryBaton *baton, node_t *np, int level) +{ + sds val; + int sts, i; + node_t *left; + const char *name; + + if (np == NULL) + return 0; + + if ((sts = series_prepare_eval(baton, np->left, level+1)) < 0) + return sts; + + switch (np->type) { + case N_EQ: /* direct hash lookup */ + left = np->left; + name = left->key + sizeof("pcp:map:") - 1; + assert(np->key == NULL); + val = series_node_value(np); + np->key = sdsnew("pcp:series:"); + np->key = sdscatfmt(np->key, "%s:%S", name, val); + sdsfree(val); + np->baton = baton; + seriesBatonReference(baton, "series_prepare_expr[direct]"); + series_prepare_smembers(baton, np->key, np); + break; + + case N_GLOB: /* globbing or regular expression lookups */ + case N_REQ: + case N_RNE: + np->baton = baton; + if (np->nmatches > 0) + seriesBatonReferences(baton, np->nmatches, "series_prepare_eval[pattern]"); + for (i = 0; i < np->nmatches; i++) + series_prepare_smembers(baton, np->matches[i], np); + break; + + default: + break; + } + + return series_prepare_eval(baton, np->right, level+1); +} + +/* + * Prepare evaluation of internal nodes. + */ +static int +series_prepare_expr(seriesQueryBaton *baton, node_t *np, int level) +{ + int sts; + + if (np == NULL) + return 0; + + if ((sts = series_prepare_expr(baton, np->left, level+1)) < 0) + return sts; + if ((sts = series_prepare_expr(baton, np->right, level+1)) < 0) + return sts; + + switch (np->type) { + case N_LT: case N_LEQ: case N_GEQ: case N_GT: case N_NEQ: case N_NEG: + /* TODO - relational operators */ + break; + + case N_AND: + sts = node_series_intersect(np, np->left, np->right); + break; + + case N_OR: + sts = node_series_union(np, np->left, np->right); + break; + + default: + break; + } + return sts; +} + +static void +on_series_solve_setup(void *arg) +{ + if (pmDebugOptions.query) + fprintf(stderr, "on_series_solve_setup\n"); +} + +static void +on_series_solve_log(pmLogLevel level, sds message, void *arg) +{ + if (pmDebugOptions.query) + fprintf(stderr, "on_series_solve_log: %s\n", message); +} + +static void +on_series_solve_done(int status, void *arg) +{ + seriesQueryBaton *baton = arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "on_series_solve_done"); + if (pmDebugOptions.query && pmDebugOptions.desperate) + fprintf(stderr, "on_series_solve_done: arg=%p status=%d\n", arg, status); + baton->callbacks->on_done(status, baton->userdata); +} + +static int +on_series_solve_value(pmSID sid, pmSeriesValue *value, void *arg) +{ + seriesQueryBaton *baton = arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "on_series_solve_value"); + if (pmDebugOptions.query && pmDebugOptions.desperate) + fprintf(stderr, "on_series_solve_value: arg=%p %s %s %s\n", + arg, value->timestamp, value->data, value->series); + return baton->callbacks->on_value(sid, value, baton->userdata); +} + + +static void +on_series_solve_inst_done(int status, void *arg) +{ + seriesQueryBaton *baton = arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "on_series_solve_done"); + if (pmDebugOptions.query && pmDebugOptions.desperate) + fprintf(stderr, "on_series_solve_done: arg=%p status=%d\n", arg, status); + /* on_done is called by series_query_finished */ + seriesBatonDereference(baton, "on_series_solve_inst_done"); +} + +/* + * HMGETALL pcp:inst:series:(value->series) + * re-using series_instances_reply_callback as the callback. + */ +static int +on_series_solve_inst_value(pmSID sid, pmSeriesValue *value, void *arg) +{ + seriesQueryBaton *baton = arg; + seriesGetSID *sidbat; + sds key, cmd; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "on_series_solve_inst_value"); + if (pmDebugOptions.query) { + fprintf(stderr, "on_series_solve_inst_value: arg=%p %s %s %s\n", + arg, value->timestamp, value->data, value->series); + } + + sidbat = calloc(1, sizeof(seriesGetSID)); + initSeriesGetSID(sidbat, value->series, 1, baton); + sidbat->metric = sdsdup(sid); + + seriesBatonReference(baton, "on_series_solve_inst_value"); + seriesBatonReference(sidbat, "on_series_solve_inst_value"); + + key = sdscatfmt(sdsempty(), "pcp:inst:series:%S", value->series); + cmd = redis_command(5); + cmd = redis_param_str(cmd, HMGET, HMGET_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_str(cmd, "inst", sizeof("inst")-1); + cmd = redis_param_str(cmd, "name", sizeof("name")-1); + cmd = redis_param_str(cmd, "source", sizeof("source")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_instances_reply_callback, sidbat); + sdsfree(cmd); + return 0; +} + +/* settings and callbacks for /series/values with fabricated SID */ +static pmSeriesSettings series_solve_values_settings = { + .callbacks.on_value = on_series_solve_value, + .callbacks.on_done = on_series_solve_done, + .module.on_setup = on_series_solve_setup, + .module.on_info = on_series_solve_log, +}; + +/* settings and callbacks for /series/instances with fabricated SID */ +static pmSeriesSettings series_solve_inst_settings = { + .callbacks.on_value = on_series_solve_inst_value, + .callbacks.on_done = on_series_solve_inst_done, + .module.on_setup = on_series_solve_setup, + .module.on_info = on_series_solve_log, +}; + +/* + * Called from /series/values?series=SID[, ...] for a fabricated + * SID expression. Parse and series_solve the expression with + * samples/timing then via callbacks, add the resulting reply + * elements to the response series for original pmSeriesBaton. + */ +static int +series_solve_sid_expr(pmSeriesSettings *settings, pmSeriesExpr *expr, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + series_t sp = {0}; /* root of parsed expression tree, with timing */ + char *errstr; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_query_expr_reply"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_expr_reply"); + + if (pmDebugOptions.query) { + fprintf(stderr, "series_solve_sid_expr: SID %s, " + "seriesQueryBaton=%p, pmSeriesBaton=userdata=%p expr=\"%s\"\n", + sid->name, baton, baton->userdata, expr->query); + } + + /* ref baton until on_series_solve_done */ + seriesBatonReference(baton, "series_solve_sid_expr"); + + if ((sts = series_parse(expr->query, &sp, &errstr, arg)) == 0) { + pmSeriesSetSlots(&settings->module, baton->slots); + settings->module = *baton->module; /* struct cpy */ + + sts = series_solve(settings, sp.expr, &baton->u.query.timing, + PM_SERIES_FLAG_NONE, baton); + } + + return sts; +} + +static void +series_query_expr_reply(redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + pmSeriesExpr expr = {0}; + sds msg; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_query_expr_reply"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_expr_reply"); + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array of one string element (got %zu) from series %s %s (type=%s)", + reply->elements, sid->name, HMGET, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + } else if (reply->element[0]->type == REDIS_REPLY_STRING) { + expr.query = sdsempty(); + if ((sts = extract_string(baton, sid->name, reply->element[0], &expr.query, "query")) < 0) { + baton->error = sts; + } else { + /* Parse the expr (with timing) and series solve the resulting expr tree */ + baton->error = series_solve_sid_expr(&series_solve_values_settings, &expr, arg); + } + } + series_query_end_phase(baton); +} + +static void +series_prepare_time_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + seriesGetSID *expr; + sds key, exprcmd; + sds msg; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_prepare_time_reply"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_prepare_time_reply"); + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array from %s XSTREAM values (type=%s)", + sid->name, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else { + if (reply->elements > 0) { + /* reply is a normal time series */ + series_values_reply(baton, sid->name, reply->elements, reply->element, arg); + } else { + /* Handle fabricated/expression SID in /series/values : + * - get the expr for sid->name from redis. In the callback for that, + * parse the expr and then solve the expression tree with timing from + * this series query baton. Then merge the values in the reply elements. + * TODO (maybe) - also get the desc and check source hash is zero. + */ + if (pmDebugOptions.series) + fprintf(stderr, "series_prepare_time_reply: sid %s is fabricated\n", sid->name); + expr = calloc(1, sizeof(seriesGetSID)); + initSeriesGetSID(expr, sid->name, 1, baton); + seriesBatonReference(baton, "series_query_expr_reply"); + + key = sdscatfmt(sdsempty(), "pcp:expr:series:%S", expr->name); + exprcmd = redis_command(3); + exprcmd = redis_param_str(exprcmd, HMGET, HMGET_LEN); + exprcmd = redis_param_sds(exprcmd, key); + exprcmd = redis_param_str(exprcmd, "query", sizeof("query")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, exprcmd, series_query_expr_reply, expr); + sdsfree(exprcmd); + } + } + freeSeriesGetSID(sid); + series_query_end_phase(baton); +} + +unsigned int +series_value_count_only(timing_t *tp) +{ + if (tp->window.range || tp->window.delta || + tp->window.start || tp->window.end) + return 0; + return tp->count; +} + +static void +series_prepare_time(seriesQueryBaton *baton, series_set_t *result) +{ + timing_t *tp = &baton->u.query.timing; + unsigned char *series = result->series; + seriesGetSID *sid; + char buffer[64], revbuf[64]; + sds start, end, key, cmd; + unsigned int i, revlen = 0, reverse = 0; + + /* if only 'count' is requested, work back from most recent value */ + if ((reverse = series_value_count_only(tp)) != 0) { + revlen = pmsprintf(revbuf, sizeof(revbuf), "%u", reverse); + start = sdsnew("+"); + } else { + start = sdsnew(timeval_stream_str(&tp->start, buffer, sizeof(buffer))); + } + + if (pmDebugOptions.series) + fprintf(stderr, "START: %s\n", start); + + if (reverse) + end = sdsnew("-"); + else if (tp->end.tv_sec) + end = sdsnew(timeval_stream_str(&tp->end, buffer, sizeof(buffer))); + else + end = sdsnew("+"); /* "+" means "no end" - to the most recent */ + + if (pmDebugOptions.series) + fprintf(stderr, "END: %s\n", end); + + /* + * Query cache for the time series range (groups of instance:value + * pairs, with an associated timestamp). + */ + for (i = 0; i < result->nseries; i++, series += SHA1SZ) { + sid = calloc(1, sizeof(seriesGetSID)); + pmwebapi_hash_str(series, buffer, sizeof(buffer)); + + initSeriesGetSID(sid, buffer, 1, baton); + seriesBatonReference(baton, "series_prepare_time"); + + key = sdscatfmt(sdsempty(), "pcp:values:series:%S", sid->name); + + /* X[REV]RANGE key t1 t2 [count N] */ + if (reverse) { + cmd = redis_command(6); + cmd = redis_param_str(cmd, XREVRANGE, XREVRANGE_LEN); + } else { + cmd = redis_command(4); + cmd = redis_param_str(cmd, XRANGE, XRANGE_LEN); + } + cmd = redis_param_sds(cmd, key); + cmd = redis_param_sds(cmd, start); + cmd = redis_param_sds(cmd, end); + if (reverse) { + cmd = redis_param_str(cmd, "COUNT", sizeof("COUNT")-1); + cmd = redis_param_str(cmd, revbuf, revlen); + } + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_prepare_time_reply, sid); + sdsfree(cmd); + } + sdsfree(start); + sdsfree(end); +} + +static void +series_expr_query_desc(seriesQueryBaton *baton, series_set_t *query_series_set, node_t *np) +{ + unsigned int i; + int nseries = query_series_set->nseries; + unsigned char *series = query_series_set->series; + char hashbuf[42]; + seriesGetSID *sid; + + /* calloc nseries samples store space */ + if ((np->value_set.series_values = (series_sample_set_t *)calloc(nseries, sizeof(series_sample_set_t))) == NULL) { + /* TODO: error report here */ + baton->error = -ENOMEM; + } + for (i = 0; i < nseries; i++, series += SHA1SZ) { + sid = calloc(1, sizeof(seriesGetSID)); + pmwebapi_hash_str(series, hashbuf, sizeof(hashbuf)); + initSeriesGetSID(sid, hashbuf, 1, baton); + np->value_set.series_values[i].baton = baton; + np->value_set.series_values[i].sid = sid; + np->value_set.series_values[i].num_samples = 0; + series_node_get_desc(baton, sid->name, &np->value_set.series_values[i]); + series_node_get_metric_name(baton, sid, &np->value_set.series_values[i]); + } +} + +static int +series_expr_node_desc(seriesQueryBaton *baton, node_t *np){ + int sts, nelements = 0; + + if (np == NULL) + return 0; + if (&np->result != NULL) + nelements = np->result.nseries; + + if (nelements != 0) { + np->value_set.num_series = nelements; + np->baton = baton; + series_expr_query_desc(baton, &np->result, np); + return baton->error; + } + + if ((sts = series_expr_node_desc(baton, np->left)) < 0) + return sts; + return series_expr_node_desc(baton, np->right); +} + +static void +series_report_set(seriesQueryBaton *baton, node_t *np) +{ + int i, j; + sds series; + + for (i = 0; i < np->value_set.num_series; i++) { + series = np->value_set.series_values[i].sid->name; + for (j=0; j < i; j++) { + if (strncmp(series, np->value_set.series_values[j].sid->name, SHA1SZ) == 0) + break; + } + if (i == j && baton->callbacks->on_match) + baton->callbacks->on_match(series, baton->userdata); + } +} + +static void +series_query_report_matches(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + int has_function = 0; + char hashbuf[42]; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_report_matches"); + seriesBatonCheckCount(baton, "series_query_report_matches"); + + seriesBatonReference(baton, "series_query_report_matches"); + + has_function = series_calculate(baton, &baton->u.query.root, 0); + + if (has_function != 0) + series_redis_hash_expression(baton, hashbuf, sizeof(hashbuf)); + series_report_set(baton, &baton->u.query.root); + series_query_end_phase(baton); +} + +static void +series_query_maps(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_maps"); + seriesBatonCheckCount(baton, "series_query_maps"); + + seriesBatonReference(baton, "series_query_maps"); + series_prepare_maps(baton, &baton->u.query.root, 0); + series_query_end_phase(baton); +} + +static void +series_query_eval(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_eval"); + seriesBatonCheckCount(baton, "series_query_eval"); + + seriesBatonReference(baton, "series_query_eval"); + series_prepare_eval(baton, &baton->u.query.root, 0); + series_query_end_phase(baton); +} + +static void +series_query_expr(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_expr"); + seriesBatonCheckCount(baton, "series_query_expr"); + + seriesBatonReference(baton, "series_query_expr"); + series_prepare_expr(baton, &baton->u.query.root, 0); + series_query_end_phase(baton); +} + +static int +series_instance_store_to_node(seriesQueryBaton *baton, sds series, + pmSeriesValue *value, int nelements, redisReply **elements, node_t *np, int idx_sample) +{ + char hashbuf[42]; + sds inst; + int i, sts = 0; + int idx_instance = 0; + int idx_series = np->value_set.num_series; + + for (i = 0; i < nelements; i += 2) { + inst = value->series; + if (extract_string(baton, series, elements[i], &inst, "series") < 0) { + sts = -EPROTO; + continue; + } + if (sdslen(inst) == 0) { /* no InDom, use series */ + inst = sdscpylen(inst, series, 40); + } else if (sdslen(inst) == 20) { + pmwebapi_hash_str((const unsigned char *)inst, hashbuf, sizeof(hashbuf)); + inst = sdscpylen(inst, hashbuf, 40); + } else { + /* TODO: propagate errors and mark records - separate callbacks? */ + continue; + } + value->series = inst; + + if (extract_string(baton, series, elements[i+1], &value->data, "value") < 0) + sts = -EPROTO; + else { + /* update value instance */ + pmSeriesValue *valinst = &np->value_set.series_values[idx_series].series_sample[idx_sample].series_instance[idx_instance]; + + valinst->ts = value->ts; /* struct pmTimespec assign */ + valinst->timestamp = sdsnew(value->timestamp); + valinst->series = sdsnew(value->series); + valinst->data = sdsnew(value->data); + ++idx_instance; + } + } + return sts; +} + +/* Do something like memcpy */ +static void +series_values_store_to_node(seriesQueryBaton *baton, sds series, + int nsamples, redisReply **samples, node_t *np) +{ + seriesSampling sampling = {0}; + redisReply *reply, *sample, **elements; + timing_t *tp = &baton->u.query.timing; + int i, sts, next, nelements; + int idx_series = np->value_set.num_series; + int idx_sample = 0; + sds msg, save_timestamp; + + sampling.value.timestamp = sdsempty(); + sampling.value.series = sdsempty(); + sampling.value.data = sdsempty(); + + /* iterate over the 'samples' array */ + for (i = 0; i < nsamples; i++) { + sample = samples[i]; + if ((nelements = sample->elements) == 0) + continue; + elements = sample->element; + + /* expecting timestamp:valueset pairs, then instance:value pairs */ + if (nelements % 2) { + infofmt(msg, "expected time:valueset pairs in %s XRANGE", series); + batoninfo(baton, PMLOG_RESPONSE, msg); + sts = -EPROTO; + break; + } + + /* verify the instance:value pairs array before proceeding */ + reply = elements[1]; + if (reply->type != REDIS_REPLY_ARRAY) { + infofmt(msg, "expected value array for series %s %s (type=%s)", + series, XRANGE, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + break; + } + + /* setup state variables used internally during selection process */ + if (sampling.setup == 0 && (tp->delta.tv_sec || tp->delta.tv_usec)) { + /* 'next' is a nanosecond precision time interval to step with */ + sampling.delta.tv_sec = tp->delta.tv_sec; + sampling.delta.tv_nsec = tp->delta.tv_usec * 1000; + + /* extract the first timestamp to kickstart the comparison process */ + if ((sts = extract_time(baton, series, elements[0], + &sampling.value.timestamp, + &sampling.value.ts)) < 0) { + baton->error = sts; + break; + } + /* 'goal' is the first target interval as an absolute timestamp */ + if (tp->start.tv_sec || tp->start.tv_usec) { + sampling.goal.tv_sec = tp->start.tv_sec; + sampling.goal.tv_nsec = tp->start.tv_usec * 1000; + } else { + sampling.goal = sampling.value.ts; + } + sampling.next_timestamp = sdsempty(); + sampling.subsampling = 1; + } + sampling.setup = 1; + + if (sampling.subsampling == 0) { + if ((sts = extract_time(baton, series, elements[0], + &sampling.value.timestamp, + &sampling.value.ts)) < 0) { + baton->error = sts; + continue; + } + } else if ((next = i + 1) < nsamples) { + /* + * Compare this point and the next to the ideal based on delta; + * skip over returning this value if the next one looks better. + */ + elements = samples[next]->element; + if ((sts = extract_time(baton, series, elements[0], + &sampling.next_timestamp, + &sampling.next_timespec)) < 0) { + baton->error = sts; + continue; + } else if ((sts = use_next_sample(&sampling)) == 1) { + goto next_sample; + } else if (sts == -1) { /* sampling reached the end */ + goto last_sample; + } + } /* else falls through and may call user-supplied callback */ + + /* check whether a user-requested sample count has been reached + * Here copy the sample results(instance values) to the node. + */ + if (tp->count && sampling.count++ >= tp->count) + break; + + idx_sample = i; + np->value_set.series_values[idx_series].series_sample[idx_sample].num_instances = reply->elements/2; + if ((np->value_set.series_values[idx_series].series_sample[idx_sample].series_instance = + (pmSeriesValue *)calloc(reply->elements/2, sizeof(pmSeriesValue))) == NULL) { + /* TODO: error report here */ + baton->error = -ENOMEM; + } + if ((sts = series_instance_store_to_node(baton, series, &sampling.value, + reply->elements, reply->element, np, idx_sample)) < 0) { + baton->error = sts; + goto last_sample; + } + + if (sampling.subsampling == 0) + continue; + +next_sample: + /* carefully swap time strings to avoid leaking memory */ + save_timestamp = sampling.next_timestamp; + sampling.next_timestamp = sampling.value.timestamp; + sampling.value.timestamp = save_timestamp; + sampling.value.ts = sampling.next_timespec; + } + +last_sample: + if (sampling.setup) + sdsfree(sampling.next_timestamp); + sdsfree(sampling.value.timestamp); + sdsfree(sampling.value.series); + sdsfree(sampling.value.data); +} + +static int +extract_series_desc(seriesQueryBaton *baton, pmSID series, + int nelements, redisReply **elements, pmSeriesDesc *desc) +{ + sds msg; + + if (nelements < 6) { + infofmt(msg, "bad reply from %s %s (%d)", series, HMGET, nelements); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + + /* were we given a non-metric series identifier? (e.g. an instance) */ + if (elements[0]->type == REDIS_REPLY_NIL) { + desc->indom = sdscpylen(desc->indom, "unknown", 7); + desc->pmid = sdscpylen(desc->pmid, "PM_ID_NULL", 10); + desc->semantics = sdscpylen(desc->semantics, "unknown", 7); + desc->source = sdscpylen(desc->source, "unknown", 7); + desc->type = sdscpylen(desc->type, "unknown", 7); + desc->units = sdscpylen(desc->units, "unknown", 7); + return 0; + } + + if (extract_string(baton, series, elements[0], &desc->indom, "indom") < 0) + return -EPROTO; + if (extract_string(baton, series, elements[1], &desc->pmid, "pmid") < 0) + return -EPROTO; + if (extract_string(baton, series, elements[2], &desc->semantics, "semantics") < 0) + return -EPROTO; + if (extract_sha1(baton, series, elements[3], &desc->source, "source") < 0) + return -EPROTO; + if (extract_string(baton, series, elements[4], &desc->type, "type") < 0) + return -EPROTO; + if (extract_string(baton, series, elements[5], &desc->units, "units") < 0) + return -EPROTO; + + return 0; +} + +static int +extract_series_node_desc(seriesQueryBaton *baton, pmSID series, + int nelements, redisReply **elements, pmSeriesDesc *desc) +{ + sds msg; + + if (nelements < 4 || elements[0]->type == REDIS_REPLY_NIL) { + infofmt(msg, "bad reply from %s %s (%d)", series, HMGET, nelements); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + + desc->pmid = sdsnew("511.0.0"); + if (extract_string(baton, series, elements[0], &desc->indom, "indom") < 0) + return -EPROTO; + if (extract_string(baton, series, elements[1], &desc->semantics, "semantics") < 0) + return -EPROTO; + desc->source = sdsnew(elements[2]->str); + if (extract_string(baton, series, elements[3], &desc->type, "type") < 0) + return -EPROTO; + if (extract_string(baton, series, elements[4], &desc->units, "units") < 0) + return -EPROTO; + return 0; +} + +static void +series_node_get_desc_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + series_sample_set_t *sample_set = (series_sample_set_t *) arg; + redisReply *reply = r; + int sts; + pmSeriesDesc *desc = &sample_set->series_desc; + seriesQueryBaton *baton = (seriesQueryBaton *)sample_set->baton; + sds msg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_node_get_desc_reply"); + + desc->indom = sdsempty(); + desc->pmid = sdsempty(); + desc->semantics = sdsempty(); + desc->source = sdsempty(); + desc->type = sdsempty(); + desc->units = sdsempty(); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array type from series %s %s (type=%s)", + sample_set->sid->name, HMGET, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else if ((sts = extract_series_node_desc(baton, sample_set->sid->name, + reply->elements, reply->element, desc)) < 0) + baton->error = sts; + + series_query_end_phase(baton); +} + +static void +series_node_get_desc(seriesQueryBaton *baton, sds sid_name, series_sample_set_t *sample_set) +{ + sds cmd, key; + + seriesBatonReference(baton, "series_node_get_desc"); + + key = sdscatfmt(sdsempty(), "pcp:desc:series:%S", sid_name); + cmd = redis_command(7); + cmd = redis_param_str(cmd, HMGET, HMGET_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_str(cmd, "indom", sizeof("indom")-1); + cmd = redis_param_str(cmd, "semantics", sizeof("semantics")-1); + cmd = redis_param_str(cmd, "source", sizeof("source")-1); + cmd = redis_param_str(cmd, "type", sizeof("type")-1); + cmd = redis_param_str(cmd, "units", sizeof("units")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, series_node_get_desc_reply, sample_set); + sdsfree(cmd); +} + +static int +series_store_metric_name(seriesQueryBaton *baton, series_sample_set_t *sample_set, + sds series, int nelements, redisReply **elements) +{ + redisMapEntry *entry; + redisReply *reply; + sds msg, key; + unsigned int i; + int sts = 0; + + key = sdsnewlen(SDS_NOINIT, 20); + for (i = 0; i < nelements; i++) { + reply = elements[i]; + if (reply->type == REDIS_REPLY_STRING) { + sdsclear(key); + key = sdscatlen(key, reply->str, reply->len); + if ((entry = redisMapLookup(namesmap, key)) != NULL){ + sample_set->metric_name = redisMapValue(entry); + } else { + infofmt(msg, "%s - timeseries string map", series); + batoninfo(baton, PMLOG_CORRUPT, msg); + sts = -EINVAL; + } + } else { + infofmt(msg, "expected string in %s set (type=%s)", + series, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + sts = -EPROTO; + } + } + sdsfree(key); + + return sts; +} + +static void +series_node_get_metric_name_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + series_sample_set_t *sample_set = (series_sample_set_t *) arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sample_set->baton; + redisReply *reply = r; + int sts; + sds msg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_node_get_metric_name_reply"); + + /* unpack - extract names for this source via context name map */ + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array from %s %s (type=%s)", + SMEMBERS, sample_set->sid->name, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else if ((sts = series_store_metric_name(baton, sample_set, sample_set->sid->name, + reply->elements, reply->element)) < 0) { + baton->error = sts; + } + series_query_end_phase(baton); +} + +static void +series_node_get_metric_name( + seriesQueryBaton *baton, seriesGetSID *sid, series_sample_set_t *sample_set) +{ + sds cmd, key; + + seriesBatonReference(baton, "series_node_get_metric_name"); + key = sdscatfmt(sdsempty(), "pcp:metric.name:series:%S", sid->name); + cmd = redis_command(2); + cmd = redis_param_str(cmd, SMEMBERS, SMEMBERS_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_node_get_metric_name_reply, sample_set); + sdsfree(cmd); +} + +/* + * Redis has returned replies about samples of series, save them into the corresponding node. + */ +static void +series_node_prepare_time_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + node_t *np = (node_t *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + redisReply *reply = r; + sds msg; + int idx = np->value_set.num_series; + seriesGetSID *sid = np->value_set.series_values[idx].sid; + + /* + * Got an reply contains series values which need to be saved into the corresponding + * node, but when this callback function be called, we need the information of SID of the + * series. Here we can not access SID unless store SIDs in node. That's why I add **SID into + * struct node_t in query.h + */ + seriesBatonCheckMagic(sid, MAGIC_SID, "series_node_prepare_time_reply"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_node_prepare_time_reply"); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array from %s XSTREAM values (type=%s)", + sid->name, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else { + /* calloc space to store series samples */ + np->value_set.series_values[idx].num_samples = reply->elements; + if ((np->value_set.series_values[idx].series_sample = + (series_instance_set_t *)calloc(reply->elements, sizeof(series_instance_set_t))) == NULL) { + /* TODO: error report here */ + baton->error = -ENOMEM; + } + /* Query for the desc of idx-th series */ + np->value_set.series_values[idx].baton = baton; + series_node_get_desc(baton, sid->name, &np->value_set.series_values[idx]); + series_node_get_metric_name(baton, sid, &np->value_set.series_values[idx]); + + series_values_store_to_node(baton, sid->name, reply->elements, reply->element, np); + np->value_set.num_series++; + } + series_query_end_phase(baton); +} + +static void +series_node_prepare_time(seriesQueryBaton *baton, series_set_t *query_series_set, node_t *np) +{ + timing_t *tp = &np->time; + unsigned char *series = query_series_set->series; + seriesGetSID *sid; + char buffer[64], revbuf[64]; + sds start, end, key, cmd; + unsigned int i, revlen = 0, reverse = 0; + int nseries = query_series_set->nseries; + + /* if only 'count' is requested, work back from most recent value */ + if ((reverse = series_value_count_only(tp)) != 0) { + revlen = pmsprintf(revbuf, sizeof(revbuf), "%u", reverse); + start = sdsnew("+"); + } else { + start = sdsnew(timeval_stream_str(&tp->start, buffer, sizeof(buffer))); + } + + if (pmDebugOptions.series) + fprintf(stderr, "START: %s\n", start); + + if (reverse) + end = sdsnew("-"); + else if (tp->end.tv_sec) + end = sdsnew(timeval_stream_str(&tp->end, buffer, sizeof(buffer))); + else + end = sdsnew("+"); /* "+" means "no end" - to the most recent */ + + if (pmDebugOptions.series) + fprintf(stderr, "END: %s\n", end); + + + /* calloc nseries samples store space */ + if ((np->value_set.series_values = + (series_sample_set_t *)calloc(nseries, sizeof(series_sample_set_t))) == NULL) { + /* TODO: error report here */ + baton->error = -ENOMEM; + } + + /* + * Query cache for the time series range (groups of instance:value + * pairs, with an associated timestamp). + */ + for (i = 0; i < nseries; i++, series += SHA1SZ) { + sid = calloc(1, sizeof(seriesGetSID)); + pmwebapi_hash_str(series, buffer, sizeof(buffer)); + + initSeriesGetSID(sid, buffer, 1, baton); + seriesBatonReference(baton, "series_prepare_time"); + + key = sdscatfmt(sdsempty(), "pcp:values:series:%S", sid->name); + + /* X[REV]RANGE key t1 t2 [count N] */ + if (reverse) { + cmd = redis_command(6); + cmd = redis_param_str(cmd, XREVRANGE, XREVRANGE_LEN); + } else { + cmd = redis_command(4); + cmd = redis_param_str(cmd, XRANGE, XRANGE_LEN); + } + cmd = redis_param_sds(cmd, key); + cmd = redis_param_sds(cmd, start); + cmd = redis_param_sds(cmd, end); + if (reverse) { + cmd = redis_param_str(cmd, "COUNT", sizeof("COUNT")-1); + cmd = redis_param_str(cmd, revbuf, revlen); + } + sdsfree(key); + np->value_set.series_values[i].baton = baton; + np->value_set.series_values[i].sid = sid; + /* Note: np->series_set.num_series is not equal to nseries in this function */ + redisSlotsRequest(baton->slots, cmd, + series_node_prepare_time_reply, np); + sdsfree(cmd); + + } + sdsfree(start); + sdsfree(end); +} + +/* + * When we encounter a data node (i.e. np->result.nseries!=0), + * query Redis for actual values and store them into this node + * because time series identifier will always be described in + * the top node of a subtree at the parser tree's bottom. + */ +static int +series_process_func(seriesQueryBaton *baton, node_t *np, int level) +{ + int sts, nelements = 0; + + if (np == NULL) + return 0; + + if (&np->result != NULL) + nelements = np->result.nseries; + + if (nelements != 0) { + np->value_set.num_series = 0; + np->baton = baton; + series_node_prepare_time(baton, &np->result, np); + return baton->error; + } + + if ((sts = series_process_func(baton, np->left, level+1)) < 0) + return sts; + return series_process_func(baton, np->right, level+1); +} + +static sds +series_expr_canonical(node_t *np, int idx) +{ + sds left, right, metric = NULL, statement = NULL; + + if (np == NULL) + return sdsempty(); + + /* first find each of the left and right hand sides, if any */ + switch (np->type) { + case N_INTEGER: + case N_NAME: + case N_DOUBLE: + case N_STRING: + case N_SCALE: + statement = sdsdup(np->value); + left = right = NULL; /* statement is a leaf in the expr tree */ + break; + + case N_EQ: + if (np->left->type == N_NAME && + strncmp(np->left->value, "metric.name", sdslen(np->left->value)) == 0) { + left = sdsempty(); + } else + left = series_expr_canonical(np->left, idx); + right = series_expr_canonical(np->right, idx); + break; + + case N_LT: + case N_LEQ: + case N_GLOB: + case N_GEQ: + case N_GT: + case N_NEQ: + case N_AND: + case N_OR: + case N_REQ: + case N_RNE: + case N_PLUS: + case N_MINUS: + case N_STAR: + case N_SLASH: + case N_RESCALE: + left = series_expr_canonical(np->left, idx); + right = series_expr_canonical(np->right, idx); + break; + + case N_AVG: + case N_SUM: + case N_MAX: + case N_MIN: + case N_RATE: + case N_ABS: + case N_FLOOR: + case N_SQRT: + case N_ROUND: + left = series_expr_canonical(np->left, idx); + right = NULL; + break; + + case N_LOG: + left = series_expr_canonical(np->left, idx); + right = np->right ? series_expr_canonical(np->right, idx) : NULL; + break; + default: + left = right = NULL; + break; + } + + /* form a merged canonical expression from component parts */ + switch (np->type) { + case N_PLUS: + statement = sdscatfmt(sdsempty(), "%S+%S", left, right); + break; + case N_MINUS: + statement = sdscatfmt(sdsempty(), "%S-%S", left, right); + break; + case N_STAR: + statement = sdscatfmt(sdsempty(), "%S*%S", left, right); + break; + case N_SLASH: + statement = sdscatfmt(sdsempty(), "%S/%S", left, right); + break; + case N_AVG: + statement = sdscatfmt(sdsempty(), "avg(%S)", left); + break; + case N_COUNT: + statement = sdscatfmt(sdsempty(), "count(%S)", left); + break; + case N_DELTA: + break; + case N_MAX: + statement = sdscatfmt(sdsempty(), "max(%S)", left); + break; + case N_MIN: + statement = sdscatfmt(sdsempty(), "min(%S)", left); + break; + case N_SUM: + statement = sdscatfmt(sdsempty(), "sum(%S)", left); + break; + case N_ANON: + break; + case N_RATE: + statement = sdscatfmt(sdsempty(), "rate(%S)", left); + break; + case N_INSTANT: + break; + case N_LT: + statement = sdscatfmt(sdsempty(), "%S<%S", left, right); + break; + case N_LEQ: + statement = sdscatfmt(sdsempty(), "%S<=%S", left, right); + break; + case N_EQ: + metric = sdsnew("metric.name"); + if (np->left->type == N_NAME && sdscmp(np->left->value, metric) == 0) + statement = sdsdup(right); + else + statement = sdscatfmt(sdsempty(), "%S==\"%S\"", left, right); + break; + case N_GLOB: + metric = sdsnew("metric.name"); + if (np->left->type == N_NAME && sdscmp(np->left->value, metric) == 0) + statement = sdscatfmt(sdsempty(), "%S", np->value_set.series_values[idx].metric_name); + else + statement = sdscatfmt(sdsempty(), "%S~~\"%S\"", left, right); + break; + case N_GEQ: + statement = sdscatfmt(sdsempty(), "%S>=%S", left, right); + break; + case N_GT: + statement = sdscatfmt(sdsempty(), "%S>%S", left, right); + break; + case N_NEQ: + statement = sdscatfmt(sdsempty(), "%S!=\"%S\"", left, right); + break; + case N_AND: + metric = sdsnew("metric.name"); + if ((np->left->type == N_EQ || np->left->type == N_GLOB) + && sdscmp(np->left->left->value, metric) == 0) + statement = sdscatfmt(sdsempty(), "%S{%S}", np->value_set.series_values[idx].metric_name, right); + else + statement = sdscatfmt(sdsempty(), "%S&&%S", left, right); + break; + case N_OR: + statement = sdscatfmt(sdsempty(), "%S||%S", left, right); + break; + case N_REQ: + statement = sdscatfmt(sdsempty(), "%S=~%S", left, right); + break; + case N_RNE: + statement = sdscatfmt(sdsempty(), "%S!~%S", left, right); + break; + case N_NEG: + break; + case N_RESCALE: + statement = sdscatfmt(sdsempty(), "rescale(%S,\"%S\")", left, right); + break; + case N_DEFINED: + break; + case N_ABS: + statement = sdscatfmt(sdsempty(), "abs(%S)", left); + break; + case N_FLOOR: + statement = sdscatfmt(sdsempty(), "floor(%S)", left); + break; + case N_LOG: + if (np->right == NULL) + statement = sdscatfmt(sdsempty(), "log(%S)", left); + else + statement = sdscatfmt(sdsempty(), "log(%S,%S)", left, right); + break; + case N_SQRT: + statement = sdscatfmt(sdsempty(), "sqrt(%S)", left); + break; + case N_ROUND: + statement = sdscatfmt(sdsempty(), "round(%S)", left); + break; + default: + break; + } + sdsfree(left); + sdsfree(right); + sdsfree(metric); + return statement ? statement : sdsempty(); +} + +static sds +series_function_hash(unsigned char *hash, node_t *np, int idx) +{ + sds identifier = series_expr_canonical(np, idx); + SHA1_CTX shactx; + const char prefix[] = "{\"series\":\"expr\",\"expr\":\""; + const char suffix[] = "\"}"; + + if (pmDebugOptions.query) + fprintf(stderr, "%s: canonical expr: \"%s\"\n", __FUNCTION__, identifier); + SHA1Init(&shactx); + SHA1Update(&shactx, (unsigned char *)prefix, sizeof(prefix)-1); + SHA1Update(&shactx, (unsigned char *)identifier, sdslen(identifier)); + SHA1Update(&shactx, (unsigned char *)suffix, sizeof(suffix)-1); + SHA1Final(hash, &shactx); + + return identifier; +} + +/* + * Report a timeseries result - timestamps and (instance) values from a node + */ +static void +series_node_values_report(seriesQueryBaton *baton, node_t *np) +{ + sds series; + int i, j, k; + + for (i = 0; i < np->value_set.num_series; i++) { + series = np->value_set.series_values[i].sid->name; + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + pmSeriesValue value = np->value_set.series_values[i].series_sample[j].series_instance[k]; + baton->callbacks->on_value(series, &value, baton->userdata); + } + } + } +} + +static int +series_rate_check(pmSeriesDesc desc) +{ + /* TODO: Do type check for rate function. return 0 when success. */ + if (strncmp(desc.semantics, "counter", sizeof("counter")-1) != 0) + return 1; + return 0; +} + +/* + * Compute rate between samples for each metric. + * The number of samples in result is one less than the original samples. + */ +static void +series_calculate_rate(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + pmSeriesValue s_pmval, t_pmval; + unsigned int n_instances, n_samples, i, j, k; + double s_data, t_data, mult; + char str[256]; + sds msg, expr; + int sts; + pmUnits units = {0}; + + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + n_samples = np->value_set.series_values[i].num_samples; + if (series_rate_check(np->value_set.series_values[i].series_desc) == 0) { + if (n_samples > 0) { + n_instances = np->value_set.series_values[i].series_sample[0].num_instances; + } + for (j = 1; j < n_samples; j++) { + if (np->value_set.series_values[i].series_sample[j].num_instances != n_instances) { + if (pmDebugOptions.query && pmDebugOptions.desperate) + fprintf(stderr, "Error: number of instances in each sample are not equal %d != %d.\n", + np->value_set.series_values[i].series_sample[j].num_instances, n_instances); + continue; + } + for (k = 0; k < n_instances; k++) { + t_pmval = np->value_set.series_values[i].series_sample[j-1].series_instance[k]; + s_pmval = np->value_set.series_values[i].series_sample[j].series_instance[k]; + if (strcmp(s_pmval.series, t_pmval.series) != 0) { + /* TODO: two SIDs of the instances' names between samples are different, report error. */ + if (pmDebugOptions.query) { + fprintf(stderr, "TODO: two SIDs of the instances' names between samples are different, report error."); + fprintf(stderr, "%s %s\n", s_pmval.series, t_pmval.series); + } + } + + /* compute rate/sec from delta value and delta timestamp */ + s_data = strtod(s_pmval.data, NULL); + t_data = strtod(t_pmval.data, NULL); + pmsprintf(str, sizeof(str), "%.6lf", (t_data - s_data) / pmTimespec_delta(&t_pmval.ts, &s_pmval.ts)); + + sdsfree(np->value_set.series_values[i].series_sample[j-1].series_instance[k].data); + sdsfree(np->value_set.series_values[i].series_sample[j-1].series_instance[k].timestamp); + np->value_set.series_values[i].series_sample[j-1].series_instance[k].data = sdsnew(str); + np->value_set.series_values[i].series_sample[j-1].series_instance[k].timestamp = + sdsnew(np->value_set.series_values[i].series_sample[j].series_instance[k].timestamp); + np->value_set.series_values[i].series_sample[j-1].series_instance[k].ts = + np->value_set.series_values[i].series_sample[j].series_instance[k].ts; + } + if (j == n_samples-1) { + /* Free the last sample */ + for (k = 0; k < n_instances; k++) { + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].timestamp); + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].series); + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + } + np->value_set.series_values[i].num_samples -= 1; + } + } + } else { + expr = series_expr_canonical(np->left, i); + infofmt(msg, "Can't rate convert '%s', counter semantics required\n", expr); + sdsfree(expr); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -n_samples; + } + sdsfree(np->value_set.series_values[i].series_desc.type); + sdsfree(np->value_set.series_values[i].series_desc.semantics); + if ((sts = pmParseUnitsStr( + np->value_set.series_values[i].series_desc.units, + &units, &mult, &msg)) < 0) { + free(msg); + } + sdsfree(np->value_set.series_values[i].series_desc.units); + units.dimTime -= 1; + units.scaleTime = PM_TIME_SEC; + np->value_set.series_values[i].series_desc.type = sdsnew("double"); + np->value_set.series_values[i].series_desc.semantics = sdsnew("instant"); + np->value_set.series_values[i].series_desc.units = sdsnew(pmUnitsStr(&units)); + } +} + +/* + * Compare and pick the maximal instance value(s) among samples for each metric. + */ +static void +series_calculate_max(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + unsigned int n_series, n_samples, n_instances, i, j, k; + double max_data, data; + int max_pointer; + sds msg; + + n_series = np->left->value_set.num_series; + np->value_set.num_series = n_series; + np->value_set.series_values = (series_sample_set_t *)calloc(n_series, sizeof(series_sample_set_t)); + for (i = 0; i < n_series; i++) { + n_samples = np->left->value_set.series_values[i].num_samples; + if (n_samples > 0) { + np->value_set.series_values[i].num_samples = 1; + np->value_set.series_values[i].series_sample = (series_instance_set_t *)calloc(1, sizeof(series_instance_set_t)); + n_instances = np->left->value_set.series_values[i].series_sample[0].num_instances; + np->value_set.series_values[i].series_sample[0].num_instances = n_instances; + np->value_set.series_values[i].series_sample[0].series_instance = (pmSeriesValue *)calloc(n_instances, sizeof(pmSeriesValue)); + for (k = 0; k < n_instances; k++) { + max_pointer = 0; + max_data = atof(np->left->value_set.series_values[i].series_sample[0].series_instance[k].data); + for (j = 1; j < n_samples; j++) { + if (np->left->value_set.series_values[i].series_sample[j].num_instances != n_instances) { + if (pmDebugOptions.query && pmDebugOptions.desperate) { + infofmt(msg, "number of instances in each sample are not equal\n"); + batoninfo(baton, PMLOG_ERROR, msg); + } + continue; + } + data = atof(np->left->value_set.series_values[i].series_sample[j].series_instance[k].data); + if (max_data < data) { + max_data = data; + max_pointer = j; + } + } + np->value_set.series_values[i].series_sample[0].series_instance[k].timestamp = + sdsnew(np->left->value_set.series_values[i].series_sample[max_pointer].series_instance[k].timestamp); + np->value_set.series_values[i].series_sample[0].series_instance[k].series = + sdsnew(np->left->value_set.series_values[i].series_sample[max_pointer].series_instance[k].series); + np->value_set.series_values[i].series_sample[0].series_instance[k].data = + sdsnew(np->left->value_set.series_values[i].series_sample[max_pointer].series_instance[k].data); + np->value_set.series_values[i].series_sample[0].series_instance[k].ts = + np->left->value_set.series_values[i].series_sample[max_pointer].series_instance[k].ts; + } + } else { + np->value_set.series_values[i].num_samples = 0; + } + np->value_set.series_values[i].sid = (seriesGetSID *)calloc(1, sizeof(seriesGetSID)); + np->value_set.series_values[i].sid->name = sdsnew(np->left->value_set.series_values[i].sid->name); + np->value_set.series_values[i].baton = np->left->value_set.series_values[i].baton; + np->value_set.series_values[i].series_desc = np->left->value_set.series_values[i].series_desc; + } +} + +/* + * Compare and pick the minimal instance value(s) among samples for each metric. + */ +static void +series_calculate_min(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + unsigned int n_series, n_samples, n_instances, i, j, k; + double min_data, data; + int min_pointer; + sds msg; + + n_series = np->left->value_set.num_series; + np->value_set.num_series = n_series; + np->value_set.series_values = (series_sample_set_t *)calloc(n_series, sizeof(series_sample_set_t)); + for (i = 0; i < n_series; i++) { + n_samples = np->left->value_set.series_values[i].num_samples; + if (n_samples > 0) { + np->value_set.series_values[i].num_samples = 1; + np->value_set.series_values[i].series_sample = (series_instance_set_t *)calloc(1, sizeof(series_instance_set_t)); + n_instances = np->left->value_set.series_values[i].series_sample[0].num_instances; + np->value_set.series_values[i].series_sample[0].num_instances = n_instances; + np->value_set.series_values[i].series_sample[0].series_instance = (pmSeriesValue *)calloc(n_instances, sizeof(pmSeriesValue)); + for (k = 0; k < n_instances; k++) { + min_pointer = 0; + min_data = atof(np->left->value_set.series_values[i].series_sample[0].series_instance[k].data); + for (j = 1; j < n_samples; j++) { + if (np->left->value_set.series_values[i].series_sample[j].num_instances != n_instances) { + if (pmDebugOptions.query && pmDebugOptions.desperate) { + infofmt(msg, "number of instances in each sample are not equal\n"); + batoninfo(baton, PMLOG_ERROR, msg); + } + continue; + } + data = atof(np->left->value_set.series_values[i].series_sample[j].series_instance[k].data); + if (min_data > data) { + min_data = data; + min_pointer = j; + } + } + np->value_set.series_values[i].series_sample[0].series_instance[k].timestamp = + sdsnew(np->left->value_set.series_values[i].series_sample[min_pointer].series_instance[k].timestamp); + np->value_set.series_values[i].series_sample[0].series_instance[k].series = + sdsnew(np->left->value_set.series_values[i].series_sample[min_pointer].series_instance[k].series); + np->value_set.series_values[i].series_sample[0].series_instance[k].data = + sdsnew(np->left->value_set.series_values[i].series_sample[min_pointer].series_instance[k].data); + np->value_set.series_values[i].series_sample[0].series_instance[k].ts = + np->left->value_set.series_values[i].series_sample[min_pointer].series_instance[k].ts; + } + } else { + np->value_set.series_values[i].num_samples = 0; + } + np->value_set.series_values[i].sid = (seriesGetSID *)calloc(1, sizeof(seriesGetSID)); + np->value_set.series_values[i].sid->name = sdsnew(np->left->value_set.series_values[i].sid->name); + np->value_set.series_values[i].baton = np->left->value_set.series_values[i].baton; + np->value_set.series_values[i].series_desc = np->left->value_set.series_values[i].series_desc; + } +} + +static int +compare_pmUnits_dim(pmUnits *a, pmUnits *b) +{ + if (a->dimCount == b->dimCount && + a->dimTime == b->dimTime && + a->dimSpace == b->dimSpace) + return 0; + return -1; +} + +const int +series_extract_type(char *typeStr) +{ + if (strncmp("32", typeStr, sizeof("32")-1) == 0) { + return PM_TYPE_32; + } else if ((strncmp("U32", typeStr, sizeof("U32")-1) == 0) || (strncmp("u32", typeStr, sizeof("u32")-1) == 0)) { + return PM_TYPE_U32; + } else if (strncmp("64", typeStr, sizeof("64")-1) == 0) { + return PM_TYPE_64; + } else if ((strncmp("U64", typeStr, sizeof("U64")-1) == 0) || (strncmp("u64", typeStr, sizeof("u64")-1) == 0)) { + return PM_TYPE_U64; + } else if ((strncmp("FLOAT", typeStr, sizeof("FLOAT")-1) == 0) || (strncmp("float", typeStr, sizeof("float")-1) == 0)) { + return PM_TYPE_FLOAT; + } else if ((strncmp("DOUBLE", typeStr, sizeof("DOUBLE")-1) == 0) || (strncmp("double", typeStr, sizeof("double")-1) == 0)) { + return PM_TYPE_DOUBLE; + } else { + return PM_TYPE_UNKNOWN; + } +} + +static int +series_extract_value(int type, sds str, pmAtomValue *oval) +{ + int sts; + + switch (type) { + case PM_TYPE_32: + sts = sscanf(str, "%d", &oval->l); + break; + case PM_TYPE_U32: + sts = sscanf(str, "%u", &oval->ul); + break; + case PM_TYPE_64: + sts = sscanf(str, "%" PRId64, &oval->ll); + break; + case PM_TYPE_U64: + sts = sscanf(str, "%" PRIu64, &oval->ull); + break; + case PM_TYPE_FLOAT: + sts = sscanf(str, "%f", &oval->f); + break; + case PM_TYPE_DOUBLE: + sts = sscanf(str, "%lf", &oval->d); + break; + default: + sts = 0; + break; + } + return (sts == 1) ? 0 : PM_ERR_CONV; +} + +static int +series_pmAtomValue_conv_str(int type, char *str, pmAtomValue *val, int max_len) +{ + char *s; + + switch (type) { + case PM_TYPE_32: + case PM_TYPE_U32: + case PM_TYPE_64: + case PM_TYPE_U64: + case PM_TYPE_FLOAT: + case PM_TYPE_DOUBLE: + s = pmAtomStr_r(val, type, str, max_len); + if (s && (isdigit(*s) || *s == '-' || *s == '+')) + return strlen(str); + break; + + default: + s = NULL; + break; + } + + pmNotifyErr(LOG_ERR, "series_pmAtomValue_conv_str: type=%s failed: %s\n", + pmTypeStr(type), s ? s : "only numeric types supported"); + return 0; +} + +/* + * The left child node of L_RESCALE should contains a set of time + * series values. And the right child node should be L_SCALE, which + * contains the target units information. This rescale() should only + * accept metrics with semantics instant. Compare the consistencies + * of 3 time/space/count dimensions between the pmUnits of input and + * metrics to be modified. + */ +static void +series_calculate_rescale(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + double mult; + pmUnits iunit; + char *errmsg, str_val[256]; + pmAtomValue ival, oval; + int type, sts, str_len, i, j, k; + sds msg; + + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + if (pmParseUnitsStr(np->value_set.series_values[i].series_desc.units, &iunit, &mult, &errmsg) < 0) { + infofmt(msg, "Units string of %s parse error, %s\n", np->value_set.series_values[i].sid->name, errmsg); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + free(errmsg); + return; + } + if (compare_pmUnits_dim(&iunit, &np->right->meta.units) != 0) { + infofmt(msg, "Dimensions of units mismatch, for series %s the units is %s\n", + np->value_set.series_values[i].sid->name, np->value_set.series_values[i].series_desc.units); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + if ((type = series_extract_type(np->value_set.series_values[i].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + type = PM_TYPE_DOUBLE; + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + if (series_extract_value(type, + np->value_set.series_values[i].series_sample[j].series_instance[k].data, &ival) != 0 ) { + /* TODO: error report for extracting values from string fail */ + fprintf(stderr, "Extract values from string fail\n"); + return; + } + if ((sts = pmConvScale(type, &ival, &iunit, &oval, &np->right->meta.units)) != 0) { + /* TODO: rescale error report */ + fprintf(stderr, "rescale error\n"); + return; + } + if ((str_len = series_pmAtomValue_conv_str(type, str_val, &oval, sizeof(str_val))) == 0) + return; + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + np->value_set.series_values[i].series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + sdsfree(np->value_set.series_values[i].series_desc.units); + np->value_set.series_values[i].series_desc.units = sdsnew(pmUnitsStr(&np->right->meta.units)); + } +} + +static int +series_abs_pmAtomValue(int type, pmAtomValue *val) +{ + int sts = 0; + + switch (type) { + case PM_TYPE_32: + if (val->l < 0) + val->l = -val->l; + break; + case PM_TYPE_64: + if (val->ll < 0) + val->ll = -val->ll; + break; + case PM_TYPE_U32: + case PM_TYPE_U64: + /* No need to change value */ + break; + case PM_TYPE_FLOAT: + if (val->f < 0) + val->f = -val->f; + break; + case PM_TYPE_DOUBLE: + if (val->d < 0) + val->d = -val->d; + break; + default: + /* Unsupported type */ + sts = -1; + break; + } + return sts; +} + +static void +series_calculate_abs(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + pmAtomValue val; + int type, sts, str_len, i, j, k; + char str_val[256]; + sds msg; + + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + if ((type = series_extract_type(np->value_set.series_values[i].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + if (series_extract_value(type, + np->value_set.series_values[i].series_sample[j].series_instance[k].data, &val) != 0 ) { + /* TODO: error report for extracting values from string fail */ + fprintf(stderr, "Extract values from string fail\n"); + return; + } + if ((sts = series_abs_pmAtomValue(type, &val)) != 0) { + /* TODO: unsupported type */ + fprintf(stderr, "Unsupport type to take abs()\n"); + return; + } + if ((str_len = series_pmAtomValue_conv_str(type, str_val, &val, sizeof(str_val))) == 0) + return; + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + np->value_set.series_values[i].series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + } +} + +/* + * calculate sum or avg series per-instance over time samples + */ +static void +series_calculate_statistical(node_t *np, nodetype_t func) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + unsigned int n_series, n_samples, n_instances, i, j, k; + double sum_data, data; + char sum_data_str[64]; + sds msg; + + assert(func == N_SUM || func == N_AVG); + + n_series = np->left->value_set.num_series; + np->value_set.num_series = n_series; + np->value_set.series_values = (series_sample_set_t *)calloc(n_series, sizeof(series_sample_set_t)); + for (i = 0; i < n_series; i++) { + n_samples = np->left->value_set.series_values[i].num_samples; + if (n_samples > 0) { + np->value_set.series_values[i].num_samples = 1; + np->value_set.series_values[i].series_sample = (series_instance_set_t *)calloc(1, sizeof(series_instance_set_t)); + n_instances = np->left->value_set.series_values[i].series_sample[0].num_instances; + np->value_set.series_values[i].series_sample[0].num_instances = n_instances; + np->value_set.series_values[i].series_sample[0].series_instance = (pmSeriesValue *)calloc(n_instances, sizeof(pmSeriesValue)); + for (k = 0; k < n_instances; k++) { + sum_data = 0.0; + for (j = 0; j < n_samples; j++) { + if (np->left->value_set.series_values[i].series_sample[j].num_instances != n_instances) { + if (pmDebugOptions.query && pmDebugOptions.desperate) { + infofmt(msg, "number of instances in each sample are not equal\n"); + batoninfo(baton, PMLOG_ERROR, msg); + } + continue; + } + data = strtod(np->left->value_set.series_values[i].series_sample[j].series_instance[k].data, NULL); + sum_data += data; + } + np->value_set.series_values[i].series_sample[0].series_instance[k].timestamp = + sdsnew(np->left->value_set.series_values[i].series_sample[0].series_instance[k].timestamp); + np->value_set.series_values[i].series_sample[0].series_instance[k].series = + sdsnew(np->left->value_set.series_values[i].series_sample[0].series_instance[k].series); + switch (func) { + case N_SUM: + pmsprintf(sum_data_str, sizeof(sum_data_str), "%le", sum_data); + break; + case N_AVG: + pmsprintf(sum_data_str, sizeof(sum_data_str), "%le", sum_data / n_samples); + break; + default: + /* .. TODO any other statistical functions such as stddev, variance, mode, median etc */ + break; + } + + np->value_set.series_values[i].series_sample[0].series_instance[k].data = sdsnew(sum_data_str); + np->value_set.series_values[i].series_sample[0].series_instance[k].ts = + np->left->value_set.series_values[i].series_sample[0].series_instance[k].ts; + } + } else { + np->value_set.series_values[i].num_samples = 0; + } + np->value_set.series_values[i].sid = (seriesGetSID *)calloc(1, sizeof(seriesGetSID)); + np->value_set.series_values[i].sid->name = sdsnew(np->left->value_set.series_values[i].sid->name); + np->value_set.series_values[i].baton = np->left->value_set.series_values[i].baton; + np->value_set.series_values[i].series_desc = np->left->value_set.series_values[i].series_desc; + + /* statistical result values are type double, but maybe this depends on the function and args */ + sdsfree(np->value_set.series_values[i].series_desc.type); + np->value_set.series_values[i].series_desc.type = sdsnew("double"); + } +} + +static int +series_floor_pmAtomValue(int type, pmAtomValue *val) +{ + int sts = 0; + + switch (type) { + case PM_TYPE_32: + case PM_TYPE_U32: + case PM_TYPE_64: + case PM_TYPE_U64: + /* No change */ + break; + case PM_TYPE_FLOAT: + val->f = floorf(val->f); + break; + case PM_TYPE_DOUBLE: + val->d = floor(val->d); + break; + default: + /* Unsupported type */ + sts = -1; + break; + } + + return sts; +} + +static void +series_calculate_floor(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + pmAtomValue val; + int type, sts, str_len, i, j, k; + char str_val[256]; + sds msg; + + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + if ((type = series_extract_type(np->value_set.series_values[i].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + if (series_extract_value(type, + np->value_set.series_values[i].series_sample[j].series_instance[k].data, &val) != 0 ) { + /* TODO: error report for extracting values from string fail */ + fprintf(stderr, "Extract values from string fail\n"); + return; + } + if ((sts = series_floor_pmAtomValue(type, &val)) != 0) { + /* TODO: unsupported type */ + fprintf(stderr, "Unsupport type to take abs()\n"); + return; + } + if ((str_len = series_pmAtomValue_conv_str(type, str_val, &val, sizeof(str_val))) == 0) + return; + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + np->value_set.series_values[i].series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + } +} + +static int +series_log_pmAtomValue(int itype, int *otype, pmAtomValue *val, int is_natural_log, double base) +{ + int sts = 0; + double res; + + switch (itype) { + case PM_TYPE_32: + res = val->l; + break; + case PM_TYPE_U32: + res = val->ul; + break; + case PM_TYPE_64: + res = val->ll; + break; + case PM_TYPE_U64: + res = val->ull; + break; + case PM_TYPE_FLOAT: + res = val->f; + break; + case PM_TYPE_DOUBLE: + res = val->d; + break; + default: + /* Unsupported type */ + sts = -1; + break; + } + + if (sts == 0) { + *otype = PM_TYPE_DOUBLE; + if (is_natural_log == 1) + val->d = log(res); + else + val->d = log(res)/log(base); + } + + return sts; +} + +/* + * Return the logarithm of x to base b (log_b^x). + */ +static void +series_calculate_log(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + double base; + pmAtomValue val; + int i, j, k, itype, otype=PM_TYPE_UNKNOWN; + int sts, str_len, is_natural_log; + char str_val[256]; + sds msg; + + + if (np->right != NULL) { + sscanf(np->right->value, "%lf", &base); + is_natural_log = 0; + } else { + is_natural_log = 1; + } + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + if ((itype = series_extract_type(np->value_set.series_values[i].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + if (series_extract_value(itype, + np->value_set.series_values[i].series_sample[j].series_instance[k].data, &val) != 0 ) { + /* TODO: error report for extracting values from string fail */ + fprintf(stderr, "Extract values from string fail\n"); + return; + } + if ((sts = series_log_pmAtomValue(itype, &otype, &val, is_natural_log, base)) != 0) { + /* TODO: unsupported type */ + fprintf(stderr, "Unsupport type to take log()\n"); + return; + } + if ((str_len = series_pmAtomValue_conv_str(otype, str_val, &val, sizeof(str_val))) == 0) + return; + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + np->value_set.series_values[i].series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + sdsfree(np->value_set.series_values[i].series_desc.type); + np->value_set.series_values[i].series_desc.type = sdsnew(pmTypeStr(otype)); + } +} + +static int +series_sqrt_pmAtomValue(int itype, int *otype, pmAtomValue *val) +{ + int sts = 0; + double res; + + switch (itype) { + case PM_TYPE_32: + *otype = PM_TYPE_DOUBLE; + res = val->l; + val->d = sqrt(res); + break; + case PM_TYPE_U32: + *otype = PM_TYPE_DOUBLE; + res = val->ul; + val->d = sqrt(res); + break; + case PM_TYPE_64: + *otype = PM_TYPE_DOUBLE; + res = val->ll; + val->d = sqrt(res); + break; + case PM_TYPE_U64: + *otype = PM_TYPE_DOUBLE; + res = val->ull; + val->d = sqrt(res); + break; + case PM_TYPE_FLOAT: + *otype = PM_TYPE_DOUBLE; + res = val->f; + val->d = sqrt(res); + break; + case PM_TYPE_DOUBLE: + val->d = sqrt(val->d); + break; + default: + /* Unsupported type */ + sts = -1; + break; + } + return sts; +} + +static void +series_calculate_sqrt(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + pmAtomValue val; + int i, j, k, itype, otype=PM_TYPE_UNKNOWN; + int sts, str_len; + char str_val[256]; + sds msg; + + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + if ((itype = series_extract_type(np->value_set.series_values[i].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + if (series_extract_value(itype, + np->value_set.series_values[i].series_sample[j].series_instance[k].data, &val) != 0 ) { + /* TODO: error report for extracting values from string fail */ + fprintf(stderr, "Extract values from string fail\n"); + return; + } + if ((sts = series_sqrt_pmAtomValue(itype, &otype, &val)) != 0) { + /* TODO: unsupported type */ + fprintf(stderr, "Unsupport type to take sqrt()\n"); + return; + } + if ((str_len = series_pmAtomValue_conv_str(otype, str_val, &val, sizeof(str_val))) == 0) + return; + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + np->value_set.series_values[i].series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + sdsfree(np->value_set.series_values[i].series_desc.type); + np->value_set.series_values[i].series_desc.type = sdsnew(pmTypeStr(otype)); + } +} + +static int +series_round_pmAtomValue(int type, pmAtomValue *val) +{ + int sts = 0; + + switch (type) { + case PM_TYPE_32: + case PM_TYPE_U32: + case PM_TYPE_64: + case PM_TYPE_U64: + /* No change */ + break; + case PM_TYPE_FLOAT: + val->f = roundf(val->f); + break; + case PM_TYPE_DOUBLE: + val->d = round(val->f); + break; + default: + /* Unsupported type */ + sts = -1; + break; + } + return sts; +} + +static void +series_calculate_round(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + pmAtomValue val; + int i, j, k, type, sts, str_len; + char str_val[256]; + sds msg; + + np->value_set = np->left->value_set; + for (i = 0; i < np->value_set.num_series; i++) { + if ((type = series_extract_type(np->value_set.series_values[i].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + np->value_set.series_values[i].num_samples = -np->value_set.series_values[i].num_samples; + return; + } + for (j = 0; j < np->value_set.series_values[i].num_samples; j++) { + for (k = 0; k < np->value_set.series_values[i].series_sample[j].num_instances; k++) { + if (series_extract_value(type, + np->value_set.series_values[i].series_sample[j].series_instance[k].data, &val) != 0 ) { + /* TODO: error report for extracting values from string fail */ + fprintf(stderr, "Extract values from string fail\n"); + return; + } + if ((sts = series_round_pmAtomValue(type, &val)) != 0) { + /* TODO: unsupported type */ + fprintf(stderr, "Unsupport type to take abs()\n"); + return; + } + if ((str_len = series_pmAtomValue_conv_str(type, str_val, &val, sizeof(str_val))) == 0) + return; + sdsfree(np->value_set.series_values[i].series_sample[j].series_instance[k].data); + np->value_set.series_values[i].series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + + } +} + +const int +pmStrSem(sds sem_str) +{ + if (strncmp("counter", sem_str, sizeof("counter")-1) == 0) + return PM_SEM_COUNTER; + if (strncmp("instant", sem_str, sizeof("instant")-1) == 0) + return PM_SEM_INSTANT; + if (strncmp("discrete", sem_str, sizeof("discrete")-1) == 0) + return PM_SEM_DISCRETE; + return -1; +} + +static int +series_calculate_binary_check(int ope_type, seriesQueryBaton *baton, + node_t *left, node_t *right, int *l_type, int *r_type, + int *l_sem, int *r_sem, pmUnits *l_units, pmUnits *r_units, + pmUnits *large_units, sds l_indom, sds r_indom) +{ + sds msg; + int num_samples; + double mult; + char *errmsg = NULL; + + /* + * Operands should have the same instance domain for all of + * the binary operators. + */ + if (sdscmp(l_indom, r_indom) != 0) { + infofmt(msg, "Operands should have the same instance domain for all of the binary operators.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + /* + * For addition and subtraction all dimensions for each of + * the operands and result are identical. + */ + if ((ope_type == N_PLUS || ope_type == N_MINUS) && + compare_pmUnits_dim(&left->meta.units, &right->meta.units) != 0) { + infofmt(msg, "Dimensions of two operands mismatch\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + + /* Number of samples of both operands should be identical. */ + num_samples = left->value_set.series_values[0].num_samples; + if (num_samples != right->value_set.series_values[0].num_samples) { + infofmt(msg, "Number of samples of two metrics are not identical, %s has %d but %s has %d\n", + left->value_set.series_values[0].sid->name, num_samples, + right->value_set.series_values[0].sid->name, right->value_set.series_values[0].num_samples); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + + /* + * For an arithmetic expression: + * - if both operands have the semantics of a counter, then only + * addition or subtraction is allowed + * - if the left operand is a counter and the right operand is not, + * then only multiplication or division are allowed + * - if the left operand is not a counter and the right operand is + * a counter, then only multiplication is allowed. + */ + *l_sem = pmStrSem(left->value_set.series_values[0].series_desc.semantics); + *r_sem = pmStrSem(right->value_set.series_values[0].series_desc.semantics); + if (*l_sem == PM_SEM_COUNTER && *r_sem == PM_SEM_COUNTER) { + if (ope_type != N_PLUS && ope_type != N_MINUS) { + infofmt(msg, "Both operands have the semantics of counter, only addition or subtraction is allowed.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + } + if ((*l_sem == PM_SEM_COUNTER && *r_sem !=PM_SEM_COUNTER)) { + if (ope_type != N_STAR && ope_type != N_SLASH) { + infofmt(msg, "Left operand is a counter and the right one is not, only multiplication or division is allowed.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + } + if (*l_sem != PM_SEM_COUNTER && *r_sem ==PM_SEM_COUNTER) { + if (ope_type != N_STAR) { + infofmt(msg, "Left operand is not a counter and the right one is, only multiplication is allowed.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + } + + /* Extract data tpyes of two operands */ + if ((*l_type = series_extract_type(left->value_set.series_values[0].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + if ((*r_type = series_extract_type(right->value_set.series_values[0].series_desc.type)) == PM_TYPE_UNKNOWN) { + infofmt(msg, "Series values' Type extract fail, unsupported type\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return -1; + } + /* Extract units of both operands */ + if (pmParseUnitsStr(left->value_set.series_values[0].series_desc.units, l_units, &mult, &errmsg) < 0 && + strncmp(left->value_set.series_values[0].series_desc.units, "none", sizeof("none")-1) != 0) { + infofmt(msg, "Units string of %s parse error, %s\n", left->value_set.series_values[0].sid->name, errmsg); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + free(errmsg); + return -1; + } else if (errmsg) { + free(errmsg); + errmsg = NULL; + } + if (pmParseUnitsStr(right->value_set.series_values[0].series_desc.units, r_units, &mult, &errmsg) < 0 && + strncmp(right->value_set.series_values[0].series_desc.units, "none", sizeof("none")-1) != 0) { + infofmt(msg, "Units string of %s parse error, %s\n", right->value_set.series_values[0].sid->name, errmsg); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + free(errmsg); + errmsg = NULL; + return -1; + } else if (errmsg) { + free(errmsg); + errmsg = NULL; + } + /* + * If both operands have a dimension of Count/Time/Space and the scales + * are not the same, use the larger scale and convert the values of the + * operand with the smaller scale. + * The result is promoted to type PM_TYPE_DOUBLE. + */ + large_units->scaleCount = l_units->scaleCount > r_units->scaleCount ? l_units->scaleCount : r_units->scaleCount; + large_units->scaleSpace = l_units->scaleSpace > r_units->scaleSpace ? l_units->scaleSpace : r_units->scaleSpace; + large_units->scaleTime = l_units->scaleTime > r_units->scaleTime ? l_units->scaleTime : r_units->scaleTime; + if (large_units->scaleCount != l_units->scaleCount || + large_units->scaleSpace != l_units->scaleSpace || + large_units->scaleTime != l_units->scaleTime) { + *l_type = PM_TYPE_DOUBLE; + } + if (large_units->scaleCount != r_units->scaleCount || + large_units->scaleSpace != r_units->scaleSpace || + large_units->scaleTime != r_units->scaleTime) { + *r_type = PM_TYPE_DOUBLE; + } + + return 0; +} + +int +calculate_plus(int *type, pmAtomValue *l_val, pmAtomValue *r_val, pmAtomValue *res) +{ + switch (*type) { + case PM_TYPE_32: + res->l = l_val->l + r_val->l; + break; + case PM_TYPE_U32: + res->ul = l_val->ul + r_val->ul; + break; + case PM_TYPE_64: + res->ll = l_val->ll + r_val->ll; + break; + case PM_TYPE_U64: + res->ull = l_val->ull + r_val->ull; + break; + case PM_TYPE_FLOAT: + res->f = l_val->f + r_val->f; + break; + case PM_TYPE_DOUBLE: + res->d = l_val->d + r_val->d; + break; + default: + break; + } + return 0; +} + +int +calculate_minus(int *type, pmAtomValue *l_val, pmAtomValue *r_val, pmAtomValue *res) +{ + switch (*type) { + case PM_TYPE_32: + res->l = l_val->l - r_val->l; + break; + case PM_TYPE_U32: + if (l_val->ul < r_val->ul) + return -1; + res->ul = l_val->ul - r_val->ul; + break; + case PM_TYPE_64: + res->ll = l_val->ll - r_val->ll; + break; + case PM_TYPE_U64: + if (l_val->ull < r_val->ull) + return -1; + res->ull = l_val->ull - r_val->ull; + break; + case PM_TYPE_FLOAT: + res->f = l_val->f - r_val->f; + break; + case PM_TYPE_DOUBLE: + res->d = l_val->d - r_val->d; + break; + default: + break; + } + return 0; +} + +int +calculate_star(int *type, pmAtomValue *l_val, pmAtomValue *r_val, pmAtomValue *res) +{ + switch (*type) { + case PM_TYPE_32: + res->l = l_val->l * r_val->l; + break; + case PM_TYPE_U32: + res->ul = l_val->ul * r_val->ul; + break; + case PM_TYPE_64: + res->ll = l_val->ll * r_val->ll; + break; + case PM_TYPE_U64: + res->ull = l_val->ull * r_val->ull; + break; + case PM_TYPE_FLOAT: + res->f = l_val->f * r_val->f; + break; + case PM_TYPE_DOUBLE: + res->d = l_val->d * r_val->d; + break; + default: + break; + } + return 0; +} + +int +calculate_slash(int *type, pmAtomValue *l_val, pmAtomValue *r_val, pmAtomValue *res) +{ + switch (*type) { + case PM_TYPE_32: + res->l = l_val->l / r_val->l; + break; + case PM_TYPE_U32: + res->ul = l_val->ul / r_val->ul; + break; + case PM_TYPE_64: + res->ll = l_val->ll / r_val->ll; + break; + case PM_TYPE_U64: + res->ull = l_val->ull / r_val->ull; + break; + case PM_TYPE_FLOAT: + res->f = l_val->f / r_val->f; + break; + case PM_TYPE_DOUBLE: + res->d = l_val->d / r_val->d; + break; + default: + break; + } + return 0; +} + +static void +series_calculate_order_binary(int ope_type, int l_type, int r_type, int *otype, + pmAtomValue *l_val, pmAtomValue *r_val, + pmSeriesValue *l_data, pmSeriesValue *r_data, + pmUnits *l_units, pmUnits *r_units, pmUnits *large_units, + int (*operator)(int*, pmAtomValue*, pmAtomValue*, pmAtomValue*)) +{ + pmAtomValue res; + int str_len; + char str_val[256]; + + if (l_type == PM_TYPE_DOUBLE || r_type == PM_TYPE_DOUBLE) { + *otype = PM_TYPE_DOUBLE; + } else if (ope_type == N_SLASH) { + *otype = PM_TYPE_DOUBLE; + } else if (l_type == PM_TYPE_FLOAT || r_type == PM_TYPE_FLOAT) { + *otype = PM_TYPE_FLOAT; + } else if (l_type == PM_TYPE_U64 || r_type == PM_TYPE_U64) { + *otype = PM_TYPE_U64; + } else if (l_type == PM_TYPE_64 || r_type == PM_TYPE_64) { + *otype = PM_TYPE_64; + } else if (l_type == PM_TYPE_U32 || r_type == PM_TYPE_U32) { + *otype = PM_TYPE_U32; + } else { /* both are PM_TYPE_32 */ + *otype = PM_TYPE_32; + } + + /* Extract series values */ + series_extract_value(*otype, r_data->data, r_val); + series_extract_value(*otype, l_data->data, l_val); + + /* Convert scale to larger one */ + if (pmConvScale(*otype, l_val, l_units, l_val, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); + if (pmConvScale(*otype, r_val, r_units, r_val, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); + + if ((*operator)(otype, l_val, r_val, &res) != 0) { + sdsfree(l_data->data); + l_data->data = sdsnew("no value"); /* TODO - error handling */ + } else { + sdsfree(l_data->data); + str_len = series_pmAtomValue_conv_str(*otype, str_val, &res, sizeof(str_val)); + l_data->data = sdsnewlen(str_val, str_len); + } +} + +static void +series_binary_meta_update(node_t *left, pmUnits *large_units, int *l_sem, int *r_sem, int *otype) +{ + int o_sem; + + /* Update units */ + sdsfree(left->value_set.series_values[0].series_desc.units); + left->value_set.series_values[0].series_desc.units = sdsnew(pmUnitsStr(large_units)); + + /* + * If the semantics of both operands is not a counter + * (i.e. PM_SEM_INSTANT or PM_SEM_DISCRETE) then the + * result will have semantics PM_SEM_INSTANT unless both + * operands are PM_SEM_DISCRETE in which case the result + * is also PM_SEM_DISCRETE. + */ + if (*l_sem == PM_SEM_DISCRETE && *r_sem == PM_SEM_DISCRETE) { + o_sem = PM_SEM_DISCRETE; + } else if (*l_sem != PM_SEM_COUNTER || *r_sem != PM_SEM_COUNTER) { + o_sem = PM_SEM_INSTANT; + } else { + o_sem = PM_SEM_COUNTER; + } + + /* override type of result value (if it's been set) */ + if (*otype != PM_TYPE_UNKNOWN) { + sdsfree(left->value_set.series_values[0].series_desc.type); + left->value_set.series_values[0].series_desc.type = sdsnew(pmTypeStr(*otype)); + } + + /* Update semantics */ + sdsfree(left->value_set.series_values[0].series_desc.semantics); + left->value_set.series_values[0].series_desc.semantics = sdsnew(pmSemStr(o_sem)); +} + +static void +series_calculate_plus(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + node_t *left = np->left, *right = np->right; + int l_type, r_type, otype=PM_TYPE_UNKNOWN; + int l_sem, r_sem, j, k; + unsigned int num_samples, num_instances; + pmAtomValue l_val, r_val; + pmUnits l_units = {0}, r_units = {0}, large_units = {0}; + sds msg; + + if (left->value_set.num_series == 0 || right->value_set.num_series == 0) + return; + + if (series_calculate_binary_check(N_PLUS, baton, left, right, + &l_type, &r_type, &l_sem, &r_sem, + &l_units, &r_units, &large_units, + left->value_set.series_values[0].series_desc.indom, + right->value_set.series_values[0].series_desc.indom) != 0) + return; + + num_samples = left->value_set.series_values[0].num_samples; + + for (j = 0; j < num_samples; j++) { + num_instances = left->value_set.series_values[0].series_sample[j].num_instances; + if (num_instances != right->value_set.series_values[0].series_sample[j].num_instances) { + infofmt(msg, "Number of instances of two metrics are inconsistent.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return; + } + for (k = 0; k < num_instances; k++) { + series_calculate_order_binary(N_PLUS, l_type, r_type, &otype, + &l_val, &r_val, + left->value_set.series_values[0].series_sample[j].series_instance + k, + right->value_set.series_values[0].series_sample[j].series_instance + k, + &l_units, &r_units, &large_units, calculate_plus); + } + } + /* + * For addition and subtraction all dimensions for + * each of the operands and result are identical. + */ + large_units.dimCount = l_units.dimCount; + large_units.dimSpace = l_units.dimSpace; + large_units.dimTime = l_units.dimTime; + + series_binary_meta_update(left, &large_units, &l_sem, &r_sem, &otype); + np->value_set = left->value_set; +} + +static void +series_calculate_minus(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + node_t *left = np->left, *right = np->right; + unsigned int num_samples, num_instances, j, k; + pmAtomValue l_val, r_val; + pmUnits l_units = {0}, r_units = {0}, large_units = {0}; + int l_type, r_type, otype=PM_TYPE_UNKNOWN; + int l_sem, r_sem; + sds msg; + + if (left->value_set.num_series == 0 || right->value_set.num_series == 0) + return; + + if (series_calculate_binary_check(N_MINUS, baton, left, right, + &l_type, &r_type, &l_sem, &r_sem, + &l_units, &r_units, &large_units, + left->value_set.series_values[0].series_desc.indom, + right->value_set.series_values[0].series_desc.indom) != 0) + return; + + num_samples = left->value_set.series_values[0].num_samples; + + for (j = 0; j < num_samples; j++) { + num_instances = left->value_set.series_values[0].series_sample[j].num_instances; + if (num_instances != right->value_set.series_values[0].series_sample[j].num_instances) { + infofmt(msg, "Number of instances of two metrics are inconsistent.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return; + } + for (k = 0; k < num_instances; k++) { + series_calculate_order_binary(N_MINUS, l_type, r_type, &otype, + &l_val, &r_val, + left->value_set.series_values[0].series_sample[j].series_instance + k, + right->value_set.series_values[0].series_sample[j].series_instance + k, + &l_units, &r_units, &large_units, calculate_minus); + } + } + /* + * For addition and subtraction all dimensions for each of + * the operands and result are identical. + */ + large_units.dimCount = l_units.dimCount; + large_units.dimSpace = l_units.dimSpace; + large_units.dimTime = l_units.dimTime; + + series_binary_meta_update(left, &large_units, &l_sem, &r_sem, &otype); + np->value_set = left->value_set; +} + +static void +series_calculate_star(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + node_t *left = np->left, *right = np->right; + unsigned int num_samples, num_instances, j, k; + pmAtomValue l_val, r_val; + pmUnits l_units = {0}, r_units = {0}, large_units = {0}; + int l_type, r_type, otype=PM_TYPE_UNKNOWN; + int l_sem, r_sem; + sds msg; + + if (left->value_set.num_series == 0 || right->value_set.num_series == 0) + return; + + if (series_calculate_binary_check(N_STAR, baton, left, right, + &l_type, &r_type, &l_sem, &r_sem, + &l_units, &r_units, &large_units, + left->value_set.series_values[0].series_desc.indom, + right->value_set.series_values[0].series_desc.indom) != 0) + return; + + num_samples = left->value_set.series_values[0].num_samples; + + for (j = 0; j < num_samples; j++) { + num_instances = left->value_set.series_values[0].series_sample[j].num_instances; + if (num_instances != right->value_set.series_values[0].series_sample[j].num_instances) { + infofmt(msg, "Number of instances of two metrics are inconsistent.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return; + } + for (k = 0; k < num_instances; k++) { + series_calculate_order_binary(N_STAR, l_type, r_type, &otype, + &l_val, &r_val, + left->value_set.series_values[0].series_sample[j].series_instance + k, + right->value_set.series_values[0].series_sample[j].series_instance + k, + &l_units, &r_units, &large_units, calculate_star); + } + } + /* + * For multiplication, the dimensions of the result are the + * sum of the dimensions of the operands. + */ + large_units.dimCount = l_units.dimCount + r_units.dimCount; + large_units.dimSpace = l_units.dimSpace + r_units.dimSpace; + large_units.dimTime = l_units.dimTime + r_units.dimTime; + + series_binary_meta_update(left, &large_units, &l_sem, &r_sem, &otype); + np->value_set = left->value_set; +} + +static void +series_calculate_slash(node_t *np) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)np->baton; + node_t *left = np->left, *right = np->right; + unsigned int num_samples, num_instances, j, k; + pmAtomValue l_val, r_val; + pmUnits l_units = {0}, r_units = {0}, large_units = {0}; + int l_type, r_type, otype=PM_TYPE_UNKNOWN; + int l_sem, r_sem; + sds msg; + + if (left->value_set.num_series == 0 || right->value_set.num_series == 0) return; + if (series_calculate_binary_check(N_SLASH, baton, left, right, &l_type, &r_type, &l_sem, &r_sem, + &l_units, &r_units, &large_units, left->value_set.series_values[0].series_desc.indom, + right->value_set.series_values[0].series_desc.indom) != 0) { + return; + } + num_samples = left->value_set.series_values[0].num_samples; + + for (j = 0; j < num_samples; j++) { + num_instances = left->value_set.series_values[0].series_sample[j].num_instances; + if (num_instances != right->value_set.series_values[0].series_sample[j].num_instances) { + infofmt(msg, "Number of instances of two metrics are inconsistent.\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + return; + } + for (k = 0; k < num_instances; k++) { + series_calculate_order_binary(N_SLASH, l_type, r_type, &otype, + &l_val, &r_val, + left->value_set.series_values[0].series_sample[j].series_instance + k, + right->value_set.series_values[0].series_sample[j].series_instance + k, + &l_units, &r_units, &large_units, calculate_slash); + } + } + /* + * For division, the dimensions of the result are the + * difference of the dimensions of the operands. + */ + large_units.dimCount = l_units.dimCount - r_units.dimCount; + large_units.dimSpace = l_units.dimSpace - r_units.dimSpace; + large_units.dimTime = l_units.dimTime - r_units.dimTime; + + series_binary_meta_update(left, &large_units, &l_sem, &r_sem, &otype); + np->value_set = left->value_set; + +} + +/* + * In this phase all time series values have been stored into nodes. + * Therefore we can directly calculate values of a node according to + * the semantics of this node. Do dfs here. + * In the process of unstacking from bottom of the parser tree, each + * time we encounter a function-type node, calculate the results and + * store them into this node. + */ +static int +series_calculate(seriesQueryBaton *baton, node_t *np, int level) +{ + int sts; + + if (np == NULL) + return 0; + if ((sts = series_calculate(baton, np->left, level+1)) < 0) + return sts; + if ((sts = series_calculate(baton, np->right, level+1)) < 0) + return sts; + + np->baton = baton; + switch (np->type) { + case N_RATE: + series_calculate_rate(np); + sts = N_RATE; + break; + case N_MAX: + series_calculate_max(np); + sts = N_MAX; + break; + case N_MIN: + series_calculate_min(np); + sts = N_MIN; + break; + case N_RESCALE: + series_calculate_rescale(np); + sts = N_RESCALE; + break; + case N_ABS: + series_calculate_abs(np); + sts = N_ABS; + break; + case N_FLOOR: + series_calculate_floor(np); + sts = N_FLOOR; + break; + case N_LOG: + series_calculate_log(np); + sts = N_LOG; + break; + case N_SQRT: + series_calculate_sqrt(np); + sts = N_SQRT; + break; + case N_ROUND: + series_calculate_round(np); + sts = N_ROUND; + break; + case N_PLUS: + series_calculate_plus(np); + sts = N_PLUS; + break; + case N_MINUS: + series_calculate_minus(np); + sts = N_MINUS; + break; + case N_STAR: + series_calculate_star(np); + sts = N_STAR; + break; + case N_SLASH: + series_calculate_slash(np); + sts = N_SLASH; + break; + case N_AVG: + series_calculate_statistical(np, N_AVG); + sts = N_AVG; + break; + case N_SUM: + series_calculate_statistical(np, N_SUM); + sts = N_SUM; + break; + default: + break; + } + return sts; +} + +static int +check_compatibility(pmUnits *units_a, pmUnits *units_b) +{ + if (compare_pmUnits_dim(units_a, units_b) == 0) { + return 0; + } else return -1; +} + +static void +series_compatibility_convert( + series_sample_set_t *set0, series_sample_set_t *set1, pmUnits *units0, pmUnits *units1, pmUnits *large_units) +{ + unsigned int j, k; + int type0, type1, str_len; + char str_val[256]; + pmAtomValue val0, val1; + + large_units->scaleCount = units0->scaleCount > units1->scaleCount ? units0->scaleCount : units1->scaleCount; + large_units->scaleSpace = units0->scaleSpace > units1->scaleSpace ? units0->scaleSpace : units1->scaleSpace; + large_units->scaleTime = units0->scaleTime > units1->scaleTime ? units0->scaleTime : units1->scaleTime; + + type0 = PM_TYPE_NOSUPPORT; + type1 = PM_TYPE_NOSUPPORT; + if (large_units->scaleCount != units0->scaleCount || + large_units->scaleSpace != units0->scaleSpace || + large_units->scaleTime != units0->scaleTime) { + type0 = PM_TYPE_DOUBLE; + for (j = 0; j < set0->num_samples; j++) { + for (k = 0; k < set0->series_sample[j].num_instances; k++) { + series_extract_value(type0, set0->series_sample[j].series_instance[k].data, &val0); + if (pmConvScale(type0, &val0, units0, &val0, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); + sdsfree(set0->series_sample[j].series_instance[k].data); + str_len = series_pmAtomValue_conv_str(type0, str_val, &val0, sizeof(str_val)); + set0->series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + sdsfree(set0->series_desc.type); + sdsfree(set0->series_desc.units); + set0->series_desc.type = sdsnew(pmTypeStr(type0)); + set0->series_desc.units = sdsnew(pmUnitsStr(large_units)); + } + if (large_units->scaleCount != units1->scaleCount || + large_units->scaleSpace != units1->scaleSpace || + large_units->scaleTime != units1->scaleTime) { + type1 = PM_TYPE_DOUBLE; + for (j = 0; j < set1->num_samples; j++) { + for (k = 0; k < set1->series_sample[j].num_instances; k++) { + series_extract_value(type1, set1->series_sample[j].series_instance[k].data, &val1); + if (pmConvScale(type1, &val1, units1, &val1, large_units) < 0) + memset(large_units, 0, sizeof(*large_units)); + sdsfree(set1->series_sample[j].series_instance[k].data); + str_len = series_pmAtomValue_conv_str(type1, str_val, &val1, sizeof(str_val)); + set1->series_sample[j].series_instance[k].data = sdsnewlen(str_val, str_len); + } + } + sdsfree(set1->series_desc.type); + sdsfree(set1->series_desc.units); + set1->series_desc.type = sdsnew(pmTypeStr(type1)); + set1->series_desc.units = sdsnew(pmUnitsStr(large_units)); + } +} + +static void +series_redis_hash_expression(seriesQueryBaton *baton, char *hashbuf, int len_hashbuf) +{ + unsigned char hash[20]; + sds key, msg; + char *errmsg; + node_t *np = &baton->u.query.root; + int i, j, num_series = np->value_set.num_series; + pmUnits units0, units1, large_units; + double mult; + pmSeriesExpr expr; + + for (i = 0; i < num_series; i++) + np->value_set.series_values[i].compatibility = 1; + + if (num_series > 0) { + expr.query = series_function_hash(hash, np, 0); + pmwebapi_hash_str(hash, hashbuf, len_hashbuf); + } + + for (i = 0; i < num_series; i++) { + if (!np->value_set.series_values[i].compatibility) { + infofmt(msg, "Descriptors for metric '%s' do not satisfy compatibility between different hosts/sources.\n", + np->value_set.series_values[i].metric_name); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + continue; + } + for (j = 0; j < num_series; j++) { + if (!np->value_set.series_values[j].compatibility || i == j) + continue; + + if (strncmp(np->value_set.series_values[i].series_desc.units, "none", 4) == 0) + memset(&units0, 0, sizeof(units0)); + else if (pmParseUnitsStr(np->value_set.series_values[i].series_desc.units, + &units0, &mult, &errmsg) != 0) { + np->value_set.series_values[i].compatibility = 0; + infofmt(msg, "Invalid units string: %s\n", + np->value_set.series_values[i].series_desc.units); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + free(errmsg); + break; + } + + if (strncmp(np->value_set.series_values[j].series_desc.units, "none", 4) == 0) + memset(&units1, 0, sizeof(units1)); + else if (pmParseUnitsStr(np->value_set.series_values[j].series_desc.units, + &units1, &mult, &errmsg) != 0) { + np->value_set.series_values[i].compatibility = 0; + infofmt(msg, "Invalid units string: %s\n", + np->value_set.series_values[j].series_desc.units); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + free(errmsg); + break; + } + + if (check_compatibility(&units0, &units1) != 0) { + np->value_set.series_values[j].compatibility = 0; + infofmt(msg, "Incompatible units between operand metrics or expressions\n"); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EPROTO; + break; + } else { + /* + * For series with the same metric names, if they have + * same dimensions but different scales, use the larger + * scale and convert the values with the smaller scale. + * The result is promoted to type PM_TYPE_DOUBLE. + */ + series_compatibility_convert(&np->value_set.series_values[i], + &np->value_set.series_values[j], + &units0, &units1, &large_units); + } + } + + if (baton->error != 0) + break; + + sdsfree(np->value_set.series_values[i].sid->name); + np->value_set.series_values[i].sid->name = sdsnew(hashbuf); + } + + if (baton->error == 0 && num_series > 0 && np->value_set.series_values[0].compatibility) { + /* descriptor, after the O(N^2) checking the descriptor of 1st series has been + * converted to the largest one. + */ + key = sdscatfmt(sdsempty(), "pcp:desc:series:%s", hashbuf); + sdsfree(np->value_set.series_values[0].series_desc.source); + np->value_set.series_values[0].series_desc.source = sdsnewlen(NULL, SHA1SZ); + series_hmset_function_desc(baton, key, &np->value_set.series_values[0].series_desc); + + /* expression */ + key = sdscatfmt(sdsempty(), "pcp:expr:series:%s", hashbuf); + series_hmset_function_expr(baton, key, expr.query); + } +} + +static void +series_query_report_values(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_report_values"); + seriesBatonCheckCount(baton, "series_query_report_values"); + + seriesBatonReference(baton, "series_query_report_values"); + series_prepare_time(baton, &baton->u.query.root.result); + series_query_end_phase(baton); +} + +static void +series_query_funcs_report_values(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + int has_function = 0; + char hashbuf[42]; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_funcs_report_values"); + seriesBatonCheckCount(baton, "series_query_funcs_report_values"); + + seriesBatonReference(baton, "series_query_funcs_report_values"); + + /* For function-type nodes, calculate actual values */ + has_function = series_calculate(baton, &baton->u.query.root, 0); + + /* + * Store the canonical query to Redis if this query statement has + * function operation. + */ + if (has_function) + series_redis_hash_expression(baton, hashbuf, sizeof(hashbuf)); + + /* time series values saved in root node so report them directly. */ + series_node_values_report(baton, &baton->u.query.root); + + series_query_end_phase(baton); +} + +static void +series_query_funcs(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_funcs"); + seriesBatonCheckCount(baton, "series_query_funcs"); + + seriesBatonReference(baton, "series_query_funcs"); + /* Process function-type node */ + series_process_func(baton, &baton->u.query.root, 0); + series_query_end_phase(baton); +} + +static void +series_query_desc(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_desc"); + seriesBatonCheckCount(baton, "series_query_desc"); + + seriesBatonReference(baton, "series_query_desc"); + series_expr_node_desc(baton, &baton->u.query.root); + series_query_end_phase(baton); +} + +static int +series_time_window(timing_t *tp) +{ + if (tp->count || tp->window.range || + tp->window.start || tp->window.end || + tp->window.count || tp->window.delta) + return 1; + return 0; +} + +static void +series_query_services(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + pmSeriesModule *module = baton->module; + seriesModuleData *data = getSeriesModuleData(module); + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_services"); + seriesBatonCheckCount(baton, "series_query_services"); + + seriesBatonReference(baton, "series_query_services"); + + /* attempt to re-use existing slots connections */ + if (data == NULL) { + baton->error = -ENOMEM; + } else if (data->slots) { + baton->slots = data->slots; + series_query_end_phase(baton); + } else { + baton->slots = data->slots = + redisSlotsConnect( + data->config, 1, baton->info, + series_query_end_phase, baton->userdata, + data->events, (void *)baton); + } +} + +int +series_solve(pmSeriesSettings *settings, + node_t *root, timing_t *timing, pmSeriesFlags flags, void *arg) +{ + seriesQueryBaton *baton; + unsigned int i = 0; + + if ((baton = calloc(1, sizeof(seriesQueryBaton))) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetQuery(baton, root, timing); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_query_services; + + /* Resolve label key names (via their map keys) */ + baton->phases[i++].func = series_query_maps; + + /* Resolve sets of series identifiers for leaf nodes */ + baton->phases[i++].func = series_query_eval; + + /* Perform final matching (set of) series solving */ + baton->phases[i++].func = series_query_expr; + + baton->phases[i++].func = series_query_mapping; + if ((flags & PM_SERIES_FLAG_METADATA) || !series_time_window(timing)) { + /* Store series descriptors into nodes */ + baton->phases[i++].func = series_query_desc; + /* Report matching series IDs, unless time windowing */ + baton->phases[i++].func = series_query_report_matches; + } else { + /* Store time series values into nodes */ + baton->phases[i++].func = series_query_funcs; + /* Report actual values */ + baton->phases[i++].func = series_query_funcs_report_values; + } + + /* final callback once everything is finished, free baton */ + baton->phases[i++].func = series_query_finished; + + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + return 0; +} + +/* build a reverse hash mapping */ +static void +reverse_map(seriesQueryBaton *baton, redisMap *map, int nkeys, redisReply **elements) +{ + redisReply *name, *hash; + sds msg, key, val; + unsigned int i; + + for (i = 0; i < nkeys; i += 2) { + hash = elements[i]; + name = elements[i+1]; + if (name->type == REDIS_REPLY_STRING) { + if (hash->type == REDIS_REPLY_STRING) { + key = sdsnewlen(hash->str, hash->len); + val = sdsnewlen(name->str, name->len); + redisMapInsert(map, key, val); + } else { + infofmt(msg, "expected string key for hashmap (type=%s)", + redis_reply_type(hash)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EINVAL; + } + } else { + infofmt(msg, "expected string name for hashmap (type=%s)", + redis_reply_type(name)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EINVAL; + } + } +} + +static void +series_map_lookup_expr_reply(redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + sds query; + sds msg; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_map_lookup_expr_reply"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_map_lookup_expr_reply"); + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY || reply->elements == 0)) { + infofmt(msg, "expected array of one string element (got %zu) from series %s %s (type=%s)", + reply->elements, sid->name, HMGET, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + } else if (reply->element[0]->type == REDIS_REPLY_STRING) { + query = sdsempty(); + if ((sts = extract_string(baton, sid->name, reply->element[0], &query, "query")) < 0) { + baton->error = sts; + } else { + /* call the on_metric callback, whatever it's set to by the caller */ + baton->u.lookup.func(sid->name, query, baton->userdata); + } + } + series_query_end_phase(baton); +} + +static void +series_map_lookup_expr(seriesQueryBaton *baton, sds series, void *arg) +{ + seriesGetSID *sidexpr; + sds key; + sds exprcmd; + + sidexpr = calloc(1, sizeof(seriesGetSID)); + initSeriesGetSID(sidexpr, series, 1, baton); + + seriesBatonReference(baton, "series_map_lookup_expr"); + + key = sdscatfmt(sdsempty(), "pcp:expr:series:%S", sidexpr->name); + exprcmd = redis_command(3); + exprcmd = redis_param_str(exprcmd, HMGET, HMGET_LEN); + exprcmd = redis_param_sds(exprcmd, key); + exprcmd = redis_param_str(exprcmd, "query", sizeof("query")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, exprcmd, series_map_lookup_expr_reply, sidexpr); + sdsfree(exprcmd); +} + +/* + * Produce the list of mapped names (requires reverse mapping from IDs) + */ +static int +series_map_reply(seriesQueryBaton *baton, sds series, + int nelements, redisReply **elements) +{ + redisMapEntry *entry; + redisReply *reply; + sds msg, key; + unsigned int i; + int sts = 0; + key = sdsnewlen(SDS_NOINIT, 20); + if (nelements == 0) { + /* expression - not mapped */ + if (pmDebugOptions.series || pmDebugOptions.query) + fprintf(stderr, "series_map_reply: fabricated SID %s\n", series); + series_map_lookup_expr(baton, series, baton->userdata); + } else { + /* name - get the mapped value */ + for (i = 0; i < nelements; i++) { + reply = elements[i]; + if (reply->type == REDIS_REPLY_STRING) { + sdsclear(key); + key = sdscatlen(key, reply->str, reply->len); + if ((entry = redisMapLookup(baton->u.lookup.map, key)) != NULL) + baton->u.lookup.func(series, redisMapValue(entry), baton->userdata); + else { + infofmt(msg, "%s - timeseries string map", series); + batoninfo(baton, PMLOG_CORRUPT, msg); + sts = -EINVAL; + } + } else { + infofmt(msg, "expected string in %s set (type=%s)", + series, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + sts = -EPROTO; + } + } + } + sdsfree(key); + + return sts; +} + +static void +series_map_keys_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + redisReply *reply = r; + redisReply *child; + sds val, msg; + unsigned int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_map_keys_callback"); + if (LIKELY(reply && reply->type == REDIS_REPLY_ARRAY)) { + val = sdsempty(); + for (i = 0; i < reply->elements; i++) { + child = reply->element[i]; + if (child->type == REDIS_REPLY_STRING) { + if (baton->u.lookup.pattern != NULL && + fnmatch(baton->u.lookup.pattern, child->str, 0) != 0) + continue; + val = sdscpylen(val, child->str, child->len); + baton->u.lookup.func(NULL, val, baton->userdata); + } else { + infofmt(msg, "bad response for string map %s (%s)", + HVALS, redis_reply_type(child)); + batoninfo(baton, PMLOG_RESPONSE, msg); + sdsfree(val); + baton->error = -EINVAL; + } + } + sdsfree(val); + } else { + infofmt(msg, "expected array from string map %s (reply=%s)", + HVALS, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + + baton->callbacks->on_done(baton->error, baton->userdata); + freeSeriesGetLookup(baton); +} + +static int +series_map_keys(seriesQueryBaton *baton, const char *name) +{ + sds cmd, key; + + key = sdscatfmt(sdsempty(), "pcp:map:%s", name); + cmd = redis_command(2); + cmd = redis_param_str(cmd, HVALS, HVALS_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_map_keys_callback, baton); + sdsfree(cmd); + return 0; +} + +static void +series_label_value_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetLabelMap *value = (seriesGetLabelMap *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)value->baton; + redisReply *reply = r; + redisMapEntry *entry; + pmSeriesLabel label; + sds msg; + + seriesBatonCheckMagic(value, MAGIC_LABELMAP, "series_label_value_reply"); + + /* unpack - produce reverse map of ids-to-values for each entry */ + if (LIKELY(reply && reply->type == REDIS_REPLY_ARRAY)) { + reverse_map(baton, value->map, reply->elements, reply->element); + } else { + infofmt(msg, "expected array from %s %s.%s.value (type=%s)", HGETALL, + "pcp:map:label", value->mapID, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + if (baton->error == 0) { + label.name = value->name; + if ((entry = redisMapLookup(value->map, value->mapID)) == NULL) + label.value = sdsnew("null"); + else + label.value = redisMapValue(entry); + + baton->callbacks->on_labelmap(value->series, &label, baton->userdata); + + if (entry == NULL) + sdsfree(label.value); + } else { + infofmt(msg, "%s - timeseries name map", value->series); + batoninfo(baton, PMLOG_CORRUPT, msg); + } + + freeSeriesGetLabelMap(value); + + series_query_end_phase(baton); +} + +static int +series_label_reply(seriesQueryBaton *baton, sds series, + int nelements, redisReply **elements) +{ + seriesGetLabelMap *labelmap; + redisMapEntry *entry; + redisReply *reply; + redisMap *vmap; + char hashbuf[42]; + sds msg, key, cmd, name, vkey, nmapID, vmapID; + unsigned int i, index; + int sts = 0; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_label_reply"); + + /* result verification first */ + if (nelements % 2) { + infofmt(msg, "expected even number of results from %s (not %d)", + HGETALL, nelements); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + for (i = 0; i < nelements; i++) { + reply = elements[i]; + if (reply->type != REDIS_REPLY_STRING) { + infofmt(msg, "expected only string results from %s (type=%s)", + HGETALL, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + } + + nmapID = sdsnewlen(SDS_NOINIT, 20); + vmapID = sdsnewlen(SDS_NOINIT, 20); + + /* perform the label value reverse lookup */ + nelements /= 2; + for (i = 0; i < nelements; i++) { + index = i * 2; + + sdsclear(nmapID); + nmapID = sdscatlen(nmapID, elements[index]->str, elements[index]->len); + sdsclear(vmapID); + vmapID = sdscatlen(vmapID, elements[index+1]->str, elements[index+1]->len); + + if ((entry = redisMapLookup(baton->u.lookup.map, nmapID)) != NULL) { + pmwebapi_hash_str((unsigned char *)nmapID, hashbuf, sizeof(hashbuf)); + vkey = sdscatfmt(sdsempty(), "label.%s.value", hashbuf); + vmap = redisMapCreate(vkey); + name = redisMapValue(entry); + + baton->callbacks->on_label(series, name, baton->userdata); + + if ((labelmap = calloc(1, sizeof(seriesGetLabelMap))) == NULL) { + infofmt(msg, "%s - label value lookup OOM", series); + batoninfo(baton, PMLOG_ERROR, msg); + sts = -ENOMEM; + if (vmap) /* Coverity CID308763 */ + redisMapRelease(vmap); + continue; + } + initSeriesGetLabelMap(labelmap, series, name, vmap, vmapID, vkey, baton); + + seriesBatonReference(baton, "series_label_reply"); + + pmwebapi_hash_str((unsigned char *)nmapID, hashbuf, sizeof(hashbuf)); + key = sdscatfmt(sdsempty(), "pcp:map:label.%s.value", hashbuf); + cmd = redis_command(2); + cmd = redis_param_str(cmd, HGETALL, HGETALL_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_label_value_reply, labelmap); + sdsfree(cmd); + } else { + infofmt(msg, "%s - timeseries label map", series); + batoninfo(baton, PMLOG_CORRUPT, msg); + sts = -EINVAL; + } + } + + sdsfree(nmapID); + sdsfree(vmapID); + return sts; +} + +static void +series_lookup_labels_callback( + redisClusterAsyncContext *c, void *r,void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + sds msg; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_lookup_labels_callback"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_labels_callback"); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array from %s %s:%s (type=%s)", + HGETALL, "pcp:labelvalue:series", sid->name, + redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else if ((sts = series_label_reply(baton, sid->name, + reply->elements, reply->element)) < 0) { + baton->error = sts; + } + freeSeriesGetSID(sid); + + series_query_end_phase(baton); +} + +static void +series_lookup_labels(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + seriesGetSID *sid; + sds cmd, key; + unsigned int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_labels"); + seriesBatonCheckCount(baton, "series_lookup_labels"); + + /* unpack - iterate over series and extract labels names and values */ + for (i = 0; i < baton->u.lookup.nseries; i++) { + seriesBatonReference(baton, "series_lookup_labels"); + sid = &baton->u.lookup.series[i]; + key = sdscatfmt(sdsempty(), "pcp:labelvalue:series:%S", sid->name); + cmd = redis_command(2); + cmd = redis_param_str(cmd, HGETALL, HGETALL_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_lookup_labels_callback, sid); + sdsfree(cmd); + } +} + +int +pmSeriesLabels(pmSeriesSettings *settings, int nseries, pmSID *series, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nseries < 0) + return -EINVAL; + bytes = sizeof(seriesQueryBaton) + (nseries * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetLookup(baton, nseries, series, settings->callbacks.on_label, labelsmap); + + if (nseries == 0) + return series_map_keys(baton, redisMapName(baton->u.lookup.map)); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_lookup_mapping; + baton->phases[i++].func = series_lookup_labels; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "labels.calls", NULL, 1); + return 0; +} + +static void +series_lookup_labelvalues_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + redisReply *child; + pmSeriesLabel label; + unsigned int i; + sds msg; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_lookup_labelvalues_callback"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_labelvalues_callback"); + + if (LIKELY(reply && reply->type == REDIS_REPLY_ARRAY)) { + label.name = sid->name; + label.value = sdsempty(); + + for (i = 0; i < reply->elements; i++) { + child = reply->element[i]; + if (child->type == REDIS_REPLY_STRING) { + label.value = sdscpylen(label.value, child->str, child->len); + baton->callbacks->on_labelmap(NULL, &label, baton->userdata); + } else { + infofmt(msg, "bad response for string map %s (%s)", + HVALS, redis_reply_type(child)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EINVAL; + } + } + sdsfree(label.value); + } else { + infofmt(msg, "expected array from string map %s (reply=%s)", + HVALS, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + freeSeriesGetSID(sid); + + series_query_end_phase(baton); +} + +static void +series_lookup_labelvalues(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + seriesGetSID *sid; + sds cmd, key; + unsigned char hash[20]; + char buffer[42]; + unsigned int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_labelvalues"); + seriesBatonCheckCount(baton, "series_lookup_labelvalues"); + + for (i = 0; i < baton->u.lookup.nseries; i++) { + sid = &baton->u.lookup.series[i]; + seriesBatonReference(baton, "series_lookup_labelvalues"); + + pmwebapi_string_hash(hash, sid->name, sdslen(sid->name)); + key = sdscatfmt(sdsempty(), "pcp:map:label.%s.value", + pmwebapi_hash_str(hash, buffer, sizeof(buffer))); + cmd = redis_command(2); + cmd = redis_param_str(cmd, HVALS, HVALS_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_lookup_labelvalues_callback, sid); + sdsfree(cmd); + } +} + +int +pmSeriesLabelValues(pmSeriesSettings *settings, int nlabels, pmSID *labels, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nlabels <= 0) + return -EINVAL; + bytes = sizeof(seriesQueryBaton) + (nlabels * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetLookup(baton, nlabels, labels, NULL, NULL); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_lookup_labelvalues; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "labelvalues.calls", NULL, 1); + return 0; +} + + +static void +redis_series_desc_reply( + redisClusterAsyncContext *c, void *r, void *arg) +{ + pmSeriesDesc desc; + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + sds msg; + int sts; + + desc.indom = sdsempty(); + desc.pmid = sdsempty(); + desc.semantics = sdsempty(); + desc.source = sdsempty(); + desc.type = sdsempty(); + desc.units = sdsempty(); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array type from series %s %s (type=%s)", + sid->name, HMGET, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + else if ((sts = extract_series_desc(baton, sid->name, + reply->elements, reply->element, &desc)) < 0) + baton->error = sts; + else if ((sts = baton->callbacks->on_desc(sid->name, &desc, baton->userdata)) < 0) + baton->error = sts; + + sdsfree(desc.indom); + sdsfree(desc.pmid); + sdsfree(desc.semantics); + sdsfree(desc.source); + sdsfree(desc.type); + sdsfree(desc.units); + + series_query_end_phase(baton); +} + +static void +series_lookup_desc(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + seriesGetSID *sid; + sds cmd, key; + unsigned int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_desc"); + seriesBatonCheckCount(baton, "series_lookup_desc"); + + for (i = 0; i < baton->u.lookup.nseries; i++) { + sid = &baton->u.lookup.series[i]; + seriesBatonReference(baton, "series_lookup_desc"); + + key = sdscatfmt(sdsempty(), "pcp:desc:series:%S", sid->name); + cmd = redis_command(8); + cmd = redis_param_str(cmd, HMGET, HMGET_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_str(cmd, "indom", sizeof("indom")-1); + cmd = redis_param_str(cmd, "pmid", sizeof("pmid")-1); + cmd = redis_param_str(cmd, "semantics", sizeof("semantics")-1); + cmd = redis_param_str(cmd, "source", sizeof("source")-1); + cmd = redis_param_str(cmd, "type", sizeof("type")-1); + cmd = redis_param_str(cmd, "units", sizeof("units")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, redis_series_desc_reply, sid); + sdsfree(cmd); + } +} + +int +pmSeriesDescs(pmSeriesSettings *settings, int nseries, pmSID *series, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nseries <= 0) + return -EINVAL; + + bytes = sizeof(seriesQueryBaton) + (nseries * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetLookup(baton, nseries, series, NULL, NULL); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_lookup_desc; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "descs.calls", NULL, 1); + return 0; +} + +static int +extract_series_inst(seriesQueryBaton *baton, seriesGetSID *sid, + pmSeriesInst *inst, int nelements, redisReply **elements) +{ + sds msg, series = sid->metric; + + if (nelements < 3) { + infofmt(msg, "bad reply from %s %s (%d)", series, HMGET, nelements); + batoninfo(baton, PMLOG_RESPONSE, msg); + return -EPROTO; + } + + if (extract_string(baton, series, elements[0], &inst->instid, "inst") < 0) + return -EPROTO; + if (extract_mapping(baton, series, elements[1], &inst->name, "name") < 0) + return -EPROTO; + if (extract_sha1(baton, series, elements[2], &inst->source, "source") < 0) + return -EPROTO; + + /* return instance series identifiers, not the metric series */ + inst->series = sdscpylen(inst->series, sid->name, sdslen(sid->name)); + return 0; +} + +static void +series_instances_reply_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + pmSeriesInst inst; + sds msg; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_instances_reply_callback"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_instances_reply_callback"); + + inst.instid = sdsempty(); + inst.name = sdsempty(); + inst.source = sdsempty(); + inst.series = sdsempty(); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array from series %s %s (type=%s)", + HMGET, sid->name, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + else if ((sts = extract_series_inst(baton, sid, &inst, + reply->elements, reply->element)) < 0) + baton->error = sts; + else if ((sts = baton->callbacks->on_inst(sid->metric, &inst, baton->userdata)) < 0) + baton->error = sts; + freeSeriesGetSID(sid); + + sdsfree(inst.instid); + sdsfree(inst.name); + sdsfree(inst.source); + sdsfree(inst.series); + + series_query_end_phase(baton); +} + +static void +series_instances_reply(seriesQueryBaton *baton, + pmSID series, int nelements, redisReply **elements) +{ + seriesGetSID *sid; + pmSID name = sdsempty(); + sds key, cmd; + int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_instances_reply"); + + /* + * Iterate over the instance series identifiers, looking up + * the instance hash contents for each. + */ + for (i = 0; i < nelements; i++) { + if ((sid = calloc(1, sizeof(seriesGetSID))) == NULL) { + /* TODO: report error */ + continue; + } + initSeriesGetSID(sid, series, 1, baton); + sid->metric = sdsdup(series); + + if (extract_sha1(baton, series, elements[i], &sid->name, "series") < 0) { + /* TODO: report error */ + freeSeriesGetSID(sid); /* Coverity CID308764 */ + continue; + } + seriesBatonReference(sid, "series_instances_reply"); + seriesBatonReference(baton, "series_instances_reply"); + + key = sdscatfmt(sdsempty(), "pcp:inst:series:%S", sid->name); + cmd = redis_command(5); + cmd = redis_param_str(cmd, HMGET, HMGET_LEN); + cmd = redis_param_sds(cmd, key); + cmd = redis_param_str(cmd, "inst", sizeof("inst")-1); + cmd = redis_param_str(cmd, "name", sizeof("name")-1); + cmd = redis_param_str(cmd, "source", sizeof("source")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_instances_reply_callback, sid); + sdsfree(cmd); + } + sdsfree(name); +} + +static void +series_inst_expr_reply(redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + pmSeriesExpr expr = {0}; + sds msg; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_inst_expr_reply"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_inst_expr_reply"); + + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array of one string element (got %zu) from series %s %s (type=%s)", + reply->elements, sid->name, HMGET, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + } else if (reply->element[0]->type == REDIS_REPLY_STRING) { + expr.query = sdsempty(); + if ((sts = extract_string(baton, sid->name, reply->element[0], &expr.query, "query")) < 0) { + baton->error = sts; + } else { + /* Parse the expr (with timing) and series solve the resulting expr tree */ + baton->u.query.timing.count = 1; + baton->error = series_solve_sid_expr(&series_solve_inst_settings, &expr, arg); + } + } + series_query_end_phase(baton); +} + +void +series_lookup_instances_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + seriesGetSID *expr; + sds key, exprcmd; + sds msg; + + seriesBatonCheckMagic(sid, MAGIC_SID, "series_lookup_instances_callback"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_instances_callback"); + + if (LIKELY(reply && reply->type == REDIS_REPLY_ARRAY)) { + if (reply->elements > 0) { + /* regular series */ + series_instances_reply(baton, sid->name, reply->elements, reply->element); + } else { + /* Handle fabricated/expression SID in /series/instances : + * - get the expr for sid->name from redis. In the callback for that, + * parse the expr and then solve the expression tree with timing from + * this series query baton, then merge the instances into the reply. + */ + if (pmDebugOptions.query) + fprintf(stderr, "series_lookup_instances_callback: sid %s is fabricated\n", sid->name); + expr = calloc(1, sizeof(seriesGetSID)); + initSeriesGetSID(expr, sid->name, 1, baton); + seriesBatonReference(baton, "series_lookup_instances_callback"); + + key = sdscatfmt(sdsempty(), "pcp:expr:series:%S", expr->name); + exprcmd = redis_command(3); + exprcmd = redis_param_str(exprcmd, HMGET, HMGET_LEN); + exprcmd = redis_param_sds(exprcmd, key); + exprcmd = redis_param_str(exprcmd, "query", sizeof("query")-1); + sdsfree(key); + redisSlotsRequest(baton->slots, exprcmd, series_inst_expr_reply, expr); + sdsfree(exprcmd); + } + } else { + infofmt(msg, "expected array from series %s %s (type=%s)", + SMEMBERS, sid->name, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + + series_query_end_phase(baton); +} + +static void +series_lookup_instances(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + seriesGetSID *sid; + sds cmd, key; + int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_instances_callback"); + seriesBatonCheckCount(baton, "series_lookup_instances_callback"); + + for (i = 0; i < baton->u.lookup.nseries; i++) { + seriesBatonReference(baton, "series_lookup_instances_callback"); + sid = &baton->u.lookup.series[i]; + key = sdscatfmt(sdsempty(), "pcp:instances:series:%S", sid->name); + cmd = redis_command(2); + cmd = redis_param_str(cmd, SMEMBERS, SMEMBERS_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_lookup_instances_callback, sid); + sdsfree(cmd); + } +} + +int +pmSeriesInstances(pmSeriesSettings *settings, int nseries, pmSID *series, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nseries < 0) + return -EINVAL; + bytes = sizeof(seriesQueryBaton) + (nseries * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetLookup(baton, nseries, series, settings->callbacks.on_instance, instmap); + + if (nseries == 0) + return series_map_keys(baton, redisMapName(baton->u.lookup.map)); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_lookup_mapping; + baton->phases[i++].func = series_lookup_instances; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "instances.calls", NULL, 1); + return 0; +} + +static void +redis_lookup_mapping_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + redisReply *reply = r; + sds msg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "redis_lookup_mapping_callback"); + + /* unpack - produce reverse map of ids-to-names for each context */ + if (LIKELY(reply && reply->type == REDIS_REPLY_ARRAY)) { + reverse_map(baton, baton->u.lookup.map, reply->elements, reply->element); + } else { + infofmt(msg, "expected array from %s %s (type=%s)", + HGETALL, "pcp:map:context.name", redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + + series_query_end_phase(baton); +} + +static void +series_lookup_mapping(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + sds cmd, key; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_mapping"); + seriesBatonCheckCount(baton, "series_lookup_mapping"); + seriesBatonReference(baton, "series_lookup_mapping"); + + key = sdscatfmt(sdsempty(), "pcp:map:%s", redisMapName(baton->u.lookup.map)); + cmd = redis_command(2); + cmd = redis_param_str(cmd, HGETALL, HGETALL_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + redis_lookup_mapping_callback, baton); + sdsfree(cmd); +} + +static void +series_query_mapping_callback( + redisClusterAsyncContext *c, void *r, void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + redisReply *reply = r; + sds msg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_mapping_callback"); + + /* unpack - produce reverse map of ids-to-names for each context */ + if (LIKELY(reply && reply->type == REDIS_REPLY_ARRAY)) { + reverse_map(baton, namesmap, reply->elements, reply->element); + } else { + infofmt(msg, "expected array from %s %s (type=%s)", + HGETALL, "pcp:map:context.name", redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } + + series_query_end_phase(baton); +} + +static void +series_query_mapping(void *arg){ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + sds cmd, key; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_query_mapping"); + seriesBatonCheckCount(baton, "series_query_mapping"); + seriesBatonReference(baton, "series_query_mapping"); + + key = sdsnew("pcp:map:metric.name"); + cmd = redis_command(2); + cmd = redis_param_str(cmd, HGETALL, HGETALL_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + series_query_mapping_callback, baton); + sdsfree(cmd); +} + +static void +series_lookup_finished(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_finished"); + baton->callbacks->on_done(baton->error, baton->userdata); + freeSeriesGetLookup(baton); +} + +static void +series_lookup_services(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + pmSeriesModule *module = baton->module; + seriesModuleData *data = getSeriesModuleData(module); + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_services"); + seriesBatonReference(baton, "series_lookup_services"); + + /* attempt to re-use existing slots connections */ + if (data == NULL) { + baton->error = -ENOMEM; + } else if (data->slots) { + baton->slots = data->slots; + series_query_end_phase(baton); + } else { + baton->slots = data->slots = + redisSlotsConnect( + data->config, 1, baton->info, + series_query_end_phase, baton->userdata, + data->events, (void *)baton); + } +} + +static void +redis_get_sid_callback( + redisClusterAsyncContext *redis, void *r, void *arg) +{ + seriesGetSID *sid = (seriesGetSID *)arg; + seriesQueryBaton *baton = (seriesQueryBaton *)sid->baton; + redisReply *reply = r; + sds msg; + int sts; + + seriesBatonCheckMagic(sid, MAGIC_SID, "redis_get_sid_callback"); + seriesBatonCheckMagic(baton, MAGIC_QUERY, "redis_get_sid_callback"); + + /* unpack - extract names for this source via context name map */ + if (UNLIKELY(reply == NULL || reply->type != REDIS_REPLY_ARRAY)) { + infofmt(msg, "expected array from %s %s (type=%s)", + SMEMBERS, sid->name, redis_reply_type(reply)); + batoninfo(baton, PMLOG_RESPONSE, msg); + baton->error = -EPROTO; + } else if ((sts = series_map_reply(baton, sid->name, + reply->elements, reply->element)) < 0) { + baton->error = sts; + } + series_query_end_phase(baton); +} + +static void +series_lookup_sources(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + seriesGetSID *sid; + sds cmd, key; + unsigned int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_sources"); + seriesBatonCheckCount(baton, "series_lookup_sources"); + seriesBatonReference(baton, "series_lookup_sources"); + + for (i = 0; i < baton->u.lookup.nseries; i++) { + seriesBatonReference(baton, "series_lookup_sources"); + sid = &baton->u.lookup.series[i]; + key = sdscatfmt(sdsempty(), "pcp:context.name:source:%S", sid->name); + cmd = redis_command(2); + cmd = redis_param_str(cmd, SMEMBERS, SMEMBERS_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + redis_get_sid_callback, sid); + sdsfree(cmd); + } + series_query_end_phase(baton); +} + +int +pmSeriesSources(pmSeriesSettings *settings, int nsources, pmSID *sources, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nsources < 0) + return -EINVAL; + bytes = sizeof(seriesQueryBaton) + (nsources * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetLookup(baton, nsources, sources, settings->callbacks.on_context, contextmap); + + if (nsources == 0) + return series_map_keys(baton, redisMapName(baton->u.lookup.map)); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_lookup_mapping; + baton->phases[i++].func = series_lookup_sources; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "sources.calls", NULL, 1); + return 0; +} + +static void +series_lookup_metrics(void *arg) +{ + seriesQueryBaton *baton = (seriesQueryBaton *)arg; + seriesGetSID *sid; + sds cmd, key; + unsigned int i; + + seriesBatonCheckMagic(baton, MAGIC_QUERY, "series_lookup_metrics"); + seriesBatonCheckCount(baton, "series_lookup_metrics"); + + for (i = 0; i < baton->u.lookup.nseries; i++) { + seriesBatonReference(baton, "series_lookup_metrics"); + sid = &baton->u.lookup.series[i]; + key = sdscatfmt(sdsempty(), "pcp:metric.name:series:%S", sid->name); + cmd = redis_command(2); + cmd = redis_param_str(cmd, SMEMBERS, SMEMBERS_LEN); + cmd = redis_param_sds(cmd, key); + sdsfree(key); + redisSlotsRequest(baton->slots, cmd, + redis_get_sid_callback, sid); + sdsfree(cmd); + } +} + +int +pmSeriesMetrics(pmSeriesSettings *settings, int nseries, sds *series, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nseries < 0) + return -EINVAL; + bytes = sizeof(seriesQueryBaton) + (nseries * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetLookup(baton, nseries, series, settings->callbacks.on_metric, namesmap); + + if (nseries == 0) + return series_map_keys(baton, redisMapName(baton->u.lookup.map)); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_lookup_mapping; + baton->phases[i++].func = series_lookup_metrics; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "metrics.calls", NULL, 1); + return 0; +} + +static void +parsedelta(seriesQueryBaton *baton, sds string, struct timeval *result, const char *source) +{ + char *error; + sds msg; + int sts; + + if ((sts = pmParseInterval(string, result, &error)) < 0) { + infofmt(msg, "Cannot parse time %s with pmParseInterval:\n%s", + source, error); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = sts; + free(error); + } +} + +static void +parsetime(seriesQueryBaton *baton, sds string, struct timeval *result, const char *source) +{ + struct timeval start = { 0, 0 }; + struct timeval end = { INT_MAX, 0 }; + char *error; + sds msg; + int sts; + + if ((sts = __pmParseTime(string, &start, &end, result, &error)) < 0) { + infofmt(msg, "Cannot parse %s time with __pmParseTime:\n%s", + source, error); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = sts; + free(error); + } +} + +static void +parseuint(seriesQueryBaton *baton, sds string, unsigned int *vp, const char *source) +{ + unsigned int value; + char *endnum; + sds msg; + + value = (unsigned int)strtoul(string, &endnum, 10); + if (*endnum != '\0') { + infofmt(msg, "Invalid sample %s requested - %s", source, string); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EINVAL; + } else { + *vp = value; + } +} + +static void +parsezone(seriesQueryBaton *baton, sds string, int *zone, const char *source) +{ + char error[PM_MAXERRMSGLEN]; + sds msg; + int sts; + + if ((sts = pmNewZone(string)) < 0) { + infofmt(msg, "Cannot parse %s with pmNewZone:\n%s - %s", + source, string, pmErrStr_r(sts, error, sizeof(error))); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = sts; + } else { + *zone = sts; + } +} + +static void +parseseries(seriesQueryBaton *baton, sds series, unsigned char *result) +{ + unsigned int i, off; + char *endptr, tuple[3] = {0}; + sds msg; + + for (i = 0; i < 20; i++) { + off = i * 2; + tuple[0] = series[off]; + tuple[1] = series[off+1]; + result[i] = (unsigned char)strtoul(tuple, &endptr, 16); + if (endptr != &tuple[2]) { + infofmt(msg, "Invalid SID %s near offset %u", series, off); + batoninfo(baton, PMLOG_ERROR, msg); + baton->error = -EINVAL; + } + } +} + +static void +initSeriesGetValues(seriesQueryBaton *baton, int nseries, sds *series, + pmSeriesTimeWindow *window) +{ + struct series_set *result = &baton->u.query.root.result; + struct timing *timing = &baton->u.query.timing; + struct timeval offset; + int i; + + /* validate and convert 40-byte (ASCII) SIDs to internal 20-byte form */ + result->nseries = nseries; + if ((result->series = calloc(nseries, 20)) == NULL) { + baton->error = -ENOMEM; + } else { + for (i = 0; i < nseries; i++) + parseseries(baton, series[i], result->series + (i * 20)); + } + if (baton->error) { + if (result->series) + free(result->series); + return; + } + + /* validate and convert time window specification to internal struct */ + timing->window = *window; + if (window->delta) + parsedelta(baton, window->delta, &timing->delta, "delta"); + if (window->align) + parsetime(baton, window->align, &timing->align, "align"); + if (window->start) + parsetime(baton, window->start, &timing->start, "start"); + if (window->end) + parsetime(baton, window->end, &timing->end, "end"); + if (window->range) { + parsedelta(baton, window->range, &timing->start, "range"); + gettimeofday(&offset, NULL); + tsub(&offset, &timing->start); + timing->start = offset; + timing->end.tv_sec = INT_MAX; + } + if (window->count) + parseuint(baton, window->count, &timing->count, "count"); + if (window->offset) + parseuint(baton, window->offset, &timing->offset, "offset"); + if (window->zone) + parsezone(baton, window->zone, &timing->zone, "timezone"); + + /* if no time window parameters passed, default to latest value */ + if (!series_time_window(timing)) + timing->count = 1; +} + +int +pmSeriesValues(pmSeriesSettings *settings, pmSeriesTimeWindow *timing, + int nseries, sds *series, void *arg) +{ + seriesQueryBaton *baton; + size_t bytes; + unsigned int i = 0; + + if (nseries <= 0) + return -EINVAL; + bytes = sizeof(seriesQueryBaton) + (nseries * sizeof(seriesGetSID)); + if ((baton = calloc(1, bytes)) == NULL) + return -ENOMEM; + initSeriesQueryBaton(baton, settings, arg); + initSeriesGetValues(baton, nseries, series, timing); + + baton->current = &baton->phases[0]; + baton->phases[i++].func = series_lookup_services; + baton->phases[i++].func = series_query_report_values; + baton->phases[i++].func = series_lookup_finished; + assert(i <= QUERY_PHASES); + seriesBatonPhases(baton->current, i, baton); + pmSeriesStatsAdd(&settings->module, "values.calls", NULL, 1); + return 0; +} diff -Nru pcp-5.3.1/src/libpcp_web/src/query_parser.y pcp-5.3.2/src/libpcp_web/src/query_parser.y --- pcp-5.3.1/src/libpcp_web/src/query_parser.y 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/query_parser.y 2021-07-30 04:05:06.000000000 +0000 @@ -1403,7 +1403,7 @@ } if (p == NULL) { lp->yy_tokbuflen = 128; - if ((p = (char *)malloc(lp->yy_tokbuflen)) == NULL) { + if ((p = (char *)malloc(lp->yy_tokbuflen+1)) == NULL) { /* CID287946 */ lp->yy_errstr = sdscatfmt(sdsempty(), "cannot allocate token buffer (length=%lld)", (long long)lp->yy_tokbuflen); @@ -1416,7 +1416,7 @@ else if (p >= &lp->yy_tokbuf[lp->yy_tokbuflen]) { len = p - lp->yy_tokbuf; lp->yy_tokbuflen *= 2; - if (!(p = (char *)realloc(lp->yy_tokbuf, lp->yy_tokbuflen))) { + if (!(p = (char *)realloc(lp->yy_tokbuf, lp->yy_tokbuflen+1))) { /* CID287946 */ lp->yy_errstr = sdscatfmt(sdsempty(), "cannot reallocate token buffer (length=%lld)", (long long)lp->yy_tokbuflen); diff -Nru pcp-5.3.1/src/libpcp_web/src/schema.c pcp-5.3.2/src/libpcp_web/src/schema.c --- pcp-5.3.1/src/libpcp_web/src/schema.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/schema.c 2021-07-30 04:05:06.000000000 +0000 @@ -1303,6 +1303,7 @@ infofmt(msg, "unsupported redis server (got v%u, expected v%u or above)", server_version, SERVER_VERSION); batoninfo(baton, PMLOG_ERROR, msg); + baton->slots->setup = 0; } break; } @@ -1884,6 +1885,11 @@ "current filesystem changed callback throttle", "minimum seconds between filesystem changed callbacks for each monitored archive"); + mmv_stats_add_metric(data->metrics, "metadata.partial_reads", 20, + MMV_TYPE_U64, MMV_SEM_COUNTER, countunits, noindom, + "metadata read returned less data than header indicated", + "number of times a metadata record read returned less than expected length"); + data->metrics_handle = mmv_stats_start(data->metrics); } diff -Nru pcp-5.3.1/src/libpcp_web/src/schema.h pcp-5.3.2/src/libpcp_web/src/schema.h --- pcp-5.3.1/src/libpcp_web/src/schema.h 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/schema.h 2021-07-30 04:05:06.000000000 +0000 @@ -118,7 +118,7 @@ /* * Asynchronous schema load baton structures */ -#define LOAD_PHASES 5 +#define LOAD_PHASES 6 typedef struct seriesGetContext { seriesBatonMagic header; /* MAGIC_CONTEXT */ diff -Nru pcp-5.3.1/src/libpcp_web/src/search.c pcp-5.3.2/src/libpcp_web/src/search.c --- pcp-5.3.1/src/libpcp_web/src/search.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/search.c 2021-07-30 04:05:06.000000000 +0000 @@ -122,6 +122,11 @@ } sdstrim(result, " "); tokens = sdssplitlen(result, sdslen(result), " ", 1, &token_count); + if (tokens == NULL) { + /* Coverity: CID370640 */ + sdsfree(result); + return NULL; + } formatted_result = sdsempty(); for (i = 0; i < token_count; i++) { size_t token_len = sdslen(tokens[i]); diff -Nru pcp-5.3.1/src/libpcp_web/src/slots.c pcp-5.3.2/src/libpcp_web/src/slots.c --- pcp-5.3.1/src/libpcp_web/src/slots.c 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/slots.c 2021-07-30 04:05:06.000000000 +0000 @@ -130,6 +130,7 @@ dictIterator *iterator; dictEntry *entry; sds servers = NULL; + sds def_servers = NULL; int sts = 0; struct timeval connection_timeout = {5, 0}; // 5s struct timeval command_timeout = {60, 0}; // 1m @@ -146,19 +147,28 @@ servers = pmIniFileLookup(config, "pmseries", "servers"); if (servers == NULL) - servers = sdsnew(default_server); + servers = def_servers = sdsnew(default_server); - slots->acc = redisClusterAsyncContextInit(); - if (slots->acc && slots->acc->err) { + if ((slots->acc = redisClusterAsyncContextInit()) == NULL) { + /* Coverity CID370635 */ + pmNotifyErr(LOG_ERR, "redisSlotsInit: redisClusterAsyncContextInit failed\n"); + sdsfree(def_servers); + return slots; + } + + if (slots->acc->err) { pmNotifyErr(LOG_ERR, "redisSlotsInit: %s\n", slots->acc->errstr); + sdsfree(def_servers); return slots; } sts = redisClusterSetOptionAddNodes(slots->acc->cc, servers); if (sts != REDIS_OK) { pmNotifyErr(LOG_ERR, "redisSlotsInit: failed to add redis nodes: %s\n", slots->acc->cc->errstr); + sdsfree(def_servers); return slots; } + sdsfree(def_servers); /* Coverity CID370634 */ sts = redisClusterSetOptionConnectTimeout(slots->acc->cc, connection_timeout); if (sts != REDIS_OK) { @@ -318,7 +328,7 @@ if ((srd = redisSlotsReplyDataAlloc(slots, sdslen(cmd), callback, arg)) == NULL) { mmv_stats_inc(slots->metrics_handle, "requests.error", NULL); - pmNotifyErr(LOG_ERR, "Error: redisSlotsRequest failed to allocate reply data (%lu bytes)\n", sdslen(cmd)); + pmNotifyErr(LOG_ERR, "Error: redisSlotsRequest failed to allocate reply data (%zu bytes)\n", sdslen(cmd)); return -ENOMEM; } sts = redisClusterAsyncFormattedCommand(slots->acc, redisSlotsReplyCallback, srd, cmd, sdslen(cmd)); @@ -363,7 +373,7 @@ if ((srd = redisSlotsReplyDataAlloc(slots, sdslen(cmd), callback, arg)) == NULL) { mmv_stats_inc(slots->metrics_handle, "requests.error", NULL); - pmNotifyErr(LOG_ERR, "Error: redisSlotsRequestFirstNode failed to allocate reply data (%lu bytes)\n", sdslen(cmd)); + pmNotifyErr(LOG_ERR, "Error: redisSlotsRequestFirstNode failed to allocate reply data (%zu bytes)\n", sdslen(cmd)); return -ENOMEM; } sts = redisClusterAsyncFormattedCommandToNode(slots->acc, node, redisSlotsReplyCallback, srd, cmd, sdslen(cmd)); diff -Nru pcp-5.3.1/src/libpcp_web/src/timer.c pcp-5.3.2/src/libpcp_web/src/timer.c --- pcp-5.3.1/src/libpcp_web/src/timer.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/timer.c 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2021 Red Hat. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ +#include +#include +#include "pmapi.h" +#include "pmda.h" +#include "pmwebapi.h" +#include "schema.h" + +typedef enum server_metric { + SERVER_PID, + SERVER_CPU_USR, + SERVER_CPU_SYS, + SERVER_CPU_TOT, + SERVER_MEM_MAXRSS, + SERVER_MEM_DATASZ, + NUM_SERVER_METRIC +} server_metric; + +/* direct lookup table */ +static pmAtomValue *server_values[NUM_SERVER_METRIC]; + +typedef struct timerCallback { + int seq; + void *data; + pmWebTimerCallBack callback; + struct timerCallback *next; +} timerCallback; + +static timerCallback *timerCallbackList; +static uv_timer_t pmwebapi_timer; +static uv_mutex_t timerCallbackMutex = PTHREAD_MUTEX_INITIALIZER; +static struct mmv_registry *server_registry; /* global generic server metrics */ +static void *server_map; + +static void +webapi_timer_worker(uv_timer_t *arg) +{ + timerCallback *timer; + uv_handle_t *handle = (uv_handle_t *)arg; + + (void)handle; + uv_mutex_lock(&timerCallbackMutex); + for (timer = timerCallbackList; timer; timer = timer->next) { + if (timer->callback) + timer->callback(timer->data); + } + uv_mutex_unlock(&timerCallbackMutex); +} + +/* + * Register given callback function and it's private data in the + * global timer list. Callbacks must be non-blocking and short, + * e.g. to refresh instrumentation, garbage collection, etc. + */ +int +pmWebTimerRegister(pmWebTimerCallBack callback, void *data) +{ + static int seq = 0; + timerCallback *timer = (timerCallback *)malloc(sizeof(timerCallback)); + + if (timer == NULL) + return -ENOMEM; + timer->seq = seq++; + timer->data = data; + timer->callback = callback; + uv_mutex_lock(&timerCallbackMutex); + if (timerCallbackList == NULL) { + uv_timer_init(uv_default_loop(), &pmwebapi_timer); + uv_timer_start(&pmwebapi_timer, webapi_timer_worker, 1000, 1000); + } + timer->next = timerCallbackList; + timerCallbackList = timer; + uv_mutex_unlock(&timerCallbackMutex); + + return timer->seq; +} + +/* + * Release a previously registered timer. If there are no + * remaining registered timers, stop the global uv timer. + */ +int +pmWebTimerRelease(int seq) +{ + int sts = -EINVAL; + timerCallback *timer, *prev = NULL; + + uv_mutex_lock(&timerCallbackMutex); + for (timer = timerCallbackList; timer; prev = timer, timer = timer->next) { + if (timer->seq == seq) { + if (timer == timerCallbackList) + timerCallbackList = timer->next; + else + prev->next = timer->next; + free(timer); + /* success */ + sts = 0; + break; + } + } + if (timerCallbackList == NULL) + uv_timer_stop(&pmwebapi_timer); + uv_mutex_unlock(&timerCallbackMutex); + + return sts; +} + +/* + * timer callback to refresh generic server metrics + */ +static void +server_metrics_refresh(void *map) +{ + double usr, sys; + unsigned long datasz = 0; + struct rusage usage = {0}; + + __pmProcessDataSize(&datasz); + __pmProcessRunTimes(&usr, &sys); + usr *= 1000.0; /* milliseconds */ + sys *= 1000.0; + if (getrusage(RUSAGE_SELF, &usage) < 0) + return; + + if (server_values[SERVER_CPU_USR]) + mmv_set_value(map, server_values[SERVER_CPU_USR], usr); + if (server_values[SERVER_CPU_SYS]) + mmv_set_value(map, server_values[SERVER_CPU_SYS], sys); + if (server_values[SERVER_CPU_TOT]) + mmv_set_value(map, server_values[SERVER_CPU_TOT], usr+sys); + if (server_values[SERVER_MEM_MAXRSS]) + mmv_set_value(map, server_values[SERVER_MEM_MAXRSS], usage.ru_maxrss); + if (server_values[SERVER_MEM_DATASZ]) + mmv_set_value(map, server_values[SERVER_MEM_DATASZ], (double)datasz); +} + +/* + * Register and set up generic server metrics. + * See pmproxy/src/server.c for calling example. + */ +int +pmWebTimerSetMetricRegistry(struct mmv_registry *registry) +{ + pmInDom noindom = MMV_INDOM_NULL; + pmUnits nounits = MMV_UNITS(0,0,0,0,0,0); + pmUnits units_kbytes = MMV_UNITS(1, 0, 0, PM_SPACE_KBYTE, 0, 0); + pmUnits units_msec = MMV_UNITS(0, 1, 0, 0, PM_TIME_MSEC, 0); + pid_t pid = getpid(); + char buffer[64]; + + if (server_registry) { + pmNotifyErr(LOG_ERR, "%s: server instrumentation already registered\n", + "pmWebTimerSetMetricRegistry"); + return -EINVAL; + } + + server_registry = registry; + mmv_stats_add_metric(registry, "pid", SERVER_PID, + MMV_TYPE_U32, MMV_SEM_DISCRETE, nounits, noindom, + "Identifier", + "Identifier for the current process"); + pmsprintf(buffer, sizeof(buffer), "%u", pid); + mmv_stats_add_metric_label(registry, SERVER_PID, + "pid", buffer, MMV_NUMBER_TYPE, 0); + + mmv_stats_add_metric(registry, "cpu.user", SERVER_CPU_USR, + MMV_TYPE_U64, MMV_SEM_COUNTER, units_msec, noindom, + "user CPU time", + "process user CPU time counter"); + + mmv_stats_add_metric(registry, "cpu.sys", SERVER_CPU_SYS, + MMV_TYPE_U64, MMV_SEM_COUNTER, units_msec, noindom, + "system CPU time", + "process system CPU time counter"); + + mmv_stats_add_metric(registry, "cpu.total", SERVER_CPU_TOT, + MMV_TYPE_U64, MMV_SEM_COUNTER, units_msec, noindom, + "system + user CPU time", + "process system + user CPU time"); + + mmv_stats_add_metric(registry, "mem.maxrss", SERVER_MEM_MAXRSS, + MMV_TYPE_U64, MMV_SEM_INSTANT, units_kbytes, noindom, + "maximum RSS", + "process maximum resident set memory size"); + + mmv_stats_add_metric(registry, "mem.datasz", SERVER_MEM_DATASZ, + MMV_TYPE_U64, MMV_SEM_INSTANT, units_kbytes, noindom, + "virtual data size", + "process data memory size, returned from sbrk(2)"); + + if ((server_map = mmv_stats_start(registry)) == NULL) { + pmNotifyErr(LOG_ERR, "%s: server instrumentation disabled", + "pmWebTimerSetMetricRegistry"); + return -EINVAL; + } + + /* PID doesn't change, set it once */ + if ((server_values[SERVER_PID] = mmv_lookup_value_desc(server_map, "pid", NULL)) != NULL) + mmv_set_value(server_map, server_values[SERVER_PID], pid); + server_values[SERVER_CPU_USR] = mmv_lookup_value_desc(server_map, "cpu.user", NULL); + server_values[SERVER_CPU_SYS] = mmv_lookup_value_desc(server_map, "cpu.sys", NULL); + server_values[SERVER_CPU_TOT] = mmv_lookup_value_desc(server_map, "cpu.total", NULL); + server_values[SERVER_MEM_MAXRSS] = mmv_lookup_value_desc(server_map, "mem.maxrss", NULL); + server_values[SERVER_MEM_DATASZ] = mmv_lookup_value_desc(server_map, "mem.datasz", NULL); + + /* initialize base sbrk */ + __pmProcessDataSize(NULL); + + /* register the refresh timer */ + return pmWebTimerRegister(server_metrics_refresh, server_map); +} diff -Nru pcp-5.3.1/src/libpcp_web/src/util.c pcp-5.3.2/src/libpcp_web/src/util.c --- pcp-5.3.1/src/libpcp_web/src/util.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/util.c 2021-07-30 04:05:06.000000000 +0000 @@ -256,6 +256,8 @@ *sets = lp; return 0; } + if (lp) + free(lp); /* Coverity CID340558 */ return sts; } @@ -270,15 +272,15 @@ indom_t *indom = metric->indom; int nsets = 0; - if (context->labelset) + if (context && context->labelset) sets[nsets++] = context->labelset; - if (domain->labelset) + if (domain && domain->labelset) sets[nsets++] = domain->labelset; if (indom && indom->labelset) sets[nsets++] = indom->labelset; - if (cluster->labelset) + if (cluster && cluster->labelset) sets[nsets++] = cluster->labelset; - if (metric->labelset) + if (metric && metric->labelset) sets[nsets++] = metric->labelset; return pmMergeLabelSets(sets, nsets, buffer, length, filter, arg); diff -Nru pcp-5.3.1/src/libpcp_web/src/webgroup.c pcp-5.3.2/src/libpcp_web/src/webgroup.c --- pcp-5.3.1/src/libpcp_web/src/webgroup.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/libpcp_web/src/webgroup.c 2021-07-30 04:05:06.000000000 +0000 @@ -51,14 +51,22 @@ uv_loop_t *events; unsigned int active; uv_timer_t timer; + uv_mutex_t mutex; + int stats_timer; } webgroups; static struct webgroups * webgroups_lookup(pmWebGroupModule *module) { - if (module->privdata == NULL) + struct webgroups *groups = module->privdata; + + if (module->privdata == NULL) { module->privdata = calloc(1, sizeof(struct webgroups)); - return (struct webgroups *)module->privdata; + groups = (struct webgroups *)module->privdata; + uv_mutex_init(&groups->mutex); + groups->stats_timer = -1; + } + return groups; } static int @@ -94,8 +102,11 @@ context->garbage = 1; uv_timer_stop(&context->timer); } - if (groups) + if (groups) { + uv_mutex_lock(&groups->mutex); dictDelete(groups->contexts, &context->randomid); + uv_mutex_unlock(&groups->mutex); + } uv_close((uv_handle_t *)&context->timer, webgroup_release_context); } } @@ -127,7 +138,7 @@ { __pmHashNode *node; __pmHashCtl attrs; - pmHostSpec *hosts = NULL; + __pmHostSpec *hosts = NULL; char *msg, buf[512]; int sts, bytes, numhosts = 0; sds value; @@ -207,13 +218,16 @@ cp->context = -1; cp->timeout = polltime; + uv_mutex_lock(&groups->mutex); if ((cp->randomid = random()) < 0 || dictFind(groups->contexts, &cp->randomid) != NULL) { infofmt(*message, "random number failure on new web context"); pmwebapi_free_context(cp); *status = -ESRCH; + uv_mutex_unlock(&groups->mutex); return NULL; } + uv_mutex_unlock(&groups->mutex); cp->origin = sdscatfmt(sdsempty(), "%i", cp->randomid); cp->name.sds = sdsdup(hostspec ? hostspec : LOCALHOST); cp->realm = sdscatfmt(sdsempty(), "pmapi/%i", cp->randomid); @@ -242,7 +256,9 @@ pmwebapi_free_context(cp); return NULL; } + uv_mutex_lock(&groups->mutex); dictAdd(groups->contexts, &cp->randomid, cp); + uv_mutex_unlock(&groups->mutex); /* leave until the end because uv_timer_init makes this visible in uv_run */ handle = (uv_handle_t *)&cp->timer; @@ -261,24 +277,39 @@ static void webgroup_garbage_collect(struct webgroups *groups) { - dictIterator *iterator = dictGetSafeIterator(groups->contexts); + dictIterator *iterator; dictEntry *entry; context_t *cp; if (pmDebugOptions.http || pmDebugOptions.libweb) fprintf(stderr, "%s: started\n", "webgroup_garbage_collect"); - while ((entry = dictNext(iterator)) != NULL) { - cp = (context_t *)dictGetVal(entry); - if (cp->garbage && cp->privdata == groups) { - if (pmDebugOptions.http || pmDebugOptions.libweb) - fprintf(stderr, "GC context %u (%p)\n", cp->randomid, cp); - webgroup_drop_context(cp, groups); + /* do context GC if we get the lock (else don't block here) */ + if (uv_mutex_trylock(&groups->mutex) == 0) { + iterator = dictGetSafeIterator(groups->contexts); + for (entry = dictNext(iterator); entry;) { + cp = (context_t *)dictGetVal(entry); + entry = dictNext(iterator); + if (cp->garbage && cp->privdata == groups) { + if (pmDebugOptions.http || pmDebugOptions.libweb) + fprintf(stderr, "GC context %u (%p)\n", cp->randomid, cp); + uv_mutex_unlock(&groups->mutex); + webgroup_drop_context(cp, groups); + uv_mutex_lock(&groups->mutex); + } } + dictReleaseIterator(iterator); + uv_mutex_unlock(&groups->mutex); } - dictReleaseIterator(iterator); - /* TODO - trim maps, particularly instmap if proc metrics are not excluded */ + if (pmDebugOptions.http || pmDebugOptions.libweb) + fprintf(stderr, "%s: finished\n", "webgroup_garbage_collect"); +} + +static void +refresh_maps_metrics(void *data) +{ + struct webgroups *groups = (struct webgroups *)data; if (groups->metrics_handle) { mmv_stats_set(groups->metrics_handle, "contextmap.size", @@ -290,9 +321,6 @@ mmv_stats_set(groups->metrics_handle, "instmap.size", NULL, dictSize(instmap)); } - - if (pmDebugOptions.http || pmDebugOptions.libweb) - fprintf(stderr, "%s: finished\n", "webgroup_garbage_collect"); } static void @@ -363,6 +391,8 @@ groups->timer.data = (void *)groups; uv_timer_start(&groups->timer, webgroup_worker, default_worker, default_worker); + /* timer for map stats refresh */ + groups->stats_timer = pmWebTimerRegister(refresh_maps_metrics, (void *)groups); } if (*id == NULL) { @@ -2313,8 +2343,6 @@ "instance name map dictionary size", "number of entries in the instance name map dictionary"); - /* TODO add call counter metrics for pmWebgroup* API functions */ - webgroups->metrics_handle = mmv_stats_start(webgroups->metrics); } @@ -2344,6 +2372,8 @@ if (groups->active) { groups->active = 0; uv_timer_stop(&groups->timer); + pmWebTimerRelease(groups->stats_timer); + groups->stats_timer = -1; } iterator = dictGetIterator(groups->contexts); while ((entry = dictNext(iterator)) != NULL) diff -Nru pcp-5.3.1/src/newhelp/chkhelp.c pcp-5.3.2/src/newhelp/chkhelp.c --- pcp-5.3.1/src/newhelp/chkhelp.c 2020-12-17 22:46:06.000000000 +0000 +++ pcp-5.3.2/src/newhelp/chkhelp.c 2021-07-30 04:05:06.000000000 +0000 @@ -323,8 +323,13 @@ tp = pmdaGetHelp(handle, (pmID)id, PM_TEXT_ONELINE); else tp = pmdaGetInDomHelp(handle, (pmInDom)id, PM_TEXT_ONELINE); - if (tp != NULL) - printf(" %s", tp); + putchar(' '); + if (tp != NULL && *tp) + printf("%s", tp); + else if (tp != NULL) + printf(""); + else + printf(""); putchar('\n'); } @@ -334,7 +339,13 @@ else tp = pmdaGetInDomHelp(handle, (pmInDom)id, PM_TEXT_HELP); if (tp != NULL && *tp) - printf("%s\n", tp); + printf("%s", tp); + else if (tp != NULL) + printf(""); + else + printf(""); + putchar('\n'); + } } diff -Nru pcp-5.3.1/src/pcp/atop/pcp-atop.1 pcp-5.3.2/src/pcp/atop/pcp-atop.1 --- pcp-5.3.1/src/pcp/atop/pcp-atop.1 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/atop/pcp-atop.1 2021-07-30 04:05:06.000000000 +0000 @@ -64,27 +64,38 @@ command, the .BR PCPIntro (1) options -.BR \-h /\c -.BR \-\-host , +.hy 0 +.BR \-A /\c +.BR \-\-align , .BR \-a /\c .BR \-\-archive , +.BR \-h /\c +.BR \-\-host , .BR \-O /\c .BR \-\-origin , +.BR \-S /\c +.BR \-\-start , .BR \-s /\c .BR \-\-samples , +.BR \-T /\c +.BR \-\-finish , .BR \-t /\c .BR \-\-interval , -.BR \-Z /\c +.BR \-v /\c +.BR \-\-version , +.BR \-z /\c , +.B \-\-hostzone +and +.BR \-z /\c , .BR \-\-timezone -and several other -.I pcp options become indirectly available. -The long option form of these is directly available. Additionally, the .B \-\-hotproc option can be used to request the per-process PCP metrics be used instead of the default proc metrics from .BR pmdaproc (1). +.br +.hy .PP When .B pcp-atop diff -Nru pcp-5.3.1/src/pcp/dstat/pcp-dstat.py pcp-5.3.2/src/pcp/dstat/pcp-dstat.py --- pcp-5.3.1/src/pcp/dstat/pcp-dstat.py 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/dstat/pcp-dstat.py 2021-06-15 01:03:49.000000000 +0000 @@ -785,7 +785,6 @@ opts.pmSetLongOption('noheaders', 0, '', '', 'disable repetitive headers') opts.pmSetLongOption('noupdate', 0, '', '', 'disable intermediate headers') opts.pmSetLongOption('output', 1, 'o', 'file', 'write CSV output to file') - opts.pmSetLongOption('profile', 0, '', '', 'show profiling statistics when exiting dstat') opts.pmSetLongOption('version', 0, 'V', '', '') opts.pmSetLongOption('debug', 1, None, '', '') opts.pmSetLongOption('dbg', 0, None, '', '') @@ -924,8 +923,6 @@ self.output = arg elif opt in ['pidfile']: self.pidfile = arg - elif opt in ['profile']: - self.profile = 'dstat_profile.log' elif opt in ['q']: self.verify = True elif opt in ['h', '?']: diff -Nru pcp-5.3.1/src/pcp/free/pcp-free.1 pcp-5.3.2/src/pcp/free/pcp-free.1 --- pcp-5.3.1/src/pcp/free/pcp-free.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/pcp/free/pcp-free.1 2021-07-30 04:05:06.000000000 +0000 @@ -87,7 +87,7 @@ \fB\-b\fP, \fB\-\-bytes\fP Display the amount of memory in bytes. .TP -\fB\-c\fR \fIcount\fR, \fB\-\-samples\fR=\fIcount\fR +\fB\-c\fR \fIcount\fR, \fB\-\-samples\fR=\fIcount\fR, \fB\-\-count\fR=\fIcount\fR Terminate the display after \fIcount\fR iterations. See also .BR \-s . @@ -113,7 +113,7 @@ \fB\-r\fP, \fB\-\-terabytes\fP Display the amount of memory in terabytes. .TP -\fB\-s\fR \fIdelay\fR, \fB\-\-interval\fR=\fIdelay\fR +\fB\-s\fR \fIdelay\fR, \fB\-\-interval\fR=\fIdelay\fR, \fB\-\-seconds\fR=\fIdelay\fR Activate continuous polling \fIdelay\fP seconds apart. You may specify any floating point number for \fIdelay\fP, or indeed any valid .BR pmParseInterval (3) diff -Nru pcp-5.3.1/src/pcp/GNUmakefile pcp-5.3.2/src/pcp/GNUmakefile --- pcp-5.3.1/src/pcp/GNUmakefile 2020-12-17 22:46:06.000000000 +0000 +++ pcp-5.3.2/src/pcp/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -33,7 +33,8 @@ tapestat \ uptime \ verify \ - vmstat + vmstat \ + ss default :: default_pcp diff -Nru pcp-5.3.1/src/pcp/htop/Action.c pcp-5.3.2/src/pcp/htop/Action.c --- pcp-5.3.1/src/pcp/htop/Action.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Action.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,685 +0,0 @@ -/* -htop - Action.c -(C) 2015 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "Action.h" - -#include -#include -#include - -#include "CategoriesPanel.h" -#include "CommandScreen.h" -#include "CRT.h" -#include "EnvScreen.h" -#include "FunctionBar.h" -#include "Hashtable.h" -#include "IncSet.h" -#include "InfoScreen.h" -#include "ListItem.h" -#include "Macros.h" -#include "MainPanel.h" -#include "OpenFilesScreen.h" -#include "Process.h" -#include "ProcessLocksScreen.h" -#include "ProvideCurses.h" -#include "ScreenManager.h" -#include "SignalsPanel.h" -#include "TraceScreen.h" -#include "Vector.h" -#include "XUtils.h" - -#if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY)) -#include "Affinity.h" -#include "AffinityPanel.h" -#endif - - -Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess) { - MainPanel* mainPanel = st->mainPanel; - Header* header = st->header; - - int y = ((Panel*)mainPanel)->y; - ScreenManager* scr = ScreenManager_new(header, st->settings, st, false); - scr->allowFocusChange = false; - ScreenManager_add(scr, list, x - 1); - ScreenManager_add(scr, (Panel*)mainPanel, -1); - Panel* panelFocus; - int ch; - bool unfollow = false; - int pid = followProcess ? MainPanel_selectedPid(mainPanel) : -1; - if (followProcess && header->pl->following == -1) { - header->pl->following = pid; - unfollow = true; - } - ScreenManager_run(scr, &panelFocus, &ch); - if (unfollow) { - header->pl->following = -1; - } - ScreenManager_delete(scr); - Panel_move((Panel*)mainPanel, 0, y); - Panel_resize((Panel*)mainPanel, COLS, LINES - y - 1); - if (panelFocus == list && ch == 13) { - if (followProcess) { - const Process* selected = (const Process*)Panel_getSelected((Panel*)mainPanel); - if (selected && selected->pid == pid) - return Panel_getSelected(list); - - beep(); - } else { - return Panel_getSelected(list); - } - } - - return NULL; -} - -// ---------------------------------------- - -static void Action_runSetup(State* st) { - ScreenManager* scr = ScreenManager_new(st->header, st->settings, st, true); - CategoriesPanel* panelCategories = CategoriesPanel_new(scr, st->settings, st->header, st->pl); - ScreenManager_add(scr, (Panel*) panelCategories, 16); - CategoriesPanel_makeMetersPage(panelCategories); - Panel* panelFocus; - int ch; - ScreenManager_run(scr, &panelFocus, &ch); - ScreenManager_delete(scr); - if (st->settings->changed) { - Header_writeBackToSettings(st->header); - } -} - -static bool changePriority(MainPanel* panel, int delta) { - bool anyTagged; - bool ok = MainPanel_foreachProcess(panel, Process_changePriorityBy, (Arg) { .i = delta }, &anyTagged); - if (!ok) - beep(); - return anyTagged; -} - -static void addUserToVector(ht_key_t key, void* userCast, void* panelCast) { - const char* user = userCast; - Panel* panel = panelCast; - Panel_add(panel, (Object*) ListItem_new(user, key)); -} - -bool Action_setUserOnly(const char* userName, uid_t* userId) { - const struct passwd* user = getpwnam(userName); - if (user) { - *userId = user->pw_uid; - return true; - } - *userId = (uid_t)-1; - return false; -} - -static void tagAllChildren(Panel* panel, Process* parent) { - parent->tag = true; - pid_t ppid = parent->pid; - for (int i = 0; i < Panel_size(panel); i++) { - Process* p = (Process*) Panel_get(panel, i); - if (!p->tag && Process_isChildOf(p, ppid)) { - tagAllChildren(panel, p); - } - } -} - -static bool expandCollapse(Panel* panel) { - Process* p = (Process*) Panel_getSelected(panel); - if (!p) - return false; - - p->showChildren = !p->showChildren; - return true; -} - -static bool collapseIntoParent(Panel* panel) { - const Process* p = (Process*) Panel_getSelected(panel); - if (!p) - return false; - - pid_t ppid = Process_getParentPid(p); - for (int i = 0; i < Panel_size(panel); i++) { - Process* q = (Process*) Panel_get(panel, i); - if (q->pid == ppid) { - q->showChildren = false; - Panel_setSelected(panel, i); - return true; - } - } - return false; -} - -Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) { - Settings_setSortKey(settings, sortKey); - return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING; -} - -// ---------------------------------------- - -static Htop_Reaction actionSetSortColumn(State* st) { - Htop_Reaction reaction = HTOP_OK; - Panel* sortPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Sort ", "Cancel ")); - Panel_setHeader(sortPanel, "Sort by"); - const ProcessField* fields = st->settings->fields; - for (int i = 0; fields[i]; i++) { - char* name = String_trim(Process_fields[fields[i]].name); - Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i])); - if (fields[i] == Settings_getActiveSortKey(st->settings)) - Panel_setSelected(sortPanel, i); - - free(name); - } - const ListItem* field = (const ListItem*) Action_pickFromVector(st, sortPanel, 15, false); - if (field) { - reaction |= Action_setSortKey(st->settings, field->key); - } - Object_delete(sortPanel); - - if (st->pauseProcessUpdate) - ProcessList_sort(st->pl); - - return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - -static Htop_Reaction actionSortByPID(State* st) { - return Action_setSortKey(st->settings, PID); -} - -static Htop_Reaction actionSortByMemory(State* st) { - return Action_setSortKey(st->settings, PERCENT_MEM); -} - -static Htop_Reaction actionSortByCPU(State* st) { - return Action_setSortKey(st->settings, PERCENT_CPU); -} - -static Htop_Reaction actionSortByTime(State* st) { - return Action_setSortKey(st->settings, TIME); -} - -static Htop_Reaction actionToggleKernelThreads(State* st) { - st->settings->hideKernelThreads = !st->settings->hideKernelThreads; - return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionToggleUserlandThreads(State* st) { - st->settings->hideUserlandThreads = !st->settings->hideUserlandThreads; - return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionToggleProgramPath(State* st) { - st->settings->showProgramPath = !st->settings->showProgramPath; - return HTOP_REFRESH | HTOP_SAVE_SETTINGS; -} - -static Htop_Reaction actionToggleMergedCommand(State* st) { - st->settings->showMergedCommand = !st->settings->showMergedCommand; - return HTOP_REFRESH | HTOP_SAVE_SETTINGS; -} - -static Htop_Reaction actionToggleTreeView(State* st) { - st->settings->treeView = !st->settings->treeView; - - if (!st->settings->allBranchesCollapsed) ProcessList_expandTree(st->pl); - return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - -static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) { - st->settings->allBranchesCollapsed = !st->settings->allBranchesCollapsed; - if (st->settings->allBranchesCollapsed) - ProcessList_collapseAllBranches(st->pl); - else - ProcessList_expandTree(st->pl); - return HTOP_REFRESH | HTOP_SAVE_SETTINGS; -} - -static Htop_Reaction actionIncFilter(State* st) { - IncSet* inc = (st->mainPanel)->inc; - IncSet_activate(inc, INC_FILTER, (Panel*)st->mainPanel); - st->pl->incFilter = IncSet_filter(inc); - return HTOP_REFRESH | HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionIncSearch(State* st) { - IncSet_reset(st->mainPanel->inc, INC_SEARCH); - IncSet_activate(st->mainPanel->inc, INC_SEARCH, (Panel*)st->mainPanel); - return HTOP_REFRESH | HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionHigherPriority(State* st) { - bool changed = changePriority(st->mainPanel, -1); - return changed ? HTOP_REFRESH : HTOP_OK; -} - -static Htop_Reaction actionLowerPriority(State* st) { - bool changed = changePriority(st->mainPanel, 1); - return changed ? HTOP_REFRESH : HTOP_OK; -} - -static Htop_Reaction actionInvertSortOrder(State* st) { - Settings_invertSortOrder(st->settings); - if (st->pauseProcessUpdate) - ProcessList_sort(st->pl); - return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionExpandOrCollapse(State* st) { - bool changed = expandCollapse((Panel*)st->mainPanel); - return changed ? HTOP_RECALCULATE : HTOP_OK; -} - -static Htop_Reaction actionCollapseIntoParent(State* st) { - if (!st->settings->treeView) { - return HTOP_OK; - } - bool changed = collapseIntoParent((Panel*)st->mainPanel); - return changed ? HTOP_RECALCULATE : HTOP_OK; -} - -static Htop_Reaction actionExpandCollapseOrSortColumn(State* st) { - return st->settings->treeView ? actionExpandOrCollapse(st) : actionSetSortColumn(st); -} - -static Htop_Reaction actionQuit(ATTR_UNUSED State* st) { - return HTOP_QUIT; -} - -static Htop_Reaction actionSetAffinity(State* st) { - if (st->pl->cpuCount == 1) - return HTOP_OK; - -#if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY)) - const Process* p = (const Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - Affinity* affinity1 = Affinity_get(p, st->pl); - if (!affinity1) - return HTOP_OK; - - int width; - Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width); - width += 1; /* we add a gap between the panels */ - Affinity_delete(affinity1); - - const void* set = Action_pickFromVector(st, affinityPanel, width, true); - if (set) { - Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, st->pl); - bool ok = MainPanel_foreachProcess(st->mainPanel, Affinity_set, (Arg) { .v = affinity2 }, NULL); - if (!ok) - beep(); - Affinity_delete(affinity2); - } - Object_delete(affinityPanel); -#endif - return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - -static Htop_Reaction actionKill(State* st) { - Panel* signalsPanel = SignalsPanel_new(); - const ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 15, true); - if (sgn && sgn->key != 0) { - Panel_setHeader((Panel*)st->mainPanel, "Sending..."); - Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st)); - refresh(); - MainPanel_foreachProcess(st->mainPanel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL); - napms(500); - } - Panel_delete((Object*)signalsPanel); - return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - -static Htop_Reaction actionFilterByUser(State* st) { - Panel* usersPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Show ", "Cancel ")); - Panel_setHeader(usersPanel, "Show processes of:"); - UsersTable_foreach(st->ut, addUserToVector, usersPanel); - Vector_insertionSort(usersPanel->items); - ListItem* allUsers = ListItem_new("All users", -1); - Panel_insert(usersPanel, 0, (Object*) allUsers); - const ListItem* picked = (ListItem*) Action_pickFromVector(st, usersPanel, 20, false); - if (picked) { - if (picked == allUsers) { - st->pl->userId = (uid_t)-1; - } else { - Action_setUserOnly(ListItem_getRef(picked), &(st->pl->userId)); - } - } - Panel_delete((Object*)usersPanel); - return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - -Htop_Reaction Action_follow(State* st) { - st->pl->following = MainPanel_selectedPid(st->mainPanel); - Panel_setSelectionColor((Panel*)st->mainPanel, PANEL_SELECTION_FOLLOW); - return HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionSetup(State* st) { - Action_runSetup(st); - int headerHeight = Header_calculateHeight(st->header); - Panel_move((Panel*)st->mainPanel, 0, headerHeight); - Panel_resize((Panel*)st->mainPanel, COLS, LINES-headerHeight-1); - return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; -} - -static Htop_Reaction actionLsof(State* st) { - const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - OpenFilesScreen* ofs = OpenFilesScreen_new(p); - InfoScreen_run((InfoScreen*)ofs); - OpenFilesScreen_delete((Object*)ofs); - clear(); - CRT_enableDelay(); - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -static Htop_Reaction actionShowLocks(State* st) { - const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) return HTOP_OK; - ProcessLocksScreen* pls = ProcessLocksScreen_new(p); - InfoScreen_run((InfoScreen*)pls); - ProcessLocksScreen_delete((Object*)pls); - clear(); - CRT_enableDelay(); - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -static Htop_Reaction actionStrace(State* st) { - const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - TraceScreen* ts = TraceScreen_new(p); - bool ok = TraceScreen_forkTracer(ts); - if (ok) { - InfoScreen_run((InfoScreen*)ts); - } - TraceScreen_delete((Object*)ts); - clear(); - CRT_enableDelay(); - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -static Htop_Reaction actionTag(State* st) { - Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - Process_toggleTag(p); - Panel_onKey((Panel*)st->mainPanel, KEY_DOWN); - return HTOP_OK; -} - -static Htop_Reaction actionRedraw(ATTR_UNUSED State* st) { - clear(); - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -static Htop_Reaction actionTogglePauseProcessUpdate(State* st) { - st->pauseProcessUpdate = !st->pauseProcessUpdate; - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -static const struct { - const char* key; - const char* info; -} helpLeft[] = { - { .key = " Arrows: ", .info = "scroll process list" }, - { .key = " Digits: ", .info = "incremental PID search" }, - { .key = " F3 /: ", .info = "incremental name search" }, - { .key = " F4 \\: ",.info = "incremental name filtering" }, - { .key = " F5 t: ", .info = "tree view" }, - { .key = " p: ", .info = "toggle program path" }, - { .key = " m: ", .info = "toggle merged command" }, - { .key = " Z: ", .info = "pause/resume process updates" }, - { .key = " u: ", .info = "show processes of a single user" }, - { .key = " H: ", .info = "hide/show user process threads" }, - { .key = " K: ", .info = "hide/show kernel threads" }, - { .key = " F: ", .info = "cursor follows process" }, - { .key = " + - *: ", .info = "expand/collapse tree/toggle all" }, - { .key = "N P M T: ", .info = "sort by PID, CPU%, MEM% or TIME" }, - { .key = " I: ", .info = "invert sort order" }, - { .key = " F6 > .: ", .info = "select sort column" }, - { .key = NULL, .info = NULL } -}; - -static const struct { - const char* key; - const char* info; -} helpRight[] = { - { .key = " Space: ", .info = "tag process" }, - { .key = " c: ", .info = "tag process and its children" }, - { .key = " U: ", .info = "untag all processes" }, - { .key = " F9 k: ", .info = "kill process/tagged processes" }, - { .key = " F7 ]: ", .info = "higher priority (root only)" }, - { .key = " F8 [: ", .info = "lower priority (+ nice)" }, -#if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY)) - { .key = " a: ", .info = "set CPU affinity" }, -#endif - { .key = " e: ", .info = "show process environment" }, - { .key = " i: ", .info = "set IO priority" }, - { .key = " l: ", .info = "list open files with lsof" }, - { .key = " x: ", .info = "list file locks of process" }, - { .key = " s: ", .info = "trace syscalls with strace" }, - { .key = " w: ", .info = "wrap process command in multiple lines" }, - { .key = " F2 C S: ", .info = "setup" }, - { .key = " F1 h: ", .info = "show this help screen" }, - { .key = " F10 q: ", .info = "quit" }, - { .key = NULL, .info = NULL } -}; - -static inline void addattrstr( int attr, const char* str) { - attrset(attr); - addstr(str); -} - -static Htop_Reaction actionHelp(State* st) { - clear(); - attrset(CRT_colors[HELP_BOLD]); - - for (int i = 0; i < LINES - 1; i++) - mvhline(i, 0, ' ', COLS); - - int line = 0; - - mvaddstr(line++, 0, "htop " VERSION " - " COPYRIGHT); - mvaddstr(line++, 0, "Released under the GNU GPLv2. See 'man' page for more info."); - - attrset(CRT_colors[DEFAULT_COLOR]); - line++; - mvaddstr(line++, 0, "CPU usage bar: "); - - addattrstr(CRT_colors[BAR_BORDER], "["); - if (st->settings->detailedCPUTime) { - addattrstr(CRT_colors[CPU_NICE_TEXT], "low"); addstr("/"); - addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/"); - addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/"); - addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/"); - addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/"); - addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/"); - addattrstr(CRT_colors[CPU_GUEST], "guest"); addstr("/"); - addattrstr(CRT_colors[CPU_IOWAIT], "io-wait"); - addattrstr(CRT_colors[BAR_SHADOW], " used%"); - } else { - addattrstr(CRT_colors[CPU_NICE_TEXT], "low-priority"); addstr("/"); - addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/"); - addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/"); - addattrstr(CRT_colors[CPU_GUEST], "virtualiz"); - addattrstr(CRT_colors[BAR_SHADOW], " used%"); - } - addattrstr(CRT_colors[BAR_BORDER], "]"); - attrset(CRT_colors[DEFAULT_COLOR]); - mvaddstr(line++, 0, "Memory bar: "); - addattrstr(CRT_colors[BAR_BORDER], "["); - addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/"); - addattrstr(CRT_colors[MEMORY_BUFFERS_TEXT], "buffers"); addstr("/"); - addattrstr(CRT_colors[MEMORY_SHARED], "shared"); addstr("/"); - addattrstr(CRT_colors[MEMORY_CACHE], "cache"); - addattrstr(CRT_colors[BAR_SHADOW], " used/total"); - addattrstr(CRT_colors[BAR_BORDER], "]"); - attrset(CRT_colors[DEFAULT_COLOR]); - mvaddstr(line++, 0, "Swap bar: "); - addattrstr(CRT_colors[BAR_BORDER], "["); - addattrstr(CRT_colors[SWAP], "used"); -#ifdef HTOP_LINUX - addattrstr(CRT_colors[BAR_SHADOW], "/"); - addattrstr(CRT_colors[SWAP_CACHE], "cache"); - addattrstr(CRT_colors[BAR_SHADOW], " used/total"); -#else - addattrstr(CRT_colors[BAR_SHADOW], " used/total"); -#endif - addattrstr(CRT_colors[BAR_BORDER], "]"); - attrset(CRT_colors[DEFAULT_COLOR]); - mvaddstr(line++, 0, "Type and layout of header meters are configurable in the setup screen."); - if (CRT_colorScheme == COLORSCHEME_MONOCHROME) { - mvaddstr(line, 0, "In monochrome, meters display as different chars, in order: |#*@$%&."); - } - line++; - - mvaddstr(line++, 0, "Process state: R: running; S: sleeping; T: traced/stopped; Z: zombie; D: disk sleep"); - - line++; - - int item; - for (item = 0; helpLeft[item].key; item++) { - attrset(CRT_colors[DEFAULT_COLOR]); - mvaddstr(line + item, 10, helpLeft[item].info); - attrset(CRT_colors[HELP_BOLD]); - mvaddstr(line + item, 1, helpLeft[item].key); - if (String_eq(helpLeft[item].key, " H: ")) { - attrset(CRT_colors[PROCESS_THREAD]); - mvaddstr(line + item, 33, "threads"); - } else if (String_eq(helpLeft[item].key, " K: ")) { - attrset(CRT_colors[PROCESS_THREAD]); - mvaddstr(line + item, 27, "threads"); - } - } - int leftHelpItems = item; - - for (item = 0; helpRight[item].key; item++) { - attrset(CRT_colors[HELP_BOLD]); - mvaddstr(line + item, 41, helpRight[item].key); - attrset(CRT_colors[DEFAULT_COLOR]); - mvaddstr(line + item, 50, helpRight[item].info); - } - line += MAXIMUM(leftHelpItems, item); - line++; - - attrset(CRT_colors[HELP_BOLD]); - mvaddstr(line++, 0, "Press any key to return."); - attrset(CRT_colors[DEFAULT_COLOR]); - refresh(); - CRT_readKey(); - clear(); - - return HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_KEEP_FOLLOWING; -} - -static Htop_Reaction actionUntagAll(State* st) { - for (int i = 0; i < Panel_size((Panel*)st->mainPanel); i++) { - Process* p = (Process*) Panel_get((Panel*)st->mainPanel, i); - p->tag = false; - } - return HTOP_REFRESH; -} - -static Htop_Reaction actionTagAllChildren(State* st) { - Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - tagAllChildren((Panel*)st->mainPanel, p); - return HTOP_OK; -} - -static Htop_Reaction actionShowEnvScreen(State* st) { - Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - EnvScreen* es = EnvScreen_new(p); - InfoScreen_run((InfoScreen*)es); - EnvScreen_delete((Object*)es); - clear(); - CRT_enableDelay(); - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -static Htop_Reaction actionShowCommandScreen(State* st) { - Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); - if (!p) - return HTOP_OK; - - CommandScreen* cmdScr = CommandScreen_new(p); - InfoScreen_run((InfoScreen*)cmdScr); - CommandScreen_delete((Object*)cmdScr); - clear(); - CRT_enableDelay(); - return HTOP_REFRESH | HTOP_REDRAW_BAR; -} - -void Action_setBindings(Htop_Action* keys) { - keys[' '] = actionTag; - keys['*'] = actionExpandOrCollapseAllBranches; - keys['+'] = actionExpandOrCollapse; - keys[','] = actionSetSortColumn; - keys['-'] = actionExpandOrCollapse; - keys['.'] = actionSetSortColumn; - keys['/'] = actionIncSearch; - keys['<'] = actionSetSortColumn; - keys['='] = actionExpandOrCollapse; - keys['>'] = actionSetSortColumn; - keys['?'] = actionHelp; - keys['C'] = actionSetup; - keys['F'] = Action_follow; - keys['H'] = actionToggleUserlandThreads; - keys['I'] = actionInvertSortOrder; - keys['K'] = actionToggleKernelThreads; - keys['M'] = actionSortByMemory; - keys['N'] = actionSortByPID; - keys['P'] = actionSortByCPU; - keys['S'] = actionSetup; - keys['T'] = actionSortByTime; - keys['U'] = actionUntagAll; - keys['Z'] = actionTogglePauseProcessUpdate; - keys['['] = actionLowerPriority; - keys['\014'] = actionRedraw; // Ctrl+L - keys['\177'] = actionCollapseIntoParent; - keys['\\'] = actionIncFilter; - keys[']'] = actionHigherPriority; - keys['a'] = actionSetAffinity; - keys['c'] = actionTagAllChildren; - keys['e'] = actionShowEnvScreen; - keys['h'] = actionHelp; - keys['k'] = actionKill; - keys['l'] = actionLsof; - keys['m'] = actionToggleMergedCommand; - keys['p'] = actionToggleProgramPath; - keys['q'] = actionQuit; - keys['s'] = actionStrace; - keys['t'] = actionToggleTreeView; - keys['u'] = actionFilterByUser; - keys['w'] = actionShowCommandScreen; - keys['x'] = actionShowLocks; - keys[KEY_F(1)] = actionHelp; - keys[KEY_F(2)] = actionSetup; - keys[KEY_F(3)] = actionIncSearch; - keys[KEY_F(4)] = actionIncFilter; - keys[KEY_F(5)] = actionToggleTreeView; - keys[KEY_F(6)] = actionSetSortColumn; - keys[KEY_F(7)] = actionHigherPriority; - keys[KEY_F(8)] = actionLowerPriority; - keys[KEY_F(9)] = actionKill; - keys[KEY_F(10)] = actionQuit; - keys[KEY_F(18)] = actionExpandCollapseOrSortColumn; - keys[KEY_RECLICK] = actionExpandOrCollapse; -} diff -Nru pcp-5.3.1/src/pcp/htop/Action.h pcp-5.3.2/src/pcp/htop/Action.h --- pcp-5.3.1/src/pcp/htop/Action.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Action.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -#ifndef HEADER_Action -#define HEADER_Action -/* -htop - Action.h -(C) 2015 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include - -#include "Header.h" -#include "Object.h" -#include "Panel.h" -#include "Process.h" -#include "ProcessList.h" -#include "Settings.h" -#include "UsersTable.h" - - -typedef enum { - HTOP_OK = 0x00, - HTOP_REFRESH = 0x01, - HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH - HTOP_SAVE_SETTINGS = 0x04, - HTOP_KEEP_FOLLOWING = 0x08, - HTOP_QUIT = 0x10, - HTOP_REDRAW_BAR = 0x20, - HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH -} Htop_Reaction; - -struct MainPanel_; - -typedef struct State_ { - Settings* settings; - UsersTable* ut; - ProcessList* pl; - struct MainPanel_* mainPanel; - Header* header; - bool pauseProcessUpdate; - bool hideProcessSelection; -} State; - -static inline bool State_hideFunctionBar(const State* st) { - return st->settings->hideFunctionBar == 2 || (st->settings->hideFunctionBar == 1 && st->hideProcessSelection); -} - -typedef Htop_Reaction (*Htop_Action)(State* st); - -Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess); - -bool Action_setUserOnly(const char* userName, uid_t* userId); - -Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey); - -Htop_Reaction Action_follow(State* st); - -void Action_setBindings(Htop_Action* keys); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/AUTHORS pcp-5.3.2/src/pcp/htop/AUTHORS --- pcp-5.3.1/src/pcp/htop/AUTHORS 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/AUTHORS 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -Originally authored by: - Hisham H. Muhammad - -Currently maintained by the htop dev team: - Benny Baumann - Christian Göttsche - Daniel Lange - Nathan Scott - -For the full list of contributors see: - git log --format="%aN" | sort -u diff -Nru pcp-5.3.1/src/pcp/htop/AvailableColumnsPanel.c pcp-5.3.2/src/pcp/htop/AvailableColumnsPanel.c --- pcp-5.3.1/src/pcp/htop/AvailableColumnsPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/AvailableColumnsPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -/* -htop - AvailableColumnsPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "AvailableColumnsPanel.h" - -#include -#include -#include - -#include "ColumnsPanel.h" -#include "FunctionBar.h" -#include "ListItem.h" -#include "Object.h" -#include "Platform.h" -#include "Process.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static const char* const AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL}; - -static void AvailableColumnsPanel_delete(Object* object) { - Panel* super = (Panel*) object; - AvailableColumnsPanel* this = (AvailableColumnsPanel*) object; - Panel_done(super); - free(this); -} - -static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) { - AvailableColumnsPanel* this = (AvailableColumnsPanel*) super; - HandlerResult result = IGNORED; - - switch(ch) { - case 13: - case KEY_ENTER: - case KEY_F(5): - { - const ListItem* selected = (ListItem*) Panel_getSelected(super); - if (!selected) - break; - - int key = selected->key; - int at = Panel_getSelectedIndex(this->columns); - Panel_insert(this->columns, at, (Object*) ListItem_new(Process_fields[key].name, key)); - Panel_setSelected(this->columns, at+1); - ColumnsPanel_update(this->columns); - result = HANDLED; - break; - } - default: - { - if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) - result = Panel_selectByTyping(super, ch); - break; - } - } - return result; -} - -const PanelClass AvailableColumnsPanel_class = { - .super = { - .extends = Class(Panel), - .delete = AvailableColumnsPanel_delete - }, - .eventHandler = AvailableColumnsPanel_eventHandler -}; - -AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns) { - AvailableColumnsPanel* this = AllocThis(AvailableColumnsPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_new(AvailableColumnsFunctions, NULL, NULL); - Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); - - Panel_setHeader(super, "Available Columns"); - - for (int i = 1; i < LAST_PROCESSFIELD; i++) { - if (i != COMM && Process_fields[i].description) { - char description[256]; - xSnprintf(description, sizeof(description), "%s - %s", Process_fields[i].name, Process_fields[i].description); - Panel_add(super, (Object*) ListItem_new(description, i)); - } - } - this->columns = columns; - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/AvailableColumnsPanel.h pcp-5.3.2/src/pcp/htop/AvailableColumnsPanel.h --- pcp-5.3.1/src/pcp/htop/AvailableColumnsPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/AvailableColumnsPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#ifndef HEADER_AvailableColumnsPanel -#define HEADER_AvailableColumnsPanel -/* -htop - AvailableColumnsPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Panel.h" - -typedef struct AvailableColumnsPanel_ { - Panel super; - Panel* columns; -} AvailableColumnsPanel; - -extern const PanelClass AvailableColumnsPanel_class; - -AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/AvailableMetersPanel.c pcp-5.3.2/src/pcp/htop/AvailableMetersPanel.c --- pcp-5.3.1/src/pcp/htop/AvailableMetersPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/AvailableMetersPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -/* -htop - AvailableMetersPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "AvailableMetersPanel.h" - -#include -#include -#include - -#include "CPUMeter.h" -#include "FunctionBar.h" -#include "Header.h" -#include "ListItem.h" -#include "Meter.h" -#include "MetersPanel.h" -#include "Object.h" -#include "Platform.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static void AvailableMetersPanel_delete(Object* object) { - Panel* super = (Panel*) object; - AvailableMetersPanel* this = (AvailableMetersPanel*) object; - Panel_done(super); - free(this); -} - -static inline void AvailableMetersPanel_addMeter(Header* header, Panel* panel, const MeterClass* type, unsigned int param, int column) { - const Meter* meter = Header_addMeterByClass(header, type, param, column); - Panel_add(panel, (Object*) Meter_toListItem(meter, false)); - Panel_setSelected(panel, Panel_size(panel) - 1); - MetersPanel_setMoving((MetersPanel*)panel, true); -} - -static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) { - AvailableMetersPanel* this = (AvailableMetersPanel*) super; - Header* header = this->header; - - const ListItem* selected = (ListItem*) Panel_getSelected(super); - if (!selected) - return IGNORED; - - unsigned int param = selected->key & 0xff; - int type = selected->key >> 16; - HandlerResult result = IGNORED; - bool update = false; - - switch(ch) { - case KEY_F(5): - case 'l': - case 'L': - { - AvailableMetersPanel_addMeter(header, this->leftPanel, Platform_meterTypes[type], param, 0); - result = HANDLED; - update = true; - break; - } - case 0x0a: - case 0x0d: - case KEY_ENTER: - case KEY_F(6): - case 'r': - case 'R': - { - AvailableMetersPanel_addMeter(header, this->rightPanel, Platform_meterTypes[type], param, 1); - result = (KEY_LEFT << 16) | SYNTH_KEY; - update = true; - break; - } - } - if (update) { - this->settings->changed = true; - Header_calculateHeight(header); - Header_updateData(header); - Header_draw(header); - ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); - } - return result; -} - -const PanelClass AvailableMetersPanel_class = { - .super = { - .extends = Class(Panel), - .delete = AvailableMetersPanel_delete - }, - .eventHandler = AvailableMetersPanel_eventHandler -}; - -AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl) { - AvailableMetersPanel* this = AllocThis(AvailableMetersPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_newEnterEsc("Add ", "Done "); - Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); - - this->settings = settings; - this->header = header; - this->leftPanel = leftMeters; - this->rightPanel = rightMeters; - this->scr = scr; - - Panel_setHeader(super, "Available meters"); - // Platform_meterTypes[0] should be always (&CPUMeter_class), which we will - // handle separately in the code below. - for (int i = 1; Platform_meterTypes[i]; i++) { - const MeterClass* type = Platform_meterTypes[i]; - assert(type != &CPUMeter_class); - const char* label = type->description ? type->description : type->uiName; - Panel_add(super, (Object*) ListItem_new(label, i << 16)); - } - // Handle (&CPUMeter_class) - const MeterClass* type = &CPUMeter_class; - unsigned int cpus = pl->cpuCount; - if (cpus > 1) { - Panel_add(super, (Object*) ListItem_new("CPU average", 0)); - for (unsigned int i = 1; i <= cpus; i++) { - char buffer[50]; - xSnprintf(buffer, sizeof(buffer), "%s %d", type->uiName, Settings_cpuId(this->settings, i - 1)); - Panel_add(super, (Object*) ListItem_new(buffer, i)); - } - } else { - Panel_add(super, (Object*) ListItem_new("CPU", 1)); - } - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/AvailableMetersPanel.h pcp-5.3.2/src/pcp/htop/AvailableMetersPanel.h --- pcp-5.3.1/src/pcp/htop/AvailableMetersPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/AvailableMetersPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#ifndef HEADER_AvailableMetersPanel -#define HEADER_AvailableMetersPanel -/* -htop - AvailableMetersPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Header.h" -#include "Panel.h" -#include "ProcessList.h" -#include "ScreenManager.h" -#include "Settings.h" - -typedef struct AvailableMetersPanel_ { - Panel super; - ScreenManager* scr; - - Settings* settings; - Header* header; - Panel* leftPanel; - Panel* rightPanel; -} AvailableMetersPanel; - -extern const PanelClass AvailableMetersPanel_class; - -AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/BatteryMeter.c pcp-5.3.2/src/pcp/htop/BatteryMeter.c --- pcp-5.3.1/src/pcp/htop/BatteryMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/BatteryMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* -htop - BatteryMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. - -This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). -*/ - -#include "BatteryMeter.h" - -#include - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "XUtils.h" - - -static const int BatteryMeter_attributes[] = { - BATTERY -}; - -static void BatteryMeter_updateValues(Meter* this) { - ACPresence isOnAC; - double percent; - - Platform_getBattery(&percent, &isOnAC); - - if (isnan(percent)) { - this->values[0] = NAN; - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A"); - return; - } - - this->values[0] = percent; - - const char* text; - switch (isOnAC) { - case AC_PRESENT: - text = this->mode == TEXT_METERMODE ? " (Running on A/C)" : "(A/C)"; - break; - case AC_ABSENT: - text = this->mode == TEXT_METERMODE ? " (Running on battery)" : "(bat)"; - break; - case AC_ERROR: - default: - text = ""; - break; - } - - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%%s", percent, text); -} - -const MeterClass BatteryMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = BatteryMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 100.0, - .attributes = BatteryMeter_attributes, - .name = "Battery", - .uiName = "Battery", - .caption = "Battery: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/BatteryMeter.h pcp-5.3.2/src/pcp/htop/BatteryMeter.h --- pcp-5.3.1/src/pcp/htop/BatteryMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/BatteryMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -#ifndef HEADER_BatteryMeter -#define HEADER_BatteryMeter -/* -htop - BatteryMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. - -This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). -*/ - -#include "Meter.h" - -typedef enum ACPresence_ { - AC_ABSENT, - AC_PRESENT, - AC_ERROR -} ACPresence; - -extern const MeterClass BatteryMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/CategoriesPanel.c pcp-5.3.2/src/pcp/htop/CategoriesPanel.c --- pcp-5.3.1/src/pcp/htop/CategoriesPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CategoriesPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -/* -htop - CategoriesPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "CategoriesPanel.h" - -#include -#include -#include - -#include "AvailableColumnsPanel.h" -#include "AvailableMetersPanel.h" -#include "ColorsPanel.h" -#include "ColumnsPanel.h" -#include "DisplayOptionsPanel.h" -#include "FunctionBar.h" -#include "ListItem.h" -#include "MetersPanel.h" -#include "Object.h" -#include "ProvideCurses.h" -#include "Vector.h" - - -static const char* const CategoriesFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; - -static void CategoriesPanel_delete(Object* object) { - Panel* super = (Panel*) object; - CategoriesPanel* this = (CategoriesPanel*) object; - Panel_done(super); - free(this); -} - -void CategoriesPanel_makeMetersPage(CategoriesPanel* this) { - MetersPanel* leftMeters = MetersPanel_new(this->settings, "Left column", this->header->columns[0], this->scr); - MetersPanel* rightMeters = MetersPanel_new(this->settings, "Right column", this->header->columns[1], this->scr); - leftMeters->rightNeighbor = rightMeters; - rightMeters->leftNeighbor = leftMeters; - Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, this->header, (Panel*) leftMeters, (Panel*) rightMeters, this->scr, this->pl); - ScreenManager_add(this->scr, (Panel*) leftMeters, 20); - ScreenManager_add(this->scr, (Panel*) rightMeters, 20); - ScreenManager_add(this->scr, availableMeters, -1); -} - -static void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) { - Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr); - ScreenManager_add(this->scr, displayOptions, -1); -} - -static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) { - Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr); - ScreenManager_add(this->scr, colors, -1); -} - -static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) { - Panel* columns = (Panel*) ColumnsPanel_new(this->settings); - Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns); - ScreenManager_add(this->scr, columns, 20); - ScreenManager_add(this->scr, availableColumns, -1); -} - -static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) { - CategoriesPanel* this = (CategoriesPanel*) super; - - HandlerResult result = IGNORED; - - int selected = Panel_getSelectedIndex(super); - switch (ch) { - case EVENT_SET_SELECTED: - result = HANDLED; - break; - case KEY_UP: - case KEY_CTRL('P'): - case KEY_DOWN: - case KEY_CTRL('N'): - case KEY_NPAGE: - case KEY_PPAGE: - case KEY_HOME: - case KEY_END: { - int previous = selected; - Panel_onKey(super, ch); - selected = Panel_getSelectedIndex(super); - if (previous != selected) - result = HANDLED; - break; - } - default: - if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) - result = Panel_selectByTyping(super, ch); - if (result == BREAK_LOOP) - result = IGNORED; - break; - } - if (result == HANDLED) { - int size = ScreenManager_size(this->scr); - for (int i = 1; i < size; i++) - ScreenManager_remove(this->scr, 1); - - switch (selected) { - case 0: - CategoriesPanel_makeMetersPage(this); - break; - case 1: - CategoriesPanel_makeDisplayOptionsPage(this); - break; - case 2: - CategoriesPanel_makeColorsPage(this); - break; - case 3: - CategoriesPanel_makeColumnsPage(this); - break; - } - } - return result; -} - -const PanelClass CategoriesPanel_class = { - .super = { - .extends = Class(Panel), - .delete = CategoriesPanel_delete - }, - .eventHandler = CategoriesPanel_eventHandler -}; - -CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Header* header, ProcessList* pl) { - CategoriesPanel* this = AllocThis(CategoriesPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_new(CategoriesFunctions, NULL, NULL); - Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); - - this->scr = scr; - this->settings = settings; - this->header = header; - this->pl = pl; - Panel_setHeader(super, "Setup"); - Panel_add(super, (Object*) ListItem_new("Meters", 0)); - Panel_add(super, (Object*) ListItem_new("Display options", 0)); - Panel_add(super, (Object*) ListItem_new("Colors", 0)); - Panel_add(super, (Object*) ListItem_new("Columns", 0)); - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/CategoriesPanel.h pcp-5.3.2/src/pcp/htop/CategoriesPanel.h --- pcp-5.3.1/src/pcp/htop/CategoriesPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CategoriesPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -#ifndef HEADER_CategoriesPanel -#define HEADER_CategoriesPanel -/* -htop - CategoriesPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Header.h" -#include "Panel.h" -#include "ProcessList.h" -#include "ScreenManager.h" -#include "Settings.h" - -typedef struct CategoriesPanel_ { - Panel super; - ScreenManager* scr; - - Settings* settings; - Header* header; - ProcessList* pl; -} CategoriesPanel; - -void CategoriesPanel_makeMetersPage(CategoriesPanel* this); - -extern const PanelClass CategoriesPanel_class; - -CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Header* header, ProcessList* pl); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ClockMeter.c pcp-5.3.2/src/pcp/htop/ClockMeter.c --- pcp-5.3.1/src/pcp/htop/ClockMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ClockMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* -htop - ClockMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "ClockMeter.h" - -#include - -#include "CRT.h" -#include "Object.h" - - -static const int ClockMeter_attributes[] = { - CLOCK -}; - -static void ClockMeter_updateValues(Meter* this) { - const ProcessList* pl = this->pl; - - struct tm result; - const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result); - this->values[0] = lt->tm_hour * 60 + lt->tm_min; - strftime(this->txtBuffer, sizeof(this->txtBuffer), "%H:%M:%S", lt); -} - -const MeterClass ClockMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = ClockMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 1440, /* 24*60 */ - .attributes = ClockMeter_attributes, - .name = "Clock", - .uiName = "Clock", - .caption = "Time: ", -}; diff -Nru pcp-5.3.1/src/pcp/htop/ClockMeter.h pcp-5.3.2/src/pcp/htop/ClockMeter.h --- pcp-5.3.1/src/pcp/htop/ClockMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ClockMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_ClockMeter -#define HEADER_ClockMeter -/* -htop - ClockMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass ClockMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ColorsPanel.c pcp-5.3.2/src/pcp/htop/ColorsPanel.c --- pcp-5.3.1/src/pcp/htop/ColorsPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ColorsPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -/* -htop - ColorsPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ColorsPanel.h" - -#include -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "Header.h" -#include "Object.h" -#include "OptionItem.h" -#include "ProvideCurses.h" -#include "RichString.h" -#include "Vector.h" - - -// TO ADD A NEW SCHEME: -// * Increment the size of bool check in ColorsPanel.h -// * Add the entry in the ColorSchemeNames array below in the file -// * Add a define in CRT.h that matches the order of the array -// * Add the colors in CRT_setColors - - -static const char* const ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; - -static const char* const ColorSchemeNames[] = { - "Default", - "Monochromatic", - "Black on White", - "Light Terminal", - "MC", - "Black Night", - "Broken Gray", - NULL -}; - -static void ColorsPanel_delete(Object* object) { - Panel* super = (Panel*) object; - ColorsPanel* this = (ColorsPanel*) object; - Panel_done(super); - free(this); -} - -static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) { - ColorsPanel* this = (ColorsPanel*) super; - - HandlerResult result = IGNORED; - int mark = Panel_getSelectedIndex(super); - - switch(ch) { - case 0x0a: - case 0x0d: - case KEY_ENTER: - case KEY_MOUSE: - case KEY_RECLICK: - case ' ': - assert(mark >= 0); - assert(mark < LAST_COLORSCHEME); - for (int i = 0; ColorSchemeNames[i] != NULL; i++) - CheckItem_set((CheckItem*)Panel_get(super, i), false); - CheckItem_set((CheckItem*)Panel_get(super, mark), true); - - this->settings->colorScheme = mark; - this->settings->changed = true; - - CRT_setColors(mark); - clear(); - - result = HANDLED | REDRAW; - } - - return result; -} - -const PanelClass ColorsPanel_class = { - .super = { - .extends = Class(Panel), - .delete = ColorsPanel_delete - }, - .eventHandler = ColorsPanel_eventHandler -}; - -ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) { - ColorsPanel* this = AllocThis(ColorsPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_new(ColorsFunctions, NULL, NULL); - Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true, fuBar); - - this->settings = settings; - this->scr = scr; - - assert(ARRAYSIZE(ColorSchemeNames) == LAST_COLORSCHEME + 1); - - Panel_setHeader(super, "Colors"); - for (int i = 0; ColorSchemeNames[i] != NULL; i++) { - Panel_add(super, (Object*) CheckItem_newByVal(ColorSchemeNames[i], false)); - } - CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true); - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/ColorsPanel.h pcp-5.3.2/src/pcp/htop/ColorsPanel.h --- pcp-5.3.1/src/pcp/htop/ColorsPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ColorsPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -#ifndef HEADER_ColorsPanel -#define HEADER_ColorsPanel -/* -htop - ColorsPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Panel.h" -#include "ScreenManager.h" -#include "Settings.h" - -typedef struct ColorsPanel_ { - Panel super; - - Settings* settings; - ScreenManager* scr; -} ColorsPanel; - -extern const PanelClass ColorsPanel_class; - -ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ColumnsPanel.c pcp-5.3.2/src/pcp/htop/ColumnsPanel.c --- pcp-5.3.1/src/pcp/htop/ColumnsPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ColumnsPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,149 +0,0 @@ -/* -htop - ColumnsPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ColumnsPanel.h" - -#include -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "ListItem.h" -#include "Object.h" -#include "Process.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static const char* const ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL}; - -static void ColumnsPanel_delete(Object* object) { - Panel* super = (Panel*) object; - ColumnsPanel* this = (ColumnsPanel*) object; - Panel_done(super); - free(this); -} - -static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) { - ColumnsPanel* const this = (ColumnsPanel*) super; - - int selected = Panel_getSelectedIndex(super); - HandlerResult result = IGNORED; - int size = Panel_size(super); - - switch(ch) { - case 0x0a: - case 0x0d: - case KEY_ENTER: - case KEY_MOUSE: - case KEY_RECLICK: - { - if (selected < size - 1) { - this->moving = !(this->moving); - Panel_setSelectionColor(super, this->moving ? PANEL_SELECTION_FOLLOW : PANEL_SELECTION_FOCUS); - ListItem* selectedItem = (ListItem*) Panel_getSelected(super); - if (selectedItem) - selectedItem->moving = this->moving; - result = HANDLED; - } - break; - } - case KEY_UP: - { - if (!this->moving) { - break; - } - } - /* else fallthrough */ - case KEY_F(7): - case '[': - case '-': - { - if (selected < size - 1) - Panel_moveSelectedUp(super); - result = HANDLED; - break; - } - case KEY_DOWN: - { - if (!this->moving) { - break; - } - } - /* else fallthrough */ - case KEY_F(8): - case ']': - case '+': - { - if (selected < size - 2) - Panel_moveSelectedDown(super); - result = HANDLED; - break; - } - case KEY_F(9): - case KEY_DC: - { - if (selected < size - 1) { - Panel_remove(super, selected); - } - result = HANDLED; - break; - } - default: - { - if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) - result = Panel_selectByTyping(super, ch); - if (result == BREAK_LOOP) - result = IGNORED; - break; - } - } - if (result == HANDLED) - ColumnsPanel_update(super); - return result; -} - -const PanelClass ColumnsPanel_class = { - .super = { - .extends = Class(Panel), - .delete = ColumnsPanel_delete - }, - .eventHandler = ColumnsPanel_eventHandler -}; - -ColumnsPanel* ColumnsPanel_new(Settings* settings) { - ColumnsPanel* this = AllocThis(ColumnsPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_new(ColumnsFunctions, NULL, NULL); - Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); - - this->settings = settings; - this->moving = false; - Panel_setHeader(super, "Active Columns"); - - const ProcessField* fields = this->settings->fields; - for (; *fields; fields++) { - if (Process_fields[*fields].name) { - Panel_add(super, (Object*) ListItem_new(Process_fields[*fields].name, *fields)); - } - } - return this; -} - -void ColumnsPanel_update(Panel* super) { - ColumnsPanel* this = (ColumnsPanel*) super; - int size = Panel_size(super); - this->settings->changed = true; - this->settings->fields = xRealloc(this->settings->fields, sizeof(ProcessField) * (size + 1)); - this->settings->flags = 0; - for (int i = 0; i < size; i++) { - int key = ((ListItem*) Panel_get(super, i))->key; - this->settings->fields[i] = key; - this->settings->flags |= Process_fields[key].flags; - } - this->settings->fields[size] = 0; -} diff -Nru pcp-5.3.1/src/pcp/htop/ColumnsPanel.h pcp-5.3.2/src/pcp/htop/ColumnsPanel.h --- pcp-5.3.1/src/pcp/htop/ColumnsPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ColumnsPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#ifndef HEADER_ColumnsPanel -#define HEADER_ColumnsPanel -/* -htop - ColumnsPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "Panel.h" -#include "Settings.h" - -typedef struct ColumnsPanel_ { - Panel super; - - Settings* settings; - bool moving; -} ColumnsPanel; - -extern const PanelClass ColumnsPanel_class; - -ColumnsPanel* ColumnsPanel_new(Settings* settings); - -void ColumnsPanel_update(Panel* super); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/CommandLine.c pcp-5.3.2/src/pcp/htop/CommandLine.c --- pcp-5.3.1/src/pcp/htop/CommandLine.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CommandLine.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,372 +0,0 @@ -/* -htop - CommandLine.c -(C) 2004-2011 Hisham H. Muhammad -(C) 2020-2021 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "CommandLine.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Action.h" -#include "CRT.h" -#include "Hashtable.h" -#include "Header.h" -#include "IncSet.h" -#include "MainPanel.h" -#include "MetersPanel.h" -#include "Panel.h" -#include "Platform.h" -#include "Process.h" -#include "ProcessList.h" -#include "ProvideCurses.h" -#include "ScreenManager.h" -#include "Settings.h" -#include "UsersTable.h" -#include "XUtils.h" - - -static void printVersionFlag(const char* name) { - printf("%s " VERSION "\n", name); -} - -static void printHelpFlag(const char* name) { - printf("%s " VERSION "\n" - COPYRIGHT "\n" - "Released under the GNU GPLv2.\n\n" - "-C --no-color Use a monochrome color scheme\n" - "-d --delay=DELAY Set the delay between updates, in tenths of seconds\n" - "-F --filter=FILTER Show only the commands matching the given filter\n" - "-h --help Print this help screen\n" - "-H --highlight-changes[=DELAY] Highlight new and old processes\n" - "-M --no-mouse Disable the mouse\n" - "-p --pid=PID[,PID,PID...] Show only the given PIDs\n" - "-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n" - "-t --tree Show the tree view (can be combined with -s)\n" - "-u --user[=USERNAME] Show only processes for a given user (or $USER)\n" - "-U --no-unicode Do not use unicode but plain ASCII\n" - "-V --version Print version info\n", name); - Platform_longOptionsUsage(name); - printf("\n" - "Long options may be passed with a single dash.\n\n" - "Press F1 inside %s for online help.\n" - "See 'man %s' for more information.\n", name, name); -} - -// ---------------------------------------- - -typedef struct CommandLineSettings_ { - Hashtable* pidMatchList; - char* commFilter; - uid_t userId; - int sortKey; - int delay; - bool useColors; - bool enableMouse; - bool treeView; - bool allowUnicode; - bool highlightChanges; - int highlightDelaySecs; -} CommandLineSettings; - -static CommandLineSettings parseArguments(const char* program, int argc, char** argv) { - - CommandLineSettings flags = { - .pidMatchList = NULL, - .commFilter = NULL, - .userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2)) - .sortKey = 0, - .delay = -1, - .useColors = true, - .enableMouse = true, - .treeView = false, - .allowUnicode = true, - .highlightChanges = false, - .highlightDelaySecs = -1, - }; - - const struct option long_opts[] = - { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"delay", required_argument, 0, 'd'}, - {"sort-key", required_argument, 0, 's'}, - {"user", optional_argument, 0, 'u'}, - {"no-color", no_argument, 0, 'C'}, - {"no-colour", no_argument, 0, 'C'}, - {"no-mouse", no_argument, 0, 'M'}, - {"no-unicode", no_argument, 0, 'U'}, - {"tree", no_argument, 0, 't'}, - {"pid", required_argument, 0, 'p'}, - {"filter", required_argument, 0, 'F'}, - {"highlight-changes", optional_argument, 0, 'H'}, - PLATFORM_LONG_OPTIONS - {0,0,0,0} - }; - - int opt, opti=0; - /* Parse arguments */ - while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) { - if (opt == EOF) break; - switch (opt) { - case 'h': - printHelpFlag(program); - exit(0); - case 'V': - printVersionFlag(program); - exit(0); - case 's': - assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */ - if (String_eq(optarg, "help")) { - for (int j = 1; j < LAST_PROCESSFIELD; j++) { - const char* name = Process_fields[j].name; - const char* description = Process_fields[j].description; - if (name) printf("%19s %s\n", name, description); - } - exit(0); - } - flags.sortKey = 0; - for (int j = 1; j < LAST_PROCESSFIELD; j++) { - if (Process_fields[j].name == NULL) - continue; - if (String_eq(optarg, Process_fields[j].name)) { - flags.sortKey = j; - break; - } - } - if (flags.sortKey == 0) { - fprintf(stderr, "Error: invalid column \"%s\".\n", optarg); - exit(1); - } - break; - case 'd': - if (sscanf(optarg, "%16d", &(flags.delay)) == 1) { - if (flags.delay < 1) flags.delay = 1; - if (flags.delay > 100) flags.delay = 100; - } else { - fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg); - exit(1); - } - break; - case 'u': - { - const char *username = optarg; - if (!username && optind < argc && argv[optind] != NULL && - (argv[optind][0] != '\0' && argv[optind][0] != '-')) { - username = argv[optind++]; - } - - if (!username) { - flags.userId = geteuid(); - } else if (!Action_setUserOnly(username, &(flags.userId))) { - fprintf(stderr, "Error: invalid user \"%s\".\n", username); - exit(1); - } - break; - } - case 'C': - flags.useColors = false; - break; - case 'M': - flags.enableMouse = false; - break; - case 'U': - flags.allowUnicode = false; - break; - case 't': - flags.treeView = true; - break; - case 'p': { - assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */ - char* argCopy = xStrdup(optarg); - char* saveptr; - const char* pid = strtok_r(argCopy, ",", &saveptr); - - if (!flags.pidMatchList) { - flags.pidMatchList = Hashtable_new(8, false); - } - - while(pid) { - unsigned int num_pid = atoi(pid); - // deepcode ignore CastIntegerToAddress: we just want a non-NUll pointer here - Hashtable_put(flags.pidMatchList, num_pid, (void *) 1); - pid = strtok_r(NULL, ",", &saveptr); - } - free(argCopy); - - break; - } - case 'F': { - assert(optarg); - free_and_xStrdup(&flags.commFilter, optarg); - break; - } - case 'H': { - const char *delay = optarg; - if (!delay && optind < argc && argv[optind] != NULL && - (argv[optind][0] != '\0' && argv[optind][0] != '-')) { - delay = argv[optind++]; - } - if (delay) { - if (sscanf(delay, "%16d", &(flags.highlightDelaySecs)) == 1) { - if (flags.highlightDelaySecs < 1) - flags.highlightDelaySecs = 1; - } else { - fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay); - exit(1); - } - } - flags.highlightChanges = true; - break; - } - - default: - if (Platform_getLongOption(opt, argc, argv) == false) - exit(1); - break; - } - } - return flags; -} - -static void millisleep(unsigned long millisec) { - struct timespec req = { - .tv_sec = 0, - .tv_nsec = millisec * 1000000L - }; - while(nanosleep(&req,&req)==-1) { - continue; - } -} - -static void setCommFilter(State* state, char** commFilter) { - ProcessList* pl = state->pl; - IncSet* inc = state->mainPanel->inc; - - IncSet_setFilter(inc, *commFilter); - pl->incFilter = IncSet_filter(inc); - - free(*commFilter); - *commFilter = NULL; -} - -int CommandLine_run(const char* name, int argc, char** argv) { - - /* initialize locale */ - const char* lc_ctype; - if ((lc_ctype = getenv("LC_CTYPE")) || (lc_ctype = getenv("LC_ALL"))) - setlocale(LC_CTYPE, lc_ctype); - else - setlocale(LC_CTYPE, ""); - - CommandLineSettings flags = parseArguments(name, argc, argv); - - Platform_init(); - - Process_setupColumnWidths(); - - UsersTable* ut = UsersTable_new(); - ProcessList* pl = ProcessList_new(ut, flags.pidMatchList, flags.userId); - - Settings* settings = Settings_new(pl->cpuCount); - pl->settings = settings; - - Header* header = Header_new(pl, settings, 2); - - Header_populateFromSettings(header); - - if (flags.delay != -1) - settings->delay = flags.delay; - if (!flags.useColors) - settings->colorScheme = COLORSCHEME_MONOCHROME; - if (!flags.enableMouse) - settings->enableMouse = false; - if (flags.treeView) - settings->treeView = true; - if (flags.highlightChanges) - settings->highlightChanges = true; - if (flags.highlightDelaySecs != -1) - settings->highlightDelaySecs = flags.highlightDelaySecs; - if (flags.sortKey > 0) { - // -t -s means "tree sorted by key" - // -s means "list sorted by key" (previous existing behavior) - if (!flags.treeView) { - settings->treeView = false; - } - Settings_setSortKey(settings, flags.sortKey); - } - - CRT_init(settings, flags.allowUnicode); - - MainPanel* panel = MainPanel_new(); - ProcessList_setPanel(pl, (Panel*) panel); - - MainPanel_updateTreeFunctions(panel, settings->treeView); - - State state = { - .settings = settings, - .ut = ut, - .pl = pl, - .mainPanel = panel, - .header = header, - .pauseProcessUpdate = false, - .hideProcessSelection = false, - }; - - MainPanel_setState(panel, &state); - if (flags.commFilter) - setCommFilter(&state, &(flags.commFilter)); - - ScreenManager* scr = ScreenManager_new(header, settings, &state, true); - ScreenManager_add(scr, (Panel*) panel, -1); - - ProcessList_scan(pl, false); - millisleep(75); - ProcessList_scan(pl, false); - - if (settings->allBranchesCollapsed) - ProcessList_collapseAllBranches(pl); - - ScreenManager_run(scr, NULL, NULL); - - attron(CRT_colors[RESET_COLOR]); - mvhline(LINES-1, 0, ' ', COLS); - attroff(CRT_colors[RESET_COLOR]); - refresh(); - - Platform_done(); - - CRT_done(); - - if (settings->changed) { - int r = Settings_write(settings); - if (r < 0) - fprintf(stderr, "Can not save configuration to %s: %s\n", settings->filename, strerror(-r)); - } - - Header_delete(header); - ProcessList_delete(pl); - - ScreenManager_delete(scr); - MetersPanel_cleanup(); - - UsersTable_delete(ut); - Settings_delete(settings); - - if (flags.pidMatchList) - Hashtable_delete(flags.pidMatchList); - - return 0; -} diff -Nru pcp-5.3.1/src/pcp/htop/CommandLine.h pcp-5.3.2/src/pcp/htop/CommandLine.h --- pcp-5.3.1/src/pcp/htop/CommandLine.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CommandLine.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_CommandLine -#define HEADER_CommandLine -/* -htop - CommandLine.h -(C) 2004-2011 Hisham H. Muhammad -(C) 2020-2021 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - - -int CommandLine_run(const char* name, int argc, char** argv); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/CommandScreen.c pcp-5.3.2/src/pcp/htop/CommandScreen.c --- pcp-5.3.1/src/pcp/htop/CommandScreen.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CommandScreen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -#include "config.h" // IWYU pragma: keep - -#include "CommandScreen.h" - -#include -#include - -#include "Macros.h" -#include "Panel.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static void CommandScreen_scan(InfoScreen* this) { - Panel* panel = this->display; - int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0); - Panel_prune(panel); - - const char* p = Process_getCommand(this->process); - char line[COLS + 1]; - int line_offset = 0, last_spc = -1, len; - for (; *p != '\0'; p++, line_offset++) { - assert(line_offset >= 0 && (size_t)line_offset < sizeof(line)); - line[line_offset] = *p; - if (*p == ' ') { - last_spc = line_offset; - } - - if (line_offset == COLS) { - len = (last_spc == -1) ? line_offset : last_spc; - line[len] = '\0'; - InfoScreen_addLine(this, line); - - line_offset -= len; - last_spc = -1; - memcpy(line, p - line_offset, line_offset + 1); - } - } - - if (line_offset > 0) { - line[line_offset] = '\0'; - InfoScreen_addLine(this, line); - } - - Panel_setSelected(panel, idx); -} - -static void CommandScreen_draw(InfoScreen* this) { - InfoScreen_drawTitled(this, "Command of process %d - %s", this->process->pid, Process_getCommand(this->process)); -} - -const InfoScreenClass CommandScreen_class = { - .super = { - .extends = Class(Object), - .delete = CommandScreen_delete - }, - .scan = CommandScreen_scan, - .draw = CommandScreen_draw -}; - -CommandScreen* CommandScreen_new(Process* process) { - CommandScreen* this = AllocThis(CommandScreen); - return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " "); -} - -void CommandScreen_delete(Object* this) { - free(InfoScreen_done((InfoScreen*)this)); -} diff -Nru pcp-5.3.1/src/pcp/htop/CommandScreen.h pcp-5.3.2/src/pcp/htop/CommandScreen.h --- pcp-5.3.1/src/pcp/htop/CommandScreen.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CommandScreen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -#ifndef HEADER_CommandScreen -#define HEADER_CommandScreen - -#include "InfoScreen.h" -#include "Object.h" -#include "Process.h" - - -typedef struct CommandScreen_ { - InfoScreen super; -} CommandScreen; - -extern const InfoScreenClass CommandScreen_class; - -CommandScreen* CommandScreen_new(Process* process); - -void CommandScreen_delete(Object* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Compat.c pcp-5.3.2/src/pcp/htop/Compat.c --- pcp-5.3.1/src/pcp/htop/Compat.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Compat.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -/* -htop - Compat.c -(C) 2020 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "Compat.h" - -#include -#include // IWYU pragma: keep -#include -#include -#include // IWYU pragma: keep - -#include "XUtils.h" // IWYU pragma: keep - - -int Compat_faccessat(int dirfd, - const char* pathname, - int mode, - int flags) { - int ret; - -#ifdef HAVE_FACCESSAT - - // Implementation note: AT_SYMLINK_NOFOLLOW unsupported on FreeBSD, fallback to lstat in that case - - errno = 0; - - ret = faccessat(dirfd, pathname, mode, flags); - if (!ret || errno != EINVAL) - return ret; - -#endif - - // Error out on unsupported configurations - if (dirfd != AT_FDCWD || mode != F_OK) { - errno = EINVAL; - return -1; - } - - // Fallback to stat(2)/lstat(2) depending on flags - struct stat statinfo; - if(flags) { - ret = lstat(pathname, &statinfo); - } else { - ret = stat(pathname, &statinfo); - } - - return ret; -} - -int Compat_fstatat(int dirfd, - const char* dirpath, - const char* pathname, - struct stat* statbuf, - int flags) { - -#ifdef HAVE_FSTATAT - - (void)dirpath; - - return fstatat(dirfd, pathname, statbuf, flags); - -#else - - (void)dirfd; - - char path[4096]; - xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); - - if (flags & AT_SYMLINK_NOFOLLOW) - return lstat(path, statbuf); - - return stat(path, statbuf); - -#endif -} - -#ifndef HAVE_OPENAT - -int Compat_openat(const char* dirpath, - const char* pathname, - int flags) { - - char path[4096]; - xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); - - return open(path, flags); -} - -#endif /* !HAVE_OPENAT */ - -ssize_t Compat_readlinkat(int dirfd, - const char* dirpath, - const char* pathname, - char* buf, - size_t bufsize) { - -#ifdef HAVE_READLINKAT - - (void)dirpath; - - return readlinkat(dirfd, pathname, buf, bufsize); - -#else - - (void)dirfd; - - char path[4096]; - xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); - - return readlink(path, buf, bufsize); - -#endif -} diff -Nru pcp-5.3.1/src/pcp/htop/Compat.h pcp-5.3.2/src/pcp/htop/Compat.h --- pcp-5.3.1/src/pcp/htop/Compat.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Compat.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#ifndef HEADER_Compat -#define HEADER_Compat -/* -htop - Compat.h -(C) 2020 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include -#include -#include // IWYU pragma: keep - - -int Compat_faccessat(int dirfd, - const char* pathname, - int mode, - int flags); - -int Compat_fstatat(int dirfd, - const char* dirpath, - const char* pathname, - struct stat* statbuf, - int flags); - -#ifdef HAVE_OPENAT - -typedef int openat_arg_t; - -static inline void Compat_openatArgClose(openat_arg_t dirfd) { - close(dirfd); -} - -static inline int Compat_openat(openat_arg_t dirfd, const char* pathname, int flags) { - return openat(dirfd, pathname, flags); -} - -#else /* HAVE_OPENAT */ - -typedef const char* openat_arg_t; - -static inline void Compat_openatArgClose(openat_arg_t dirpath) { - (void)dirpath; -} - -int Compat_openat(openat_arg_t dirpath, const char* pathname, int flags); - -#endif /* HAVE_OPENAT */ - -ssize_t Compat_readlinkat(int dirfd, - const char* dirpath, - const char* pathname, - char* buf, - size_t bufsize); - -#endif /* HEADER_Compat */ diff -Nru pcp-5.3.1/src/pcp/htop/CPUMeter.c pcp-5.3.2/src/pcp/htop/CPUMeter.c --- pcp-5.3.1/src/pcp/htop/CPUMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CPUMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,575 +0,0 @@ -/* -htop - CPUMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "CPUMeter.h" - -#include -#include -#include -#include - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "ProcessList.h" -#include "RichString.h" -#include "Settings.h" -#include "XUtils.h" - - -static const int CPUMeter_attributes[] = { - CPU_NICE, - CPU_NORMAL, - CPU_SYSTEM, - CPU_IRQ, - CPU_SOFTIRQ, - CPU_STEAL, - CPU_GUEST, - CPU_IOWAIT -}; - -typedef struct CPUMeterData_ { - unsigned int cpus; - Meter** meters; -} CPUMeterData; - -static void CPUMeter_init(Meter* this) { - unsigned int cpu = this->param; - if (cpu == 0) { - Meter_setCaption(this, "Avg"); - } else if (this->pl->cpuCount > 1) { - char caption[10]; - xSnprintf(caption, sizeof(caption), "%3u", Settings_cpuId(this->pl->settings, cpu - 1)); - Meter_setCaption(this, caption); - } -} - -static void CPUMeter_updateValues(Meter* this) { - unsigned int cpu = this->param; - if (cpu > this->pl->cpuCount) { - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "absent"); - for (uint8_t i = 0; i < this->curItems; i++) - this->values[i] = 0; - return; - } - memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT); - - char cpuUsageBuffer[8] = { 0 }; - char cpuFrequencyBuffer[16] = { 0 }; - char cpuTemperatureBuffer[16] = { 0 }; - - double percent = Platform_setCPUValues(this, cpu); - - if (this->pl->settings->showCPUUsage) { - xSnprintf(cpuUsageBuffer, sizeof(cpuUsageBuffer), "%.1f%%", percent); - } - - if (this->pl->settings->showCPUFrequency) { - double cpuFrequency = this->values[CPU_METER_FREQUENCY]; - if (isnan(cpuFrequency)) { - xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A"); - } else { - xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency); - } - } - - #ifdef BUILD_WITH_CPU_TEMP - if (this->pl->settings->showCPUTemperature) { - double cpuTemperature = this->values[CPU_METER_TEMPERATURE]; - if (isnan(cpuTemperature)) - xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A"); - else if (this->pl->settings->degreeFahrenheit) - xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%3d%sF", (int)(cpuTemperature * 9 / 5 + 32), CRT_degreeSign); - else - xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%d%sC", (int)cpuTemperature, CRT_degreeSign); - } - #endif - - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%s%s%s%s", - cpuUsageBuffer, - (cpuUsageBuffer[0] && (cpuFrequencyBuffer[0] || cpuTemperatureBuffer[0])) ? " " : "", - cpuFrequencyBuffer, - (cpuFrequencyBuffer[0] && cpuTemperatureBuffer[0]) ? " " : "", - cpuTemperatureBuffer); -} - -static void CPUMeter_display(const Object* cast, RichString* out) { - char buffer[50]; - const Meter* this = (const Meter*)cast; - if (this->param > this->pl->cpuCount) { - RichString_appendAscii(out, CRT_colors[METER_TEXT], "absent"); - return; - } - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NORMAL]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], ":"); - RichString_appendAscii(out, CRT_colors[CPU_NORMAL], buffer); - if (this->pl->settings->detailedCPUTime) { - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "sy:"); - RichString_appendAscii(out, CRT_colors[CPU_SYSTEM], buffer); - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "ni:"); - RichString_appendAscii(out, CRT_colors[CPU_NICE_TEXT], buffer); - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "hi:"); - RichString_appendAscii(out, CRT_colors[CPU_IRQ], buffer); - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_SOFTIRQ]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "si:"); - RichString_appendAscii(out, CRT_colors[CPU_SOFTIRQ], buffer); - if (!isnan(this->values[CPU_METER_STEAL])) { - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_STEAL]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "st:"); - RichString_appendAscii(out, CRT_colors[CPU_STEAL], buffer); - } - if (!isnan(this->values[CPU_METER_GUEST])) { - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_GUEST]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "gu:"); - RichString_appendAscii(out, CRT_colors[CPU_GUEST], buffer); - } - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IOWAIT]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "wa:"); - RichString_appendAscii(out, CRT_colors[CPU_IOWAIT], buffer); - } else { - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "sys:"); - RichString_appendAscii(out, CRT_colors[CPU_SYSTEM], buffer); - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "low:"); - RichString_appendAscii(out, CRT_colors[CPU_NICE_TEXT], buffer); - if (!isnan(this->values[CPU_METER_IRQ])) { - xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]); - RichString_appendAscii(out, CRT_colors[METER_TEXT], "vir:"); - RichString_appendAscii(out, CRT_colors[CPU_GUEST], buffer); - } - } - - #ifdef BUILD_WITH_CPU_TEMP - if (this->pl->settings->showCPUTemperature) { - char cpuTemperatureBuffer[10]; - double cpuTemperature = this->values[CPU_METER_TEMPERATURE]; - if (isnan(cpuTemperature)) { - xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A"); - } else if (this->pl->settings->degreeFahrenheit) { - xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sF", cpuTemperature * 9 / 5 + 32, CRT_degreeSign); - } else { - xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sC", cpuTemperature, CRT_degreeSign); - } - RichString_appendAscii(out, CRT_colors[METER_TEXT], "temp:"); - RichString_appendWide(out, CRT_colors[METER_VALUE], cpuTemperatureBuffer); - } - #endif -} - -static void AllCPUsMeter_getRange(const Meter* this, int* start, int* count) { - const CPUMeterData* data = this->meterData; - unsigned int cpus = data->cpus; - switch(Meter_name(this)[0]) { - default: - case 'A': // All - *start = 0; - *count = cpus; - break; - case 'L': // First Half - *start = 0; - *count = (cpus+1) / 2; - break; - case 'R': // Second Half - *start = (cpus+1) / 2; - *count = cpus / 2; - break; - } -} - -static void AllCPUsMeter_updateValues(Meter* this) { - CPUMeterData* data = this->meterData; - Meter** meters = data->meters; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - for (int i = 0; i < count; i++) - Meter_updateValues(meters[i]); -} - -static void CPUMeterCommonInit(Meter* this, int ncol) { - unsigned int cpus = this->pl->cpuCount; - CPUMeterData* data = this->meterData; - if (!data) { - data = this->meterData = xMalloc(sizeof(CPUMeterData)); - data->cpus = cpus; - data->meters = xCalloc(cpus, sizeof(Meter*)); - } - Meter** meters = data->meters; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - for (int i = 0; i < count; i++) { - if (!meters[i]) - meters[i] = Meter_new(this->pl, start + i + 1, (const MeterClass*) Class(CPUMeter)); - - Meter_init(meters[i]); - } - - if (this->mode == 0) - this->mode = BAR_METERMODE; - - int h = Meter_modes[this->mode]->h; - this->h = h * ((count + ncol - 1) / ncol); -} - -static void CPUMeterCommonUpdateMode(Meter* this, int mode, int ncol) { - CPUMeterData* data = this->meterData; - Meter** meters = data->meters; - this->mode = mode; - int h = Meter_modes[mode]->h; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - for (int i = 0; i < count; i++) { - Meter_setMode(meters[i], mode); - } - this->h = h * ((count + ncol - 1) / ncol); -} - -static void AllCPUsMeter_done(Meter* this) { - CPUMeterData* data = this->meterData; - Meter** meters = data->meters; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - for (int i = 0; i < count; i++) - Meter_delete((Object*)meters[i]); - free(data->meters); - free(data); -} - -static void SingleColCPUsMeter_init(Meter* this) { - CPUMeterCommonInit(this, 1); -} - -static void SingleColCPUsMeter_updateMode(Meter* this, int mode) { - CPUMeterCommonUpdateMode(this, mode, 1); -} - -static void DualColCPUsMeter_init(Meter* this) { - CPUMeterCommonInit(this, 2); -} - -static void DualColCPUsMeter_updateMode(Meter* this, int mode) { - CPUMeterCommonUpdateMode(this, mode, 2); -} - -static void QuadColCPUsMeter_init(Meter* this) { - CPUMeterCommonInit(this, 4); -} - -static void QuadColCPUsMeter_updateMode(Meter* this, int mode) { - CPUMeterCommonUpdateMode(this, mode, 4); -} - -static void OctoColCPUsMeter_init(Meter* this) { - CPUMeterCommonInit(this, 8); -} - -static void OctoColCPUsMeter_updateMode(Meter* this, int mode) { - CPUMeterCommonUpdateMode(this, mode, 8); -} - -static void CPUMeterCommonDraw(Meter* this, int x, int y, int w, int ncol) { - CPUMeterData* data = this->meterData; - Meter** meters = data->meters; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - int colwidth = (w - ncol) / ncol + 1; - int diff = (w - (colwidth * ncol)); - int nrows = (count + ncol - 1) / ncol; - for (int i = 0; i < count; i++) { - int d = (i / nrows) > diff ? diff : (i / nrows); // dynamic spacer - int xpos = x + ((i / nrows) * colwidth) + d; - int ypos = y + ((i % nrows) * meters[0]->h); - meters[i]->draw(meters[i], xpos, ypos, colwidth); - } -} - -static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) { - CPUMeterCommonDraw(this, x, y, w, 2); -} - -static void QuadColCPUsMeter_draw(Meter* this, int x, int y, int w) { - CPUMeterCommonDraw(this, x, y, w, 4); -} - -static void OctoColCPUsMeter_draw(Meter* this, int x, int y, int w) { - CPUMeterCommonDraw(this, x, y, w, 8); -} - - -static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) { - CPUMeterData* data = this->meterData; - Meter** meters = data->meters; - int start, count; - AllCPUsMeter_getRange(this, &start, &count); - for (int i = 0; i < count; i++) { - meters[i]->draw(meters[i], x, y, w); - y += meters[i]->h; - } -} - - -const MeterClass CPUMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = CPUMeter_updateValues, - .defaultMode = BAR_METERMODE, - .maxItems = CPU_METER_ITEMCOUNT, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "CPU", - .uiName = "CPU", - .caption = "CPU", - .init = CPUMeter_init -}; - -const MeterClass AllCPUsMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "AllCPUs", - .uiName = "CPUs (1/1)", - .description = "CPUs (1/1): all CPUs", - .caption = "CPU", - .draw = SingleColCPUsMeter_draw, - .init = SingleColCPUsMeter_init, - .updateMode = SingleColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass AllCPUs2Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "AllCPUs2", - .uiName = "CPUs (1&2/2)", - .description = "CPUs (1&2/2): all CPUs in 2 shorter columns", - .caption = "CPU", - .draw = DualColCPUsMeter_draw, - .init = DualColCPUsMeter_init, - .updateMode = DualColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass LeftCPUsMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "LeftCPUs", - .uiName = "CPUs (1/2)", - .description = "CPUs (1/2): first half of list", - .caption = "CPU", - .draw = SingleColCPUsMeter_draw, - .init = SingleColCPUsMeter_init, - .updateMode = SingleColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass RightCPUsMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "RightCPUs", - .uiName = "CPUs (2/2)", - .description = "CPUs (2/2): second half of list", - .caption = "CPU", - .draw = SingleColCPUsMeter_draw, - .init = SingleColCPUsMeter_init, - .updateMode = SingleColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass LeftCPUs2Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "LeftCPUs2", - .uiName = "CPUs (1&2/4)", - .description = "CPUs (1&2/4): first half in 2 shorter columns", - .caption = "CPU", - .draw = DualColCPUsMeter_draw, - .init = DualColCPUsMeter_init, - .updateMode = DualColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass RightCPUs2Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "RightCPUs2", - .uiName = "CPUs (3&4/4)", - .description = "CPUs (3&4/4): second half in 2 shorter columns", - .caption = "CPU", - .draw = DualColCPUsMeter_draw, - .init = DualColCPUsMeter_init, - .updateMode = DualColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass AllCPUs4Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "AllCPUs4", - .uiName = "CPUs (1&2&3&4/4)", - .description = "CPUs (1&2&3&4/4): all CPUs in 4 shorter columns", - .caption = "CPU", - .draw = QuadColCPUsMeter_draw, - .init = QuadColCPUsMeter_init, - .updateMode = QuadColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass LeftCPUs4Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "LeftCPUs4", - .uiName = "CPUs (1-4/8)", - .description = "CPUs (1-4/8): first half in 4 shorter columns", - .caption = "CPU", - .draw = QuadColCPUsMeter_draw, - .init = QuadColCPUsMeter_init, - .updateMode = QuadColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass RightCPUs4Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "RightCPUs4", - .uiName = "CPUs (5-8/8)", - .description = "CPUs (5-8/8): second half in 4 shorter columns", - .caption = "CPU", - .draw = QuadColCPUsMeter_draw, - .init = QuadColCPUsMeter_init, - .updateMode = QuadColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass AllCPUs8Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "AllCPUs8", - .uiName = "CPUs (1-8/8)", - .description = "CPUs (1-8/8): all CPUs in 8 shorter columns", - .caption = "CPU", - .draw = OctoColCPUsMeter_draw, - .init = OctoColCPUsMeter_init, - .updateMode = OctoColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass LeftCPUs8Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "LeftCPUs8", - .uiName = "CPUs (1-8/16)", - .description = "CPUs (1-8/16): first half in 8 shorter columns", - .caption = "CPU", - .draw = OctoColCPUsMeter_draw, - .init = OctoColCPUsMeter_init, - .updateMode = OctoColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; - -const MeterClass RightCPUs8Meter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = CPUMeter_display - }, - .updateValues = AllCPUsMeter_updateValues, - .defaultMode = CUSTOM_METERMODE, - .total = 100.0, - .attributes = CPUMeter_attributes, - .name = "RightCPUs8", - .uiName = "CPUs (9-16/16)", - .description = "CPUs (9-16/16): second half in 8 shorter columns", - .caption = "CPU", - .draw = OctoColCPUsMeter_draw, - .init = OctoColCPUsMeter_init, - .updateMode = OctoColCPUsMeter_updateMode, - .done = AllCPUsMeter_done -}; diff -Nru pcp-5.3.1/src/pcp/htop/CPUMeter.h pcp-5.3.2/src/pcp/htop/CPUMeter.h --- pcp-5.3.1/src/pcp/htop/CPUMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CPUMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -#ifndef HEADER_CPUMeter -#define HEADER_CPUMeter -/* -htop - CPUMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -typedef enum { - CPU_METER_NICE = 0, - CPU_METER_NORMAL = 1, - CPU_METER_KERNEL = 2, - CPU_METER_IRQ = 3, - CPU_METER_SOFTIRQ = 4, - CPU_METER_STEAL = 5, - CPU_METER_GUEST = 6, - CPU_METER_IOWAIT = 7, - CPU_METER_FREQUENCY = 8, - CPU_METER_TEMPERATURE = 9, - CPU_METER_ITEMCOUNT = 10, // number of entries in this enum -} CPUMeterValues; - -extern const MeterClass CPUMeter_class; - -extern const MeterClass AllCPUsMeter_class; - -extern const MeterClass AllCPUs2Meter_class; - -extern const MeterClass LeftCPUsMeter_class; - -extern const MeterClass RightCPUsMeter_class; - -extern const MeterClass LeftCPUs2Meter_class; - -extern const MeterClass RightCPUs2Meter_class; - -extern const MeterClass AllCPUs4Meter_class; - -extern const MeterClass LeftCPUs4Meter_class; - -extern const MeterClass RightCPUs4Meter_class; - -extern const MeterClass AllCPUs8Meter_class; - -extern const MeterClass LeftCPUs8Meter_class; - -extern const MeterClass RightCPUs8Meter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/CRT.c pcp-5.3.2/src/pcp/htop/CRT.c --- pcp-5.3.1/src/pcp/htop/CRT.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CRT.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1010 +0,0 @@ -/* -htop - CRT.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "CRT.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "ProvideCurses.h" -#include "XUtils.h" - -#ifdef HAVE_EXECINFO_H -#include -#endif - -#if !defined(NDEBUG) && defined(HAVE_MEMFD_CREATE) -#include -#endif - - -#define ColorIndex(i,j) ((7-(i))*8+(j)) - -#define ColorPair(i,j) COLOR_PAIR(ColorIndex(i,j)) - -#define Black COLOR_BLACK -#define Red COLOR_RED -#define Green COLOR_GREEN -#define Yellow COLOR_YELLOW -#define Blue COLOR_BLUE -#define Magenta COLOR_MAGENTA -#define Cyan COLOR_CYAN -#define White COLOR_WHITE - -#define ColorPairGrayBlack ColorPair(Magenta,Magenta) -#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta) - -#define ColorPairWhiteDefault ColorPair(Red, Red) -#define ColorIndexWhiteDefault ColorIndex(Red, Red) - -static const char* const CRT_treeStrAscii[LAST_TREE_STR] = { - [TREE_STR_VERT] = "|", - [TREE_STR_RTEE] = "`", - [TREE_STR_BEND] = "`", - [TREE_STR_TEND] = ",", - [TREE_STR_OPEN] = "+", - [TREE_STR_SHUT] = "-", - [TREE_STR_ASC] = "+", - [TREE_STR_DESC] = "-", -}; - -#ifdef HAVE_LIBNCURSESW - -static const char* const CRT_treeStrUtf8[LAST_TREE_STR] = { - [TREE_STR_VERT] = "\xe2\x94\x82", // │ - [TREE_STR_RTEE] = "\xe2\x94\x9c", // ├ - [TREE_STR_BEND] = "\xe2\x94\x94", // └ - [TREE_STR_TEND] = "\xe2\x94\x8c", // ┌ - [TREE_STR_OPEN] = "+", // +, TODO use 🮯 'BOX DRAWINGS LIGHT HORIZONTAL - // WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when - // Unicode 13 is common - [TREE_STR_SHUT] = "\xe2\x94\x80", // ─ - [TREE_STR_ASC] = "\xe2\x96\xb3", // △ - [TREE_STR_DESC] = "\xe2\x96\xbd", // ▽ -}; - -bool CRT_utf8 = false; - -#endif - -const char* const* CRT_treeStr = CRT_treeStrAscii; - -static const int* CRT_delay; - -const char* CRT_degreeSign; - -static const char* initDegreeSign(void) { -#ifdef HAVE_LIBNCURSESW - if (CRT_utf8) - return "\xc2\xb0"; - - static char buffer[4]; - // this might fail if the current locale does not support wide characters - int r = snprintf(buffer, sizeof(buffer), "%lc", 176); - if (r > 0) - return buffer; -#endif - - return ""; -} - -const int* CRT_colors; - -static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { - [COLORSCHEME_DEFAULT] = { - [RESET_COLOR] = ColorPair(White, Black), - [DEFAULT_COLOR] = ColorPair(White, Black), - [FUNCTION_BAR] = ColorPair(Black, Cyan), - [FUNCTION_KEY] = ColorPair(White, Black), - [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), - [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), - [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), - [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), - [PANEL_SELECTION_UNFOCUS] = ColorPair(Black, White), - [FAILED_SEARCH] = ColorPair(Red, Cyan), - [FAILED_READ] = A_BOLD | ColorPair(Red, Black), - [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), - [UPTIME] = A_BOLD | ColorPair(Cyan, Black), - [BATTERY] = A_BOLD | ColorPair(Cyan, Black), - [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), - [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, - [METER_TEXT] = ColorPair(Cyan, Black), - [METER_VALUE] = A_BOLD | ColorPair(Cyan, Black), - [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black), - [METER_VALUE_IOREAD] = ColorPair(Green, Black), - [METER_VALUE_IOWRITE] = ColorPair(Blue, Black), - [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black), - [METER_VALUE_OK] = ColorPair(Green, Black), - [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), - [LED_COLOR] = ColorPair(Green, Black), - [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black), - [PROCESS] = A_NORMAL, - [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack, - [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Black), - [PROCESS_MEGABYTES] = ColorPair(Cyan, Black), - [PROCESS_GIGABYTES] = ColorPair(Green, Black), - [PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Black), - [PROCESS_TREE] = ColorPair(Cyan, Black), - [PROCESS_R_STATE] = ColorPair(Green, Black), - [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), - [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), - [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), - [PROCESS_NEW] = ColorPair(Black, Green), - [PROCESS_TOMB] = ColorPair(Black, Red), - [PROCESS_THREAD] = ColorPair(Green, Black), - [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Black), - [PROCESS_COMM] = ColorPair(Magenta, Black), - [PROCESS_THREAD_COMM] = ColorPair(Blue, Black), - [BAR_BORDER] = A_BOLD, - [BAR_SHADOW] = A_BOLD | ColorPairGrayBlack, - [SWAP] = ColorPair(Red, Black), - [SWAP_CACHE] = ColorPair(Yellow, Black), - [GRAPH_1] = A_BOLD | ColorPair(Cyan, Black), - [GRAPH_2] = ColorPair(Cyan, Black), - [MEMORY_USED] = ColorPair(Green, Black), - [MEMORY_BUFFERS] = ColorPair(Blue, Black), - [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black), - [MEMORY_CACHE] = ColorPair(Yellow, Black), - [MEMORY_SHARED] = ColorPair(Magenta, Black), - [HUGEPAGE_1] = ColorPair(Green, Black), - [HUGEPAGE_2] = ColorPair(Yellow, Black), - [HUGEPAGE_3] = ColorPair(Red, Black), - [HUGEPAGE_4] = ColorPair(Blue, Black), - [LOAD_AVERAGE_FIFTEEN] = ColorPair(Cyan, Black), - [LOAD_AVERAGE_FIVE] = A_BOLD | ColorPair(Cyan, Black), - [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Black), - [LOAD] = A_BOLD, - [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Black), - [CLOCK] = A_BOLD, - [DATE] = A_BOLD, - [DATETIME] = A_BOLD, - [CHECK_BOX] = ColorPair(Cyan, Black), - [CHECK_MARK] = A_BOLD, - [CHECK_TEXT] = A_NORMAL, - [HOSTNAME] = A_BOLD, - [CPU_NICE] = ColorPair(Blue, Black), - [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black), - [CPU_NORMAL] = ColorPair(Green, Black), - [CPU_SYSTEM] = ColorPair(Red, Black), - [CPU_IOWAIT] = A_BOLD | ColorPairGrayBlack, - [CPU_IRQ] = ColorPair(Yellow, Black), - [CPU_SOFTIRQ] = ColorPair(Magenta, Black), - [CPU_STEAL] = ColorPair(Cyan, Black), - [CPU_GUEST] = ColorPair(Cyan, Black), - [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Cyan, Black), - [PRESSURE_STALL_SIXTY] = A_BOLD | ColorPair(Cyan, Black), - [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Black), - [ZFS_MFU] = ColorPair(Blue, Black), - [ZFS_MRU] = ColorPair(Yellow, Black), - [ZFS_ANON] = ColorPair(Magenta, Black), - [ZFS_HEADER] = ColorPair(Cyan, Black), - [ZFS_OTHER] = ColorPair(Magenta, Black), - [ZFS_COMPRESSED] = ColorPair(Blue, Black), - [ZFS_RATIO] = ColorPair(Magenta, Black), - [ZRAM] = ColorPair(Yellow, Black), - }, - [COLORSCHEME_MONOCHROME] = { - [RESET_COLOR] = A_NORMAL, - [DEFAULT_COLOR] = A_NORMAL, - [FUNCTION_BAR] = A_REVERSE, - [FUNCTION_KEY] = A_NORMAL, - [PANEL_HEADER_FOCUS] = A_REVERSE, - [PANEL_HEADER_UNFOCUS] = A_REVERSE, - [PANEL_SELECTION_FOCUS] = A_REVERSE, - [PANEL_SELECTION_FOLLOW] = A_REVERSE, - [PANEL_SELECTION_UNFOCUS] = A_BOLD, - [FAILED_SEARCH] = A_REVERSE | A_BOLD, - [FAILED_READ] = A_BOLD, - [PAUSED] = A_BOLD | A_REVERSE, - [UPTIME] = A_BOLD, - [BATTERY] = A_BOLD, - [LARGE_NUMBER] = A_BOLD, - [METER_SHADOW] = A_DIM, - [METER_TEXT] = A_NORMAL, - [METER_VALUE] = A_BOLD, - [METER_VALUE_ERROR] = A_BOLD, - [METER_VALUE_IOREAD] = A_NORMAL, - [METER_VALUE_IOWRITE] = A_NORMAL, - [METER_VALUE_NOTICE] = A_BOLD, - [METER_VALUE_OK] = A_NORMAL, - [METER_VALUE_WARN] = A_BOLD, - [LED_COLOR] = A_NORMAL, - [TASKS_RUNNING] = A_BOLD, - [PROCESS] = A_NORMAL, - [PROCESS_SHADOW] = A_DIM, - [PROCESS_TAG] = A_BOLD, - [PROCESS_MEGABYTES] = A_BOLD, - [PROCESS_GIGABYTES] = A_BOLD, - [PROCESS_BASENAME] = A_BOLD, - [PROCESS_TREE] = A_BOLD, - [PROCESS_R_STATE] = A_BOLD, - [PROCESS_D_STATE] = A_BOLD, - [PROCESS_HIGH_PRIORITY] = A_BOLD, - [PROCESS_LOW_PRIORITY] = A_DIM, - [PROCESS_NEW] = A_BOLD, - [PROCESS_TOMB] = A_DIM, - [PROCESS_THREAD] = A_BOLD, - [PROCESS_THREAD_BASENAME] = A_REVERSE, - [PROCESS_COMM] = A_BOLD, - [PROCESS_THREAD_COMM] = A_REVERSE, - [BAR_BORDER] = A_BOLD, - [BAR_SHADOW] = A_DIM, - [SWAP] = A_BOLD, - [SWAP_CACHE] = A_NORMAL, - [GRAPH_1] = A_BOLD, - [GRAPH_2] = A_NORMAL, - [MEMORY_USED] = A_BOLD, - [MEMORY_BUFFERS] = A_NORMAL, - [MEMORY_BUFFERS_TEXT] = A_NORMAL, - [MEMORY_CACHE] = A_NORMAL, - [MEMORY_SHARED] = A_NORMAL, - [HUGEPAGE_1] = A_BOLD, - [HUGEPAGE_2] = A_NORMAL, - [HUGEPAGE_3] = A_REVERSE | A_BOLD, - [HUGEPAGE_4] = A_REVERSE, - [LOAD_AVERAGE_FIFTEEN] = A_DIM, - [LOAD_AVERAGE_FIVE] = A_NORMAL, - [LOAD_AVERAGE_ONE] = A_BOLD, - [LOAD] = A_BOLD, - [HELP_BOLD] = A_BOLD, - [CLOCK] = A_BOLD, - [DATE] = A_BOLD, - [DATETIME] = A_BOLD, - [CHECK_BOX] = A_BOLD, - [CHECK_MARK] = A_NORMAL, - [CHECK_TEXT] = A_NORMAL, - [HOSTNAME] = A_BOLD, - [CPU_NICE] = A_NORMAL, - [CPU_NICE_TEXT] = A_NORMAL, - [CPU_NORMAL] = A_BOLD, - [CPU_SYSTEM] = A_BOLD, - [CPU_IOWAIT] = A_NORMAL, - [CPU_IRQ] = A_BOLD, - [CPU_SOFTIRQ] = A_BOLD, - [CPU_STEAL] = A_DIM, - [CPU_GUEST] = A_DIM, - [PRESSURE_STALL_THREEHUNDRED] = A_DIM, - [PRESSURE_STALL_SIXTY] = A_NORMAL, - [PRESSURE_STALL_TEN] = A_BOLD, - [ZFS_MFU] = A_NORMAL, - [ZFS_MRU] = A_NORMAL, - [ZFS_ANON] = A_DIM, - [ZFS_HEADER] = A_BOLD, - [ZFS_OTHER] = A_DIM, - [ZFS_COMPRESSED] = A_BOLD, - [ZFS_RATIO] = A_BOLD, - [ZRAM] = A_NORMAL, - }, - [COLORSCHEME_BLACKONWHITE] = { - [RESET_COLOR] = ColorPair(Black, White), - [DEFAULT_COLOR] = ColorPair(Black, White), - [FUNCTION_BAR] = ColorPair(Black, Cyan), - [FUNCTION_KEY] = ColorPair(Black, White), - [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), - [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), - [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), - [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), - [PANEL_SELECTION_UNFOCUS] = ColorPair(Blue, White), - [FAILED_SEARCH] = ColorPair(Red, Cyan), - [FAILED_READ] = ColorPair(Red, White), - [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), - [UPTIME] = ColorPair(Yellow, White), - [BATTERY] = ColorPair(Yellow, White), - [LARGE_NUMBER] = ColorPair(Red, White), - [METER_SHADOW] = ColorPair(Blue, White), - [METER_TEXT] = ColorPair(Blue, White), - [METER_VALUE] = ColorPair(Black, White), - [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, White), - [METER_VALUE_IOREAD] = ColorPair(Green, White), - [METER_VALUE_IOWRITE] = ColorPair(Yellow, White), - [METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, White), - [METER_VALUE_OK] = ColorPair(Green, White), - [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, White), - [LED_COLOR] = ColorPair(Green, White), - [TASKS_RUNNING] = ColorPair(Green, White), - [PROCESS] = ColorPair(Black, White), - [PROCESS_SHADOW] = A_BOLD | ColorPair(Black, White), - [PROCESS_TAG] = ColorPair(White, Blue), - [PROCESS_MEGABYTES] = ColorPair(Blue, White), - [PROCESS_GIGABYTES] = ColorPair(Green, White), - [PROCESS_BASENAME] = ColorPair(Blue, White), - [PROCESS_TREE] = ColorPair(Green, White), - [PROCESS_R_STATE] = ColorPair(Green, White), - [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White), - [PROCESS_HIGH_PRIORITY] = ColorPair(Red, White), - [PROCESS_LOW_PRIORITY] = ColorPair(Green, White), - [PROCESS_NEW] = ColorPair(White, Green), - [PROCESS_TOMB] = ColorPair(White, Red), - [PROCESS_THREAD] = ColorPair(Blue, White), - [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, White), - [PROCESS_COMM] = ColorPair(Magenta, White), - [PROCESS_THREAD_COMM] = ColorPair(Green, White), - [BAR_BORDER] = ColorPair(Blue, White), - [BAR_SHADOW] = ColorPair(Black, White), - [SWAP] = ColorPair(Red, White), - [SWAP_CACHE] = ColorPair(Yellow, White), - [GRAPH_1] = A_BOLD | ColorPair(Blue, White), - [GRAPH_2] = ColorPair(Blue, White), - [MEMORY_USED] = ColorPair(Green, White), - [MEMORY_BUFFERS] = ColorPair(Cyan, White), - [MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, White), - [MEMORY_CACHE] = ColorPair(Yellow, White), - [MEMORY_SHARED] = ColorPair(Magenta, White), - [HUGEPAGE_1] = ColorPair(Green, White), - [HUGEPAGE_2] = ColorPair(Yellow, White), - [HUGEPAGE_3] = ColorPair(Red, White), - [HUGEPAGE_4] = ColorPair(Blue, White), - [LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, White), - [LOAD_AVERAGE_FIVE] = ColorPair(Black, White), - [LOAD_AVERAGE_ONE] = ColorPair(Black, White), - [LOAD] = ColorPair(Black, White), - [HELP_BOLD] = ColorPair(Blue, White), - [CLOCK] = ColorPair(Black, White), - [DATE] = ColorPair(Black, White), - [DATETIME] = ColorPair(Black, White), - [CHECK_BOX] = ColorPair(Blue, White), - [CHECK_MARK] = ColorPair(Black, White), - [CHECK_TEXT] = ColorPair(Black, White), - [HOSTNAME] = ColorPair(Black, White), - [CPU_NICE] = ColorPair(Cyan, White), - [CPU_NICE_TEXT] = ColorPair(Cyan, White), - [CPU_NORMAL] = ColorPair(Green, White), - [CPU_SYSTEM] = ColorPair(Red, White), - [CPU_IOWAIT] = A_BOLD | ColorPair(Black, White), - [CPU_IRQ] = ColorPair(Blue, White), - [CPU_SOFTIRQ] = ColorPair(Blue, White), - [CPU_STEAL] = ColorPair(Cyan, White), - [CPU_GUEST] = ColorPair(Cyan, White), - [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, White), - [PRESSURE_STALL_SIXTY] = ColorPair(Black, White), - [PRESSURE_STALL_TEN] = ColorPair(Black, White), - [ZFS_MFU] = ColorPair(Cyan, White), - [ZFS_MRU] = ColorPair(Yellow, White), - [ZFS_ANON] = ColorPair(Magenta, White), - [ZFS_HEADER] = ColorPair(Yellow, White), - [ZFS_OTHER] = ColorPair(Magenta, White), - [ZFS_COMPRESSED] = ColorPair(Cyan, White), - [ZFS_RATIO] = ColorPair(Magenta, White), - [ZRAM] = ColorPair(Yellow, White) - }, - [COLORSCHEME_LIGHTTERMINAL] = { - [RESET_COLOR] = ColorPair(Black, Black), - [DEFAULT_COLOR] = ColorPair(Black, Black), - [FUNCTION_BAR] = ColorPair(Black, Cyan), - [FUNCTION_KEY] = ColorPair(Black, Black), - [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), - [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), - [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), - [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), - [PANEL_SELECTION_UNFOCUS] = ColorPair(Blue, Black), - [FAILED_SEARCH] = ColorPair(Red, Cyan), - [FAILED_READ] = ColorPair(Red, Black), - [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), - [UPTIME] = ColorPair(Yellow, Black), - [BATTERY] = ColorPair(Yellow, Black), - [LARGE_NUMBER] = ColorPair(Red, Black), - [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, - [METER_TEXT] = ColorPair(Blue, Black), - [METER_VALUE] = ColorPair(Black, Black), - [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black), - [METER_VALUE_IOREAD] = ColorPair(Green, Black), - [METER_VALUE_IOWRITE] = ColorPair(Yellow, Black), - [METER_VALUE_NOTICE] = A_BOLD | ColorPairWhiteDefault, - [METER_VALUE_OK] = ColorPair(Green, Black), - [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), - [LED_COLOR] = ColorPair(Green, Black), - [TASKS_RUNNING] = ColorPair(Green, Black), - [PROCESS] = ColorPair(Black, Black), - [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack, - [PROCESS_TAG] = ColorPair(White, Blue), - [PROCESS_MEGABYTES] = ColorPair(Blue, Black), - [PROCESS_GIGABYTES] = ColorPair(Green, Black), - [PROCESS_BASENAME] = ColorPair(Green, Black), - [PROCESS_TREE] = ColorPair(Blue, Black), - [PROCESS_R_STATE] = ColorPair(Green, Black), - [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), - [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), - [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), - [PROCESS_NEW] = ColorPair(Black, Green), - [PROCESS_TOMB] = ColorPair(Black, Red), - [PROCESS_THREAD] = ColorPair(Blue, Black), - [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black), - [PROCESS_COMM] = ColorPair(Magenta, Black), - [PROCESS_THREAD_COMM] = ColorPair(Yellow, Black), - [BAR_BORDER] = ColorPair(Blue, Black), - [BAR_SHADOW] = ColorPairGrayBlack, - [SWAP] = ColorPair(Red, Black), - [SWAP_CACHE] = ColorPair(Yellow, Black), - [GRAPH_1] = A_BOLD | ColorPair(Cyan, Black), - [GRAPH_2] = ColorPair(Cyan, Black), - [MEMORY_USED] = ColorPair(Green, Black), - [MEMORY_BUFFERS] = ColorPair(Cyan, Black), - [MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, Black), - [MEMORY_CACHE] = ColorPair(Yellow, Black), - [MEMORY_SHARED] = ColorPair(Magenta, Black), - [HUGEPAGE_1] = ColorPair(Green, Black), - [HUGEPAGE_2] = ColorPair(Yellow, Black), - [HUGEPAGE_3] = ColorPair(Red, Black), - [HUGEPAGE_4] = ColorPair(Blue, Black), - [LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, Black), - [LOAD_AVERAGE_FIVE] = ColorPair(Black, Black), - [LOAD_AVERAGE_ONE] = ColorPair(Black, Black), - [LOAD] = ColorPairWhiteDefault, - [HELP_BOLD] = ColorPair(Blue, Black), - [CLOCK] = ColorPairWhiteDefault, - [DATE] = ColorPairWhiteDefault, - [DATETIME] = ColorPairWhiteDefault, - [CHECK_BOX] = ColorPair(Blue, Black), - [CHECK_MARK] = ColorPair(Black, Black), - [CHECK_TEXT] = ColorPair(Black, Black), - [HOSTNAME] = ColorPairWhiteDefault, - [CPU_NICE] = ColorPair(Cyan, Black), - [CPU_NICE_TEXT] = ColorPair(Cyan, Black), - [CPU_NORMAL] = ColorPair(Green, Black), - [CPU_SYSTEM] = ColorPair(Red, Black), - [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black), - [CPU_IRQ] = A_BOLD | ColorPair(Blue, Black), - [CPU_SOFTIRQ] = ColorPair(Blue, Black), - [CPU_STEAL] = ColorPair(Black, Black), - [CPU_GUEST] = ColorPair(Black, Black), - [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black), - [PRESSURE_STALL_SIXTY] = ColorPair(Black, Black), - [PRESSURE_STALL_TEN] = ColorPair(Black, Black), - [ZFS_MFU] = ColorPair(Cyan, Black), - [ZFS_MRU] = ColorPair(Yellow, Black), - [ZFS_ANON] = A_BOLD | ColorPair(Magenta, Black), - [ZFS_HEADER] = ColorPair(Black, Black), - [ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Black), - [ZFS_COMPRESSED] = ColorPair(Cyan, Black), - [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black), - [ZRAM] = ColorPair(Yellow, Black), - }, - [COLORSCHEME_MIDNIGHT] = { - [RESET_COLOR] = ColorPair(White, Blue), - [DEFAULT_COLOR] = ColorPair(White, Blue), - [FUNCTION_BAR] = ColorPair(Black, Cyan), - [FUNCTION_KEY] = A_NORMAL, - [PANEL_HEADER_FOCUS] = ColorPair(Black, Cyan), - [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Cyan), - [PANEL_SELECTION_FOCUS] = ColorPair(Black, White), - [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), - [PANEL_SELECTION_UNFOCUS] = A_BOLD | ColorPair(Yellow, Blue), - [FAILED_SEARCH] = ColorPair(Red, Cyan), - [FAILED_READ] = A_BOLD | ColorPair(Red, Blue), - [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), - [UPTIME] = A_BOLD | ColorPair(Yellow, Blue), - [BATTERY] = A_BOLD | ColorPair(Yellow, Blue), - [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Blue), - [METER_SHADOW] = ColorPair(Cyan, Blue), - [METER_TEXT] = ColorPair(Cyan, Blue), - [METER_VALUE] = A_BOLD | ColorPair(Cyan, Blue), - [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Blue), - [METER_VALUE_IOREAD] = ColorPair(Green, Blue), - [METER_VALUE_IOWRITE] = ColorPair(Black, Blue), - [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Blue), - [METER_VALUE_OK] = ColorPair(Green, Blue), - [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), - [LED_COLOR] = ColorPair(Green, Blue), - [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Blue), - [PROCESS] = ColorPair(White, Blue), - [PROCESS_SHADOW] = A_BOLD | ColorPair(Black, Blue), - [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Blue), - [PROCESS_MEGABYTES] = ColorPair(Cyan, Blue), - [PROCESS_GIGABYTES] = ColorPair(Green, Blue), - [PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Blue), - [PROCESS_TREE] = ColorPair(Cyan, Blue), - [PROCESS_R_STATE] = ColorPair(Green, Blue), - [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue), - [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue), - [PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue), - [PROCESS_NEW] = ColorPair(Blue, Green), - [PROCESS_TOMB] = ColorPair(Blue, Red), - [PROCESS_THREAD] = ColorPair(Green, Blue), - [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Blue), - [PROCESS_COMM] = ColorPair(Magenta, Blue), - [PROCESS_THREAD_COMM] = ColorPair(Black, Blue), - [BAR_BORDER] = A_BOLD | ColorPair(Yellow, Blue), - [BAR_SHADOW] = ColorPair(Cyan, Blue), - [SWAP] = ColorPair(Red, Blue), - [SWAP_CACHE] = A_BOLD | ColorPair(Yellow, Blue), - [GRAPH_1] = A_BOLD | ColorPair(Cyan, Blue), - [GRAPH_2] = ColorPair(Cyan, Blue), - [MEMORY_USED] = A_BOLD | ColorPair(Green, Blue), - [MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan, Blue), - [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Cyan, Blue), - [MEMORY_CACHE] = A_BOLD | ColorPair(Yellow, Blue), - [MEMORY_SHARED] = A_BOLD | ColorPair(Magenta, Blue), - [HUGEPAGE_1] = A_BOLD | ColorPair(Green, Blue), - [HUGEPAGE_2] = A_BOLD | ColorPair(Yellow, Blue), - [HUGEPAGE_3] = A_BOLD | ColorPair(Red, Blue), - [HUGEPAGE_4] = A_BOLD | ColorPair(White, Blue), - [LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black, Blue), - [LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White, Blue), - [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Blue), - [LOAD] = A_BOLD | ColorPair(White, Blue), - [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Blue), - [CLOCK] = ColorPair(White, Blue), - [DATE] = ColorPair(White, Blue), - [DATETIME] = ColorPair(White, Blue), - [CHECK_BOX] = ColorPair(Cyan, Blue), - [CHECK_MARK] = A_BOLD | ColorPair(White, Blue), - [CHECK_TEXT] = A_NORMAL | ColorPair(White, Blue), - [HOSTNAME] = ColorPair(White, Blue), - [CPU_NICE] = A_BOLD | ColorPair(Cyan, Blue), - [CPU_NICE_TEXT] = A_BOLD | ColorPair(Cyan, Blue), - [CPU_NORMAL] = A_BOLD | ColorPair(Green, Blue), - [CPU_SYSTEM] = A_BOLD | ColorPair(Red, Blue), - [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Blue), - [CPU_IRQ] = A_BOLD | ColorPair(Black, Blue), - [CPU_SOFTIRQ] = ColorPair(Black, Blue), - [CPU_STEAL] = ColorPair(White, Blue), - [CPU_GUEST] = ColorPair(White, Blue), - [PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black, Blue), - [PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White, Blue), - [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Blue), - [ZFS_MFU] = A_BOLD | ColorPair(White, Blue), - [ZFS_MRU] = A_BOLD | ColorPair(Yellow, Blue), - [ZFS_ANON] = A_BOLD | ColorPair(Magenta, Blue), - [ZFS_HEADER] = A_BOLD | ColorPair(Yellow, Blue), - [ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Blue), - [ZFS_COMPRESSED] = A_BOLD | ColorPair(White, Blue), - [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Blue), - [ZRAM] = A_BOLD | ColorPair(Yellow, Blue), - }, - [COLORSCHEME_BLACKNIGHT] = { - [RESET_COLOR] = ColorPair(Cyan, Black), - [DEFAULT_COLOR] = ColorPair(Cyan, Black), - [FUNCTION_BAR] = ColorPair(Black, Green), - [FUNCTION_KEY] = ColorPair(Cyan, Black), - [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), - [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), - [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), - [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), - [PANEL_SELECTION_UNFOCUS] = ColorPair(Black, White), - [FAILED_SEARCH] = ColorPair(Red, Green), - [FAILED_READ] = A_BOLD | ColorPair(Red, Black), - [PAUSED] = A_BOLD | ColorPair(Yellow, Green), - [UPTIME] = ColorPair(Green, Black), - [BATTERY] = ColorPair(Green, Black), - [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), - [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, - [METER_TEXT] = ColorPair(Cyan, Black), - [METER_VALUE] = ColorPair(Green, Black), - [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black), - [METER_VALUE_IOREAD] = ColorPair(Green, Black), - [METER_VALUE_IOWRITE] = ColorPair(Blue, Black), - [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black), - [METER_VALUE_OK] = ColorPair(Green, Black), - [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), - [LED_COLOR] = ColorPair(Green, Black), - [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black), - [PROCESS] = ColorPair(Cyan, Black), - [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack, - [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Black), - [PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green, Black), - [PROCESS_GIGABYTES] = A_BOLD | ColorPair(Yellow, Black), - [PROCESS_BASENAME] = A_BOLD | ColorPair(Green, Black), - [PROCESS_TREE] = ColorPair(Cyan, Black), - [PROCESS_THREAD] = ColorPair(Green, Black), - [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black), - [PROCESS_COMM] = ColorPair(Magenta, Black), - [PROCESS_THREAD_COMM] = ColorPair(Yellow, Black), - [PROCESS_R_STATE] = ColorPair(Green, Black), - [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), - [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), - [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), - [PROCESS_NEW] = ColorPair(Black, Green), - [PROCESS_TOMB] = ColorPair(Black, Red), - [BAR_BORDER] = A_BOLD | ColorPair(Green, Black), - [BAR_SHADOW] = ColorPair(Cyan, Black), - [SWAP] = ColorPair(Red, Black), - [SWAP_CACHE] = ColorPair(Yellow, Black), - [GRAPH_1] = A_BOLD | ColorPair(Green, Black), - [GRAPH_2] = ColorPair(Green, Black), - [MEMORY_USED] = ColorPair(Green, Black), - [MEMORY_BUFFERS] = ColorPair(Blue, Black), - [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black), - [MEMORY_CACHE] = ColorPair(Yellow, Black), - [MEMORY_SHARED] = ColorPair(Magenta, Black), - [HUGEPAGE_1] = ColorPair(Green, Black), - [HUGEPAGE_2] = ColorPair(Yellow, Black), - [HUGEPAGE_3] = ColorPair(Red, Black), - [HUGEPAGE_4] = ColorPair(Blue, Black), - [LOAD_AVERAGE_FIFTEEN] = ColorPair(Green, Black), - [LOAD_AVERAGE_FIVE] = ColorPair(Green, Black), - [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(Green, Black), - [LOAD] = A_BOLD, - [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Black), - [CLOCK] = ColorPair(Green, Black), - [CHECK_BOX] = ColorPair(Green, Black), - [CHECK_MARK] = A_BOLD | ColorPair(Green, Black), - [CHECK_TEXT] = ColorPair(Cyan, Black), - [HOSTNAME] = ColorPair(Green, Black), - [CPU_NICE] = ColorPair(Blue, Black), - [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black), - [CPU_NORMAL] = ColorPair(Green, Black), - [CPU_SYSTEM] = ColorPair(Red, Black), - [CPU_IOWAIT] = ColorPair(Yellow, Black), - [CPU_IRQ] = A_BOLD | ColorPair(Blue, Black), - [CPU_SOFTIRQ] = ColorPair(Blue, Black), - [CPU_STEAL] = ColorPair(Cyan, Black), - [CPU_GUEST] = ColorPair(Cyan, Black), - [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green, Black), - [PRESSURE_STALL_SIXTY] = ColorPair(Green, Black), - [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green, Black), - [ZFS_MFU] = ColorPair(Blue, Black), - [ZFS_MRU] = ColorPair(Yellow, Black), - [ZFS_ANON] = ColorPair(Magenta, Black), - [ZFS_HEADER] = ColorPair(Yellow, Black), - [ZFS_OTHER] = ColorPair(Magenta, Black), - [ZFS_COMPRESSED] = ColorPair(Blue, Black), - [ZFS_RATIO] = ColorPair(Magenta, Black), - [ZRAM] = ColorPair(Yellow, Black), - }, - [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. -}; - -int CRT_cursorX = 0; - -int CRT_scrollHAmount = 5; - -int CRT_scrollWheelVAmount = 10; - -ColorScheme CRT_colorScheme = COLORSCHEME_DEFAULT; - -ATTR_NORETURN -static void CRT_handleSIGTERM(ATTR_UNUSED int sgn) { - CRT_done(); - _exit(0); -} - -#ifndef NDEBUG - -static int stderrRedirectNewFd = -1; -static int stderrRedirectBackupFd = -1; - -static int createStderrCacheFile(void) { -#if defined(HAVE_MEMFD_CREATE) - return memfd_create("htop.stderr-redirect", 0); -#elif defined(O_TMPFILE) - return open("/tmp", O_TMPFILE | O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); -#else - char tmpName[] = "htop.stderr-redirectXXXXXX"; - mode_t curUmask = umask(S_IXUSR | S_IRWXG | S_IRWXO); - int r = mkstemp(tmpName); - umask(curUmask); - if (r < 0) - return r; - - (void) unlink(tmpName); - - return r; -#endif /* HAVE_MEMFD_CREATE */ -} - -static void redirectStderr(void) { - stderrRedirectNewFd = createStderrCacheFile(); - if (stderrRedirectNewFd < 0) { - /* ignore failure */ - return; - } - - stderrRedirectBackupFd = dup(STDERR_FILENO); - dup2(stderrRedirectNewFd, STDERR_FILENO); -} - -static void dumpStderr(void) { - if (stderrRedirectNewFd < 0) - return; - - fsync(STDERR_FILENO); - dup2(stderrRedirectBackupFd, STDERR_FILENO); - lseek(stderrRedirectNewFd, 0, SEEK_SET); - - bool header = false; - char buffer[8192]; - for (;;) { - errno = 0; - ssize_t res = read(stderrRedirectNewFd, buffer, sizeof(buffer)); - if (res < 0) { - if (errno == EINTR) - continue; - - break; - } - - if (res == 0) { - break; - } - - if (res > 0) { - if (!header) { - fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n\n"); - header = true; - } - (void)! write(STDERR_FILENO, buffer, res); - } - } - - if (header) - fprintf(stderr, "\n<<<<<<<<<< stderr output <<<<<<<<<<\n"); - - close(stderrRedirectNewFd); - stderrRedirectNewFd = -1; -} - -#else /* !NDEBUG */ - -static void redirectStderr(void) { -} - -static void dumpStderr(void) { -} - -#endif /* !NDEBUG */ - -static struct sigaction old_sig_handler[32]; - -void CRT_init(const Settings* settings, bool allowUnicode) { - redirectStderr(); - - initscr(); - noecho(); - CRT_delay = &(settings->delay); - CRT_colors = CRT_colorSchemes[settings->colorScheme]; - CRT_colorScheme = settings->colorScheme; - - for (int i = 0; i < LAST_COLORELEMENT; i++) { - unsigned int color = CRT_colorSchemes[COLORSCHEME_DEFAULT][i]; - CRT_colorSchemes[COLORSCHEME_BROKENGRAY][i] = color == (A_BOLD | ColorPairGrayBlack) ? ColorPair(White, Black) : color; - } - - halfdelay(*CRT_delay); - nonl(); - intrflush(stdscr, false); - keypad(stdscr, true); - mouseinterval(0); - curs_set(0); - - if (has_colors()) { - start_color(); - } - - const char* termType = getenv("TERM"); - if (termType && String_eq(termType, "linux")) { - CRT_scrollHAmount = 20; - } else { - CRT_scrollHAmount = 5; - } - - if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220"))) { - define_key("\033[H", KEY_HOME); - define_key("\033[F", KEY_END); - define_key("\033[7~", KEY_HOME); - define_key("\033[8~", KEY_END); - define_key("\033OP", KEY_F(1)); - define_key("\033OQ", KEY_F(2)); - define_key("\033OR", KEY_F(3)); - define_key("\033OS", KEY_F(4)); - define_key("\033O2R", KEY_F(15)); - define_key("\033[11~", KEY_F(1)); - define_key("\033[12~", KEY_F(2)); - define_key("\033[13~", KEY_F(3)); - define_key("\033[14~", KEY_F(4)); - define_key("\033[14;2~", KEY_F(15)); - define_key("\033[17;2~", KEY_F(18)); - char sequence[3] = "\033a"; - for (char c = 'a'; c <= 'z'; c++) { - sequence[1] = c; - define_key(sequence, KEY_ALT('A' + (c - 'a'))); - } - } - - struct sigaction act; - sigemptyset (&act.sa_mask); - act.sa_flags = (int)SA_RESETHAND | SA_NODEFER; - act.sa_handler = CRT_handleSIGSEGV; - sigaction (SIGSEGV, &act, &old_sig_handler[SIGSEGV]); - sigaction (SIGFPE, &act, &old_sig_handler[SIGFPE]); - sigaction (SIGILL, &act, &old_sig_handler[SIGILL]); - sigaction (SIGBUS, &act, &old_sig_handler[SIGBUS]); - sigaction (SIGPIPE, &act, &old_sig_handler[SIGPIPE]); - sigaction (SIGSYS, &act, &old_sig_handler[SIGSYS]); - sigaction (SIGABRT, &act, &old_sig_handler[SIGABRT]); - - signal(SIGTERM, CRT_handleSIGTERM); - signal(SIGQUIT, CRT_handleSIGTERM); - - use_default_colors(); - if (!has_colors()) - CRT_colorScheme = COLORSCHEME_MONOCHROME; - CRT_setColors(CRT_colorScheme); - -#ifdef HAVE_LIBNCURSESW - if (allowUnicode && String_eq(nl_langinfo(CODESET), "UTF-8")) { - CRT_utf8 = true; - } else { - CRT_utf8 = false; - } -#else - (void) allowUnicode; -#endif - - CRT_treeStr = -#ifdef HAVE_LIBNCURSESW - CRT_utf8 ? CRT_treeStrUtf8 : -#endif - CRT_treeStrAscii; - -#if NCURSES_MOUSE_VERSION > 1 - mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL); -#else - mousemask(BUTTON1_RELEASED, NULL); -#endif - - CRT_degreeSign = initDegreeSign(); -} - -void CRT_done() { - curs_set(1); - endwin(); - - dumpStderr(); -} - -void CRT_fatalError(const char* note) { - const char* sysMsg = strerror(errno); - CRT_done(); - fprintf(stderr, "%s: %s\n", note, sysMsg); - exit(2); -} - -int CRT_readKey() { - nocbreak(); - cbreak(); - nodelay(stdscr, FALSE); - int ret = getch(); - halfdelay(*CRT_delay); - return ret; -} - -void CRT_disableDelay() { - nocbreak(); - cbreak(); - nodelay(stdscr, TRUE); -} - -void CRT_enableDelay() { - halfdelay(*CRT_delay); -} - -void CRT_setColors(int colorScheme) { - CRT_colorScheme = colorScheme; - - for (short int i = 0; i < 8; i++) { - for (short int j = 0; j < 8; j++) { - if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault) { - short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT) - ? (j == 0 ? -1 : j) - : j; - init_pair(ColorIndex(i, j), i, bg); - } - } - } - - short int grayBlackFg = COLORS > 8 ? 8 : 0; - short int grayBlackBg = (colorScheme != COLORSCHEME_BLACKNIGHT) ? -1 : 0; - init_pair(ColorIndexGrayBlack, grayBlackFg, grayBlackBg); - - init_pair(ColorIndexWhiteDefault, White, -1); - - CRT_colors = CRT_colorSchemes[colorScheme]; -} - -void CRT_handleSIGSEGV(int signal) { - CRT_done(); - - fprintf(stderr, "\n\n" - "FATAL PROGRAM ERROR DETECTED\n" - "============================\n" - "Please check at https://htop.dev/issues whether this issue has already been reported.\n" - "If no similar issue has been reported before, please create a new issue with the following information:\n" - "\n" - "- Your htop version (htop --version)\n" - "- Your OS and kernel version (uname -a)\n" - "- Your distribution and release (lsb_release -a)\n" - "- Likely steps to reproduce (How did it happened?)\n" - ); - -#ifdef HAVE_EXECINFO_H - fprintf(stderr, "- Backtrace of the issue (see below)\n"); -#endif - - fprintf(stderr, - "\n" - ); - - const char* signal_str = strsignal(signal); - if (!signal_str) { - signal_str = "unknown reason"; - } - fprintf(stderr, - "Error information:\n" - "------------------\n" - "A signal %d (%s) was received.\n" - "\n", - signal, signal_str - ); - -#ifdef HAVE_EXECINFO_H - fprintf(stderr, - "Backtrace information:\n" - "----------------------\n" - "The following function calls were active when the issue was detected:\n" - "---\n" - ); - - void *backtraceArray[256]; - - size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray)); - backtrace_symbols_fd(backtraceArray, size, 2); - fprintf(stderr, - "---\n" - "\n" - "To make the above information more practical to work with,\n" - "you should provide a disassembly of your binary.\n" - "This can usually be done by running the following command:\n" - "\n" - ); - -#ifdef HTOP_DARWIN - fprintf(stderr, " otool -tvV `which htop` > ~/htop.otool\n"); -#else - fprintf(stderr, " objdump -d -S -w `which htop` > ~/htop.objdump\n"); -#endif - - fprintf(stderr, - "\n" - "Please include the generated file in your report.\n" - "\n" - ); -#endif - - fprintf(stderr, - "Running this program with debug symbols or inside a debugger may provide further insights.\n" - "\n" - "Thank you for helping to improve htop!\n" - "\n" - "htop " VERSION " aborting.\n" - "\n" - ); - - /* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */ - if (sigaction (signal, &old_sig_handler[signal], NULL) < 0) { - /* This avoids an infinite loop in case the handler could not be reset. */ - fprintf(stderr, - "!!! Chained handler could not be restored. Forcing exit.\n" - ); - _exit(1); - } - - /* Trigger the previous signal handler. */ - raise(signal); - - // Always terminate, even if installed handler returns - fprintf(stderr, - "!!! Chained handler did not exit. Forcing exit.\n" - ); - _exit(1); -} diff -Nru pcp-5.3.1/src/pcp/htop/CRT.h pcp-5.3.2/src/pcp/htop/CRT.h --- pcp-5.3.1/src/pcp/htop/CRT.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/CRT.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -#ifndef HEADER_CRT -#define HEADER_CRT -/* -htop - CRT.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" - -#include - -#include "Macros.h" -#include "ProvideCurses.h" -#include "Settings.h" - - -typedef enum TreeStr_ { - TREE_STR_VERT, - TREE_STR_RTEE, - TREE_STR_BEND, - TREE_STR_TEND, - TREE_STR_OPEN, - TREE_STR_SHUT, - TREE_STR_ASC, - TREE_STR_DESC, - LAST_TREE_STR -} TreeStr; - -typedef enum ColorScheme_ { - COLORSCHEME_DEFAULT, - COLORSCHEME_MONOCHROME, - COLORSCHEME_BLACKONWHITE, - COLORSCHEME_LIGHTTERMINAL, - COLORSCHEME_MIDNIGHT, - COLORSCHEME_BLACKNIGHT, - COLORSCHEME_BROKENGRAY, - LAST_COLORSCHEME -} ColorScheme; - -typedef enum ColorElements_ { - RESET_COLOR, - DEFAULT_COLOR, - FUNCTION_BAR, - FUNCTION_KEY, - FAILED_SEARCH, - FAILED_READ, - PAUSED, - PANEL_HEADER_FOCUS, - PANEL_HEADER_UNFOCUS, - PANEL_SELECTION_FOCUS, - PANEL_SELECTION_FOLLOW, - PANEL_SELECTION_UNFOCUS, - LARGE_NUMBER, - METER_SHADOW, - METER_TEXT, - METER_VALUE, - METER_VALUE_ERROR, - METER_VALUE_IOREAD, - METER_VALUE_IOWRITE, - METER_VALUE_NOTICE, - METER_VALUE_OK, - METER_VALUE_WARN, - LED_COLOR, - UPTIME, - BATTERY, - TASKS_RUNNING, - SWAP, - SWAP_CACHE, - PROCESS, - PROCESS_SHADOW, - PROCESS_TAG, - PROCESS_MEGABYTES, - PROCESS_GIGABYTES, - PROCESS_TREE, - PROCESS_R_STATE, - PROCESS_D_STATE, - PROCESS_BASENAME, - PROCESS_HIGH_PRIORITY, - PROCESS_LOW_PRIORITY, - PROCESS_NEW, - PROCESS_TOMB, - PROCESS_THREAD, - PROCESS_THREAD_BASENAME, - PROCESS_COMM, - PROCESS_THREAD_COMM, - BAR_BORDER, - BAR_SHADOW, - GRAPH_1, - GRAPH_2, - MEMORY_USED, - MEMORY_BUFFERS, - MEMORY_BUFFERS_TEXT, - MEMORY_CACHE, - MEMORY_SHARED, - HUGEPAGE_1, - HUGEPAGE_2, - HUGEPAGE_3, - HUGEPAGE_4, - LOAD, - LOAD_AVERAGE_FIFTEEN, - LOAD_AVERAGE_FIVE, - LOAD_AVERAGE_ONE, - CHECK_BOX, - CHECK_MARK, - CHECK_TEXT, - CLOCK, - DATE, - DATETIME, - HELP_BOLD, - HOSTNAME, - CPU_NICE, - CPU_NICE_TEXT, - CPU_NORMAL, - CPU_SYSTEM, - CPU_IOWAIT, - CPU_IRQ, - CPU_SOFTIRQ, - CPU_STEAL, - CPU_GUEST, - PRESSURE_STALL_TEN, - PRESSURE_STALL_SIXTY, - PRESSURE_STALL_THREEHUNDRED, - ZFS_MFU, - ZFS_MRU, - ZFS_ANON, - ZFS_HEADER, - ZFS_OTHER, - ZFS_COMPRESSED, - ZFS_RATIO, - ZRAM, - LAST_COLORELEMENT -} ColorElements; - -void CRT_fatalError(const char* note) ATTR_NORETURN; - -void CRT_handleSIGSEGV(int signal) ATTR_NORETURN; - -#define KEY_WHEELUP KEY_F(20) -#define KEY_WHEELDOWN KEY_F(21) -#define KEY_RECLICK KEY_F(22) -#define KEY_ALT(x) (KEY_F(64 - 26) + ((x) - 'A')) - -extern const char* CRT_degreeSign; - -#ifdef HAVE_LIBNCURSESW - -extern bool CRT_utf8; - -#endif - -extern const char* const* CRT_treeStr; - -extern const int* CRT_colors; - -extern int CRT_cursorX; - -extern int CRT_scrollHAmount; - -extern int CRT_scrollWheelVAmount; - -extern ColorScheme CRT_colorScheme; - -void CRT_init(const Settings* settings, bool allowUnicode); - -void CRT_done(void); - -int CRT_readKey(void); - -void CRT_disableDelay(void); - -void CRT_enableDelay(void); - -void CRT_setColors(int colorScheme); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/DateMeter.c pcp-5.3.2/src/pcp/htop/DateMeter.c --- pcp-5.3.1/src/pcp/htop/DateMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DateMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* -htop - DateMeter.c -(C) 2004-2020 Hisham H. Muhammad, Michael Schönitzer -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "DateMeter.h" - -#include - -#include "CRT.h" -#include "Object.h" - - -static const int DateMeter_attributes[] = { - DATE -}; - -static void DateMeter_updateValues(Meter* this) { - const ProcessList* pl = this->pl; - - struct tm result; - const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result); - this->values[0] = lt->tm_yday; - int year = lt->tm_year + 1900; - if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { - this->total = 366; - } else { - this->total = 365; - } - strftime(this->txtBuffer, sizeof(this->txtBuffer), "%F", lt); -} - -const MeterClass DateMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = DateMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 365, - .attributes = DateMeter_attributes, - .name = "Date", - .uiName = "Date", - .caption = "Date: ", -}; diff -Nru pcp-5.3.1/src/pcp/htop/DateMeter.h pcp-5.3.2/src/pcp/htop/DateMeter.h --- pcp-5.3.1/src/pcp/htop/DateMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DateMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_DateMeter -#define HEADER_DateMeter -/* -htop - DateMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass DateMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/DateTimeMeter.c pcp-5.3.2/src/pcp/htop/DateTimeMeter.c --- pcp-5.3.1/src/pcp/htop/DateTimeMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DateTimeMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* -htop - DateTimeMeter.c -(C) 2004-2020 Hisham H. Muhammad, Michael Schönitzer -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "DateTimeMeter.h" - -#include - -#include "CRT.h" -#include "Object.h" - - -static const int DateTimeMeter_attributes[] = { - DATETIME -}; - -static void DateTimeMeter_updateValues(Meter* this) { - const ProcessList* pl = this->pl; - - struct tm result; - const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result); - int year = lt->tm_year + 1900; - if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { - this->total = 366; - } else { - this->total = 365; - } - this->values[0] = lt->tm_yday; - strftime(this->txtBuffer, sizeof(this->txtBuffer), "%F %H:%M:%S", lt); -} - -const MeterClass DateTimeMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = DateTimeMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 365, - .attributes = DateTimeMeter_attributes, - .name = "DateTime", - .uiName = "Date and Time", - .caption = "Date & Time: ", -}; diff -Nru pcp-5.3.1/src/pcp/htop/DateTimeMeter.h pcp-5.3.2/src/pcp/htop/DateTimeMeter.h --- pcp-5.3.1/src/pcp/htop/DateTimeMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DateTimeMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_DateTimeMeter -#define HEADER_DateTimeMeter -/* -htop - DateTimeMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass DateTimeMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/DiskIOMeter.c pcp-5.3.2/src/pcp/htop/DiskIOMeter.c --- pcp-5.3.1/src/pcp/htop/DiskIOMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DiskIOMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -/* -htop - DiskIOMeter.c -(C) 2020 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "DiskIOMeter.h" - -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" -#include "XUtils.h" - - -static const int DiskIOMeter_attributes[] = { - METER_VALUE_NOTICE, - METER_VALUE_IOREAD, - METER_VALUE_IOWRITE, -}; - -static bool hasData = false; -static uint32_t cached_read_diff; -static uint32_t cached_write_diff; -static double cached_utilisation_diff; - -static void DiskIOMeter_updateValues(Meter* this) { - const ProcessList* pl = this->pl; - - static uint64_t cached_last_update; - uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update; - - /* update only every 500ms */ - if (passedTimeInMs > 500) { - static uint64_t cached_read_total; - static uint64_t cached_write_total; - static uint64_t cached_msTimeSpend_total; - uint64_t diff; - - cached_last_update = pl->realtimeMs; - - DiskIOData data; - - hasData = Platform_getDiskIO(&data); - if (!hasData) { - this->values[0] = 0; - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "no data"); - return; - } - - if (data.totalBytesRead > cached_read_total) { - diff = data.totalBytesRead - cached_read_total; - diff /= 1024; /* Meter_humanUnit() expects unit in kilo */ - cached_read_diff = (uint32_t)diff; - } else { - cached_read_diff = 0; - } - cached_read_total = data.totalBytesRead; - - if (data.totalBytesWritten > cached_write_total) { - diff = data.totalBytesWritten - cached_write_total; - diff /= 1024; /* Meter_humanUnit() expects unit in kilo */ - cached_write_diff = (uint32_t)diff; - } else { - cached_write_diff = 0; - } - cached_write_total = data.totalBytesWritten; - - if (data.totalMsTimeSpend > cached_msTimeSpend_total) { - diff = data.totalMsTimeSpend - cached_msTimeSpend_total; - cached_utilisation_diff = 100.0 * (double)diff / passedTimeInMs; - } else { - cached_utilisation_diff = 0.0; - } - cached_msTimeSpend_total = data.totalMsTimeSpend; - } - - this->values[0] = cached_utilisation_diff; - this->total = MAXIMUM(this->values[0], 100.0); /* fix total after (initial) spike */ - - char bufferRead[12], bufferWrite[12]; - Meter_humanUnit(bufferRead, cached_read_diff, sizeof(bufferRead)); - Meter_humanUnit(bufferWrite, cached_write_diff, sizeof(bufferWrite)); - snprintf(this->txtBuffer, sizeof(this->txtBuffer), "%sB %sB %.1f%%", bufferRead, bufferWrite, cached_utilisation_diff); -} - -static void DiskIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) { - if (!hasData) { - RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data"); - return; - } - - char buffer[16]; - - int color = cached_utilisation_diff > 40.0 ? METER_VALUE_NOTICE : METER_VALUE; - xSnprintf(buffer, sizeof(buffer), "%.1f%%", cached_utilisation_diff); - RichString_writeAscii(out, CRT_colors[color], buffer); - - RichString_appendAscii(out, CRT_colors[METER_TEXT], " read: "); - Meter_humanUnit(buffer, cached_read_diff, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer); - - RichString_appendAscii(out, CRT_colors[METER_TEXT], " write: "); - Meter_humanUnit(buffer, cached_write_diff, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer); -} - -const MeterClass DiskIOMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = DiskIOMeter_display - }, - .updateValues = DiskIOMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 100.0, - .attributes = DiskIOMeter_attributes, - .name = "DiskIO", - .uiName = "Disk IO", - .caption = "Disk IO: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/DiskIOMeter.h pcp-5.3.2/src/pcp/htop/DiskIOMeter.h --- pcp-5.3.1/src/pcp/htop/DiskIOMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DiskIOMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#ifndef HEADER_DiskIOMeter -#define HEADER_DiskIOMeter -/* -htop - DiskIOMeter.h -(C) 2020 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -typedef struct DiskIOData_ { - uint64_t totalBytesRead; - uint64_t totalBytesWritten; - uint64_t totalMsTimeSpend; -} DiskIOData; - -extern const MeterClass DiskIOMeter_class; - -#endif /* HEADER_DiskIOMeter */ diff -Nru pcp-5.3.1/src/pcp/htop/DisplayOptionsPanel.c pcp-5.3.2/src/pcp/htop/DisplayOptionsPanel.c --- pcp-5.3.1/src/pcp/htop/DisplayOptionsPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DisplayOptionsPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,142 +0,0 @@ -/* -htop - DisplayOptionsPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "DisplayOptionsPanel.h" - -#include -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "Header.h" -#include "Object.h" -#include "OptionItem.h" -#include "ProvideCurses.h" - - -static const char* const DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; - -static void DisplayOptionsPanel_delete(Object* object) { - Panel* super = (Panel*) object; - DisplayOptionsPanel* this = (DisplayOptionsPanel*) object; - Panel_done(super); - free(this); -} - -static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) { - DisplayOptionsPanel* this = (DisplayOptionsPanel*) super; - - HandlerResult result = IGNORED; - OptionItem* selected = (OptionItem*) Panel_getSelected(super); - - switch (ch) { - case '\n': - case '\r': - case KEY_ENTER: - case KEY_MOUSE: - case KEY_RECLICK: - case ' ': - switch (OptionItem_kind(selected)) { - case OPTION_ITEM_CHECK: - CheckItem_toggle((CheckItem*)selected); - result = HANDLED; - break; - case OPTION_ITEM_NUMBER: - NumberItem_toggle((NumberItem*)selected); - result = HANDLED; - break; - } - break; - case '-': - if (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) { - NumberItem_decrease((NumberItem*)selected); - result = HANDLED; - } - break; - case '+': - if (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) { - NumberItem_increase((NumberItem*)selected); - result = HANDLED; - } - break; - } - - if (result == HANDLED) { - this->settings->changed = true; - Header* header = this->scr->header; - Header_calculateHeight(header); - Header_reinit(header); - Header_updateData(header); - Header_draw(header); - ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); - } - return result; -} - -const PanelClass DisplayOptionsPanel_class = { - .super = { - .extends = Class(Panel), - .delete = DisplayOptionsPanel_delete - }, - .eventHandler = DisplayOptionsPanel_eventHandler -}; - -DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) { - DisplayOptionsPanel* this = AllocThis(DisplayOptionsPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_new(DisplayOptionsFunctions, NULL, NULL); - Panel_init(super, 1, 1, 1, 1, Class(OptionItem), true, fuBar); - - this->settings = settings; - this->scr = scr; - - Panel_setHeader(super, "Display options"); - Panel_add(super, (Object*) CheckItem_newByRef("Tree view", &(settings->treeView))); - Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is always sorted by PID (htop 2 behavior)", &(settings->treeViewAlwaysByPID))); - Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is collapsed by default", &(settings->allBranchesCollapsed))); - Panel_add(super, (Object*) CheckItem_newByRef("Shadow other users' processes", &(settings->shadowOtherUsers))); - Panel_add(super, (Object*) CheckItem_newByRef("Hide kernel threads", &(settings->hideKernelThreads))); - Panel_add(super, (Object*) CheckItem_newByRef("Hide userland process threads", &(settings->hideUserlandThreads))); - Panel_add(super, (Object*) CheckItem_newByRef("Display threads in a different color", &(settings->highlightThreads))); - Panel_add(super, (Object*) CheckItem_newByRef("Show custom thread names", &(settings->showThreadNames))); - Panel_add(super, (Object*) CheckItem_newByRef("Show program path", &(settings->showProgramPath))); - Panel_add(super, (Object*) CheckItem_newByRef("Highlight program \"basename\"", &(settings->highlightBaseName))); - Panel_add(super, (Object*) CheckItem_newByRef("Merge exe, comm and cmdline in Command", &(settings->showMergedCommand))); - Panel_add(super, (Object*) CheckItem_newByRef("- Try to find comm in cmdline (when Command is merged)", &(settings->findCommInCmdline))); - Panel_add(super, (Object*) CheckItem_newByRef("- Try to strip exe from cmdline (when Command is merged)", &(settings->stripExeFromCmdline))); - Panel_add(super, (Object*) CheckItem_newByRef("Highlight large numbers in memory counters", &(settings->highlightMegabytes))); - Panel_add(super, (Object*) CheckItem_newByRef("Leave a margin around header", &(settings->headerMargin))); - Panel_add(super, (Object*) CheckItem_newByRef("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest)", &(settings->detailedCPUTime))); - Panel_add(super, (Object*) CheckItem_newByRef("Count CPUs from 1 instead of 0", &(settings->countCPUsFromOne))); - Panel_add(super, (Object*) CheckItem_newByRef("Update process names on every refresh", &(settings->updateProcessNames))); - Panel_add(super, (Object*) CheckItem_newByRef("Add guest time in CPU meter percentage", &(settings->accountGuestInCPUMeter))); - Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU percentage numerically", &(settings->showCPUUsage))); - Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU frequency", &(settings->showCPUFrequency))); - #ifdef BUILD_WITH_CPU_TEMP - Panel_add(super, (Object*) CheckItem_newByRef( - #if defined(HTOP_LINUX) - "Also show CPU temperature (requires libsensors)", - #elif defined(HTOP_FREEBSD) - "Also show CPU temperature", - #else - #error Unknown temperature implementation! - #endif - &(settings->showCPUTemperature))); - Panel_add(super, (Object*) CheckItem_newByRef("- Show temperature in degree Fahrenheit instead of Celsius", &(settings->degreeFahrenheit))); - #endif - Panel_add(super, (Object*) CheckItem_newByRef("Enable the mouse", &(settings->enableMouse))); - Panel_add(super, (Object*) NumberItem_newByRef("Update interval (in seconds)", &(settings->delay), -1, 1, 255)); - Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges))); - Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24*60*60)); - Panel_add(super, (Object*) NumberItem_newByRef("Hide main function bar (0 - off, 1 - on ESC until next input, 2 - permanently)", &(settings->hideFunctionBar), 0, 0, 2)); - #ifdef HAVE_LIBHWLOC - Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity))); - #endif - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/DisplayOptionsPanel.h pcp-5.3.2/src/pcp/htop/DisplayOptionsPanel.h --- pcp-5.3.1/src/pcp/htop/DisplayOptionsPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/DisplayOptionsPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -#ifndef HEADER_DisplayOptionsPanel -#define HEADER_DisplayOptionsPanel -/* -htop - DisplayOptionsPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Panel.h" -#include "ScreenManager.h" -#include "Settings.h" - -typedef struct DisplayOptionsPanel_ { - Panel super; - - Settings* settings; - ScreenManager* scr; -} DisplayOptionsPanel; - -extern const PanelClass DisplayOptionsPanel_class; - -DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/EnvScreen.c pcp-5.3.2/src/pcp/htop/EnvScreen.c --- pcp-5.3.1/src/pcp/htop/EnvScreen.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/EnvScreen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#include "config.h" // IWYU pragma: keep - -#include "EnvScreen.h" - -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Panel.h" -#include "Platform.h" -#include "ProvideCurses.h" -#include "Vector.h" -#include "XUtils.h" - - -EnvScreen* EnvScreen_new(Process* process) { - EnvScreen* this = xMalloc(sizeof(EnvScreen)); - Object_setClass(this, Class(EnvScreen)); - return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " "); -} - -void EnvScreen_delete(Object* this) { - free(InfoScreen_done((InfoScreen*)this)); -} - -static void EnvScreen_draw(InfoScreen* this) { - InfoScreen_drawTitled(this, "Environment of process %d - %s", this->process->pid, Process_getCommand(this->process)); -} - -static void EnvScreen_scan(InfoScreen* this) { - Panel* panel = this->display; - int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0); - - Panel_prune(panel); - - char* env = Platform_getProcessEnv(this->process->pid); - if (env) { - for (const char* p = env; *p; p = strrchr(p, 0) + 1) - InfoScreen_addLine(this, p); - free(env); - } - else { - InfoScreen_addLine(this, "Could not read process environment."); - } - - Vector_insertionSort(this->lines); - Vector_insertionSort(panel->items); - Panel_setSelected(panel, idx); -} - -const InfoScreenClass EnvScreen_class = { - .super = { - .extends = Class(Object), - .delete = EnvScreen_delete - }, - .scan = EnvScreen_scan, - .draw = EnvScreen_draw -}; diff -Nru pcp-5.3.1/src/pcp/htop/EnvScreen.h pcp-5.3.2/src/pcp/htop/EnvScreen.h --- pcp-5.3.1/src/pcp/htop/EnvScreen.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/EnvScreen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#ifndef HEADER_EnvScreen -#define HEADER_EnvScreen - -#include "InfoScreen.h" -#include "Object.h" -#include "Process.h" - -typedef struct EnvScreen_ { - InfoScreen super; -} EnvScreen; - -extern const InfoScreenClass EnvScreen_class; - -EnvScreen* EnvScreen_new(Process* process); - -void EnvScreen_delete(Object* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/FunctionBar.c pcp-5.3.2/src/pcp/htop/FunctionBar.c --- pcp-5.3.1/src/pcp/htop/FunctionBar.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/FunctionBar.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -/* -htop - FunctionBar.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "FunctionBar.h" - -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static const char* const FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL}; - -static const char* const FunctionBar_FLabels[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", NULL}; - -static int FunctionBar_FEvents[] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10)}; - -static const char* const FunctionBar_EnterEscKeys[] = {"Enter", "Esc", NULL}; -static const int FunctionBar_EnterEscEvents[] = {13, 27}; - -static int currentLen = 0; - -FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc) { - const char* functions[] = {enter, esc, NULL}; - return FunctionBar_new(functions, FunctionBar_EnterEscKeys, FunctionBar_EnterEscEvents); -} - -FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events) { - FunctionBar* this = xCalloc(1, sizeof(FunctionBar)); - this->functions = xCalloc(16, sizeof(char*)); - if (!functions) { - functions = FunctionBar_FLabels; - } - for (int i = 0; i < 15 && functions[i]; i++) { - this->functions[i] = xStrdup(functions[i]); - } - if (keys && events) { - this->staticData = false; - this->keys.keys = xCalloc(15, sizeof(char*)); - this->events = xCalloc(15, sizeof(int)); - int i = 0; - while (i < 15 && functions[i]) { - this->keys.keys[i] = xStrdup(keys[i]); - this->events[i] = events[i]; - i++; - } - this->size = i; - } else { - this->staticData = true; - this->keys.constKeys = FunctionBar_FKeys; - this->events = FunctionBar_FEvents; - this->size = ARRAYSIZE(FunctionBar_FEvents); - } - return this; -} - -void FunctionBar_delete(FunctionBar* this) { - for (int i = 0; i < 15 && this->functions[i]; i++) { - free(this->functions[i]); - } - free(this->functions); - if (!this->staticData) { - for (int i = 0; i < this->size; i++) { - free(this->keys.keys[i]); - } - free(this->keys.keys); - free(this->events); - } - free(this); -} - -void FunctionBar_setLabel(FunctionBar* this, int event, const char* text) { - for (int i = 0; i < this->size; i++) { - if (this->events[i] == event) { - free(this->functions[i]); - this->functions[i] = xStrdup(text); - break; - } - } -} - -void FunctionBar_draw(const FunctionBar* this) { - FunctionBar_drawExtra(this, NULL, -1, false); -} - -void FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor) { - attrset(CRT_colors[FUNCTION_BAR]); - mvhline(LINES - 1, 0, ' ', COLS); - int x = 0; - for (int i = 0; i < this->size; i++) { - attrset(CRT_colors[FUNCTION_KEY]); - mvaddstr(LINES - 1, x, this->keys.constKeys[i]); - x += strlen(this->keys.constKeys[i]); - attrset(CRT_colors[FUNCTION_BAR]); - mvaddstr(LINES - 1, x, this->functions[i]); - x += strlen(this->functions[i]); - } - - if (buffer) { - if (attr == -1) { - attrset(CRT_colors[FUNCTION_BAR]); - } else { - attrset(attr); - } - mvaddstr(LINES - 1, x, buffer); - x += strlen(buffer); - } - - attrset(CRT_colors[RESET_COLOR]); - - if (setCursor) { - CRT_cursorX = x; - curs_set(1); - } else { - curs_set(0); - } - - currentLen = x; -} - -void FunctionBar_append(const char* buffer, int attr) { - if (attr == -1) { - attrset(CRT_colors[FUNCTION_BAR]); - } else { - attrset(attr); - } - mvaddstr(LINES - 1, currentLen + 1, buffer); - attrset(CRT_colors[RESET_COLOR]); - - currentLen += strlen(buffer) + 1; -} - -int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) { - int x = 0; - for (int i = 0; i < this->size; i++) { - x += strlen(this->keys.constKeys[i]); - x += strlen(this->functions[i]); - if (pos < x) { - return this->events[i]; - } - } - return ERR; -} diff -Nru pcp-5.3.1/src/pcp/htop/FunctionBar.h pcp-5.3.2/src/pcp/htop/FunctionBar.h --- pcp-5.3.1/src/pcp/htop/FunctionBar.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/FunctionBar.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -#ifndef HEADER_FunctionBar -#define HEADER_FunctionBar -/* -htop - FunctionBar.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -typedef struct FunctionBar_ { - int size; - char** functions; - union { - char** keys; - const char* const* constKeys; - } keys; - int* events; - bool staticData; -} FunctionBar; - -FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc); - -FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events); - -void FunctionBar_delete(FunctionBar* this); - -void FunctionBar_setLabel(FunctionBar* this, int event, const char* text); - -void FunctionBar_draw(const FunctionBar* this); - -void FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor); - -void FunctionBar_append(const char* buffer, int attr); - -int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/.gitignore pcp-5.3.2/src/pcp/htop/.gitignore --- pcp-5.3.1/src/pcp/htop/.gitignore 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/.gitignore 2021-07-30 04:05:06.000000000 +0000 @@ -1 +1,7 @@ +htop.1.in pcp-htop +pcp/columns +pcp/meters +AUTHORS +*.h +*.c diff -Nru pcp-5.3.1/src/pcp/htop/GNUmakefile pcp-5.3.2/src/pcp/htop/GNUmakefile --- pcp-5.3.1/src/pcp/htop/GNUmakefile 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -24,9 +24,10 @@ LCFLAGS = $(NCURSES_CFLAGS) $(C99_CFLAGS) -Ipcp -I. LCFLAGS += -DVERSION=\"$(PCP_VERSION)\" -DSYSCONFDIR=\"$(PCP_SYSCONF_DIR)\" LCFLAGS += -DCOPYRIGHT=\"$(COPYRIGHT)\" -DPACKAGE=\"$(CMDTARGET)\" -LCFLAGS += -DMAJOR_IN_SYSMACROS=1 +LCFLAGS += -DMAJOR_IN_SYSMACROS=1 -DNDEBUG -CFILES = \ +TOPCFILES = \ + pcp-htop.c \ Action.c \ AvailableColumnsPanel.c \ AvailableMetersPanel.c \ @@ -44,6 +45,7 @@ DateTimeMeter.c \ DiskIOMeter.c \ DisplayOptionsPanel.c \ + DynamicMeter.c \ EnvScreen.c \ FunctionBar.c \ Hashtable.c \ @@ -77,16 +79,18 @@ UsersTable.c \ Vector.c \ XUtils.c \ + +SUBCFILES = \ linux/PressureStallMeter.c \ linux/ZramMeter.c \ zfs/ZfsArcMeter.c \ zfs/ZfsCompressedArcMeter.c \ + pcp/PCPDynamicMeter.c \ pcp/PCPProcess.c \ pcp/PCPProcessList.c \ pcp/Platform.c \ - pcp-htop.c \ -HFILES = \ +TOPHFILES = \ Action.h \ AvailableColumnsPanel.h \ AvailableMetersPanel.h \ @@ -104,6 +108,7 @@ DateTimeMeter.h \ DiskIOMeter.h \ DisplayOptionsPanel.h \ + DynamicMeter.h \ EnvScreen.h \ FunctionBar.h \ Hashtable.h \ @@ -139,17 +144,34 @@ UsersTable.h \ Vector.h \ XUtils.h \ + +SUBHFILES = \ linux/PressureStallMeter.h \ linux/ZramMeter.h \ linux/ZramStats.h \ zfs/ZfsArcMeter.h \ zfs/ZfsArcStats.h \ zfs/ZfsCompressedArcMeter.h \ + pcp/PCPDynamicMeter.h \ pcp/PCPProcess.h \ pcp/PCPProcessList.h \ pcp/Platform.h \ pcp/ProcessField.h \ +DOCFILES = AUTHORS htop.1.in +COLUMNS = +METERS = entropy freespace ipc locks memcache mysql postfix redis tcp +CFGMETERS = $(patsubst %,pcp/meters/%,$(METERS)) +CFGCOLUMNS = $(patsubst %,pcp/columns/%,$(COLUMNS)) + +CFGXFILES = $(CFGMETERS) $(CFGCOLUMNS) +TOPXFILES = $(TOPCFILES) $(TOPHFILES) $(DOCFILES) +SUBXFILES = $(SUBCFILES) $(SUBHFILES) +CFILES = $(TOPCFILES) $(SUBCFILES) +HFILES = $(TOPHFILES) $(SUBHFILES) +LDIRT = $(TOPXFILES) $(SUBXFILES) $(CFGXFILES) + +# manual sync MAN_PAGES = $(CMDTARGET).1 default: build-me @@ -157,10 +179,19 @@ include $(BUILDRULES) ifeq "$(HAVE_NCURSESW)" "true" -build-me: $(CMDTARGET) $(DISTLINKS) +build-me: $(TOPXFILES) $(SUBXFILES) $(CFGXFILES) $(CMDTARGET) $(DISTLINKS) install: default $(INSTALL) -m 755 $(CMDTARGET) $(DISTARGET) + $(INSTALL) -m 755 -d $(PCP_SYSCONF_DIR)/htop + $(INSTALL) -m 755 -d $(PCP_SYSCONF_DIR)/htop/meters + @for m in $(METERS); do \ + $(INSTALL) -m 644 pcp/meters/$$m $(PCP_SYSCONF_DIR)/htop/meters/$$m; \ + done + #$(INSTALL) -m 755 -d $(PCP_SYSCONF_DIR)/htop/columns + #@for c in $(COLUMNS); do \ + # $(INSTALL) -m 644 pcp/columns/$$m $(PCP_SYSCONF_DIR)/htop/columns/$$m; \ + #done @$(INSTALL_MAN) else build-me: @@ -171,6 +202,17 @@ install_pcp: install +$(TOPXFILES): + $(LN_S) -f $(TOPDIR)/vendor/github.com/htop-dev/htop/$@ $@ + +$(SUBXFILES): + mkdir -p linux pcp zfs + $(LN_S) -f $(TOPDIR)/../vendor/github.com/htop-dev/htop/$@ $@ + +$(CFGXFILES): + mkdir -p pcp/columns pcp/meters + $(LN_S) -f $(TOPDIR)/../../vendor/github.com/htop-dev/htop/$@ $@ + $(DISTLINKS): $(CMDTARGET) @$(LN_S) -f $(CMDTARGET) $@ diff -Nru pcp-5.3.1/src/pcp/htop/Hashtable.c pcp-5.3.2/src/pcp/htop/Hashtable.c --- pcp-5.3.1/src/pcp/htop/Hashtable.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Hashtable.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,323 +0,0 @@ -/* -htop - Hashtable.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "Hashtable.h" - -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "XUtils.h" - - -typedef struct HashtableItem_ { - ht_key_t key; - size_t probe; - void* value; -} HashtableItem; - -struct Hashtable_ { - size_t size; - HashtableItem* buckets; - size_t items; - bool owner; -}; - - -#ifndef NDEBUG - -static void Hashtable_dump(const Hashtable* this) { - fprintf(stderr, "Hashtable %p: size=%zu items=%zu owner=%s\n", - (const void*)this, - this->size, - this->items, - this->owner ? "yes" : "no"); - - size_t items = 0; - for (size_t i = 0; i < this->size; i++) { - fprintf(stderr, " item %5zu: key = %5u probe = %2zu value = %p\n", - i, - this->buckets[i].key, - this->buckets[i].probe, - this->buckets[i].value ? (const void*)this->buckets[i].value : "(nil)"); - - if (this->buckets[i].value) - items++; - } - - fprintf(stderr, "Hashtable %p: items=%zu counted=%zu\n", - (const void*)this, - this->items, - items); -} - -static bool Hashtable_isConsistent(const Hashtable* this) { - size_t items = 0; - for (size_t i = 0; i < this->size; i++) { - if (this->buckets[i].value) - items++; - } - bool res = items == this->items; - if (!res) - Hashtable_dump(this); - return res; -} - -size_t Hashtable_count(const Hashtable* this) { - size_t items = 0; - for (size_t i = 0; i < this->size; i++) { - if (this->buckets[i].value) - items++; - } - assert(items == this->items); - return items; -} - -#endif /* NDEBUG */ - -/* https://oeis.org/A014234 */ -static const uint64_t OEISprimes[] = { - 2, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, - 16381, 32749, 65521, 131071, 262139, 524287, 1048573, - 2097143, 4194301, 8388593, 16777213, 33554393, - 67108859, 134217689, 268435399, 536870909, 1073741789, - 2147483647, 4294967291, 8589934583, 17179869143, - 34359738337, 68719476731, 137438953447 -}; - -static size_t nextPrime(size_t n) { - /* on 32-bit make sure we do not return primes not fitting in size_t */ - for (size_t i = 0; i < ARRAYSIZE(OEISprimes) && OEISprimes[i] < SIZE_MAX; i++) { - if (n <= OEISprimes[i]) - return OEISprimes[i]; - } - - CRT_fatalError("Hashtable: no prime found"); -} - -Hashtable* Hashtable_new(size_t size, bool owner) { - Hashtable* this; - - this = xMalloc(sizeof(Hashtable)); - this->items = 0; - this->size = size ? nextPrime(size) : 13; - this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem)); - this->owner = owner; - - assert(Hashtable_isConsistent(this)); - return this; -} - -void Hashtable_delete(Hashtable* this) { - Hashtable_clear(this); - - free(this->buckets); - free(this); -} - -void Hashtable_clear(Hashtable* this) { - assert(Hashtable_isConsistent(this)); - - if (this->owner) - for (size_t i = 0; i < this->size; i++) - free(this->buckets[i].value); - - memset(this->buckets, 0, this->size * sizeof(HashtableItem)); - this->items = 0; - - assert(Hashtable_isConsistent(this)); -} - -static void insert(Hashtable* this, ht_key_t key, void* value) { - size_t index = key % this->size; - size_t probe = 0; -#ifndef NDEBUG - size_t origIndex = index; -#endif - - for (;;) { - if (!this->buckets[index].value) { - this->items++; - this->buckets[index].key = key; - this->buckets[index].probe = probe; - this->buckets[index].value = value; - return; - } - - if (this->buckets[index].key == key) { - if (this->owner && this->buckets[index].value != value) - free(this->buckets[index].value); - this->buckets[index].value = value; - return; - } - - /* Robin Hood swap */ - if (probe > this->buckets[index].probe) { - HashtableItem tmp = this->buckets[index]; - - this->buckets[index].key = key; - this->buckets[index].probe = probe; - this->buckets[index].value = value; - - key = tmp.key; - probe = tmp.probe; - value = tmp.value; - } - - index = (index + 1) % this->size; - probe++; - - assert(index != origIndex); - } -} - -void Hashtable_setSize(Hashtable* this, size_t size) { - - assert(Hashtable_isConsistent(this)); - - if (size <= this->items) - return; - - HashtableItem* oldBuckets = this->buckets; - size_t oldSize = this->size; - - this->size = nextPrime(size); - this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem)); - this->items = 0; - - /* rehash */ - for (size_t i = 0; i < oldSize; i++) { - if (!oldBuckets[i].value) - continue; - - insert(this, oldBuckets[i].key, oldBuckets[i].value); - } - - free(oldBuckets); - - assert(Hashtable_isConsistent(this)); -} - -void Hashtable_put(Hashtable* this, ht_key_t key, void* value) { - - assert(Hashtable_isConsistent(this)); - assert(this->size > 0); - assert(value); - - /* grow on load-factor > 0.7 */ - if (10 * this->items > 7 * this->size) { - if (SIZE_MAX / 2 < this->size) - CRT_fatalError("Hashtable: size overflow"); - - Hashtable_setSize(this, 2 * this->size); - } - - insert(this, key, value); - - assert(Hashtable_isConsistent(this)); - assert(Hashtable_get(this, key) != NULL); - assert(this->size > this->items); -} - -void* Hashtable_remove(Hashtable* this, ht_key_t key) { - size_t index = key % this->size; - size_t probe = 0; -#ifndef NDEBUG - size_t origIndex = index; -#endif - - assert(Hashtable_isConsistent(this)); - - void* res = NULL; - - while (this->buckets[index].value) { - if (this->buckets[index].key == key) { - if (this->owner) { - free(this->buckets[index].value); - } else { - res = this->buckets[index].value; - } - - size_t next = (index + 1) % this->size; - - while (this->buckets[next].value && this->buckets[next].probe > 0) { - this->buckets[index] = this->buckets[next]; - this->buckets[index].probe -= 1; - - index = next; - next = (index + 1) % this->size; - } - - /* set empty after backward shifting */ - this->buckets[index].value = NULL; - this->items--; - - break; - } - - if (this->buckets[index].probe < probe) - break; - - index = (index + 1) % this->size; - probe++; - - assert(index != origIndex); - } - - assert(Hashtable_isConsistent(this)); - assert(Hashtable_get(this, key) == NULL); - - /* shrink on load-factor < 0.125 */ - if (8 * this->items < this->size) - Hashtable_setSize(this, this->size / 2); - - return res; -} - -void* Hashtable_get(Hashtable* this, ht_key_t key) { - size_t index = key % this->size; - size_t probe = 0; - void* res = NULL; -#ifndef NDEBUG - size_t origIndex = index; -#endif - - assert(Hashtable_isConsistent(this)); - - while (this->buckets[index].value) { - if (this->buckets[index].key == key) { - res = this->buckets[index].value; - break; - } - - if (this->buckets[index].probe < probe) - break; - - index = (index + 1) != this->size ? (index + 1) : 0; - probe++; - - assert(index != origIndex); - } - - return res; -} - -void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) { - assert(Hashtable_isConsistent(this)); - for (size_t i = 0; i < this->size; i++) { - HashtableItem* walk = &this->buckets[i]; - if (walk->value) - f(walk->key, walk->value, userData); - } - assert(Hashtable_isConsistent(this)); -} diff -Nru pcp-5.3.1/src/pcp/htop/Hashtable.h pcp-5.3.2/src/pcp/htop/Hashtable.h --- pcp-5.3.1/src/pcp/htop/Hashtable.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Hashtable.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -#ifndef HEADER_Hashtable -#define HEADER_Hashtable -/* -htop - Hashtable.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include -#include - - -typedef unsigned int ht_key_t; - -typedef void(*Hashtable_PairFunction)(ht_key_t key, void* value, void* userdata); - -typedef struct Hashtable_ Hashtable; - -#ifndef NDEBUG - -size_t Hashtable_count(const Hashtable* this); - -#endif /* NDEBUG */ - -Hashtable* Hashtable_new(size_t size, bool owner); - -void Hashtable_delete(Hashtable* this); - -void Hashtable_clear(Hashtable* this); - -void Hashtable_setSize(Hashtable* this, size_t size); - -void Hashtable_put(Hashtable* this, ht_key_t key, void* value); - -void* Hashtable_remove(Hashtable* this, ht_key_t key); - -void* Hashtable_get(Hashtable* this, ht_key_t key); - -void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Header.c pcp-5.3.2/src/pcp/htop/Header.c --- pcp-5.3.1/src/pcp/htop/Header.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Header.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,236 +0,0 @@ -/* -htop - Header.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Header.h" - -#include -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Object.h" -#include "Platform.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -Header* Header_new(ProcessList* pl, Settings* settings, int nrColumns) { - Header* this = xCalloc(1, sizeof(Header)); - this->columns = xCalloc(nrColumns, sizeof(Vector*)); - this->settings = settings; - this->pl = pl; - this->nrColumns = nrColumns; - Header_forEachColumn(this, i) { - this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE); - } - return this; -} - -void Header_delete(Header* this) { - Header_forEachColumn(this, i) { - Vector_delete(this->columns[i]); - } - free(this->columns); - free(this); -} - -void Header_populateFromSettings(Header* this) { - Header_forEachColumn(this, col) { - const MeterColumnSettings* colSettings = &this->settings->columns[col]; - for (int i = 0; i < colSettings->len; i++) { - Header_addMeterByName(this, colSettings->names[i], col); - if (colSettings->modes[i] != 0) { - Header_setMode(this, i, colSettings->modes[i], col); - } - } - } - Header_calculateHeight(this); -} - -void Header_writeBackToSettings(const Header* this) { - Header_forEachColumn(this, col) { - MeterColumnSettings* colSettings = &this->settings->columns[col]; - - String_freeArray(colSettings->names); - free(colSettings->modes); - - const Vector* vec = this->columns[col]; - int len = Vector_size(vec); - - colSettings->names = xCalloc(len + 1, sizeof(char*)); - colSettings->modes = xCalloc(len, sizeof(int)); - colSettings->len = len; - - for (int i = 0; i < len; i++) { - const Meter* meter = (Meter*) Vector_get(vec, i); - char* name; - if (meter->param) { - xAsprintf(&name, "%s(%u)", As_Meter(meter)->name, meter->param); - } else { - xAsprintf(&name, "%s", As_Meter(meter)->name); - } - colSettings->names[i] = name; - colSettings->modes[i] = meter->mode; - } - } -} - -MeterModeId Header_addMeterByName(Header* this, const char* name, int column) { - Vector* meters = this->columns[column]; - - char* paren = strchr(name, '('); - unsigned int param = 0; - if (paren) { - int ok = sscanf(paren, "(%10u)", ¶m); - if (!ok) - param = 0; - *paren = '\0'; - } - MeterModeId mode = TEXT_METERMODE; - for (const MeterClass* const* type = Platform_meterTypes; *type; type++) { - if (String_eq(name, (*type)->name)) { - Meter* meter = Meter_new(this->pl, param, *type); - Vector_add(meters, meter); - mode = meter->mode; - break; - } - } - - if (paren) - *paren = '('; - - return mode; -} - -void Header_setMode(Header* this, int i, MeterModeId mode, int column) { - Vector* meters = this->columns[column]; - - if (i >= Vector_size(meters)) - return; - - Meter* meter = (Meter*) Vector_get(meters, i); - Meter_setMode(meter, mode); -} - -Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, int column) { - Vector* meters = this->columns[column]; - - Meter* meter = Meter_new(this->pl, param, type); - Vector_add(meters, meter); - return meter; -} - -int Header_size(const Header* this, int column) { - const Vector* meters = this->columns[column]; - return Vector_size(meters); -} - -MeterModeId Header_readMeterMode(const Header* this, int i, int column) { - const Vector* meters = this->columns[column]; - - const Meter* meter = (const Meter*) Vector_get(meters, i); - return meter->mode; -} - -void Header_reinit(Header* this) { - Header_forEachColumn(this, col) { - for (int i = 0; i < Vector_size(this->columns[col]); i++) { - Meter* meter = (Meter*) Vector_get(this->columns[col], i); - if (Meter_initFn(meter)) { - Meter_init(meter); - } - } - } -} - -void Header_draw(const Header* this) { - const int height = this->height; - const int pad = this->pad; - attrset(CRT_colors[RESET_COLOR]); - for (int y = 0; y < height; y++) { - mvhline(y, 0, ' ', COLS); - } - const int width = COLS / this->nrColumns - pad; - int x = pad; - - Header_forEachColumn(this, col) { - Vector* meters = this->columns[col]; - for (int y = (pad / 2), i = 0; i < Vector_size(meters); i++) { - Meter* meter = (Meter*) Vector_get(meters, i); - - int actualWidth; - if (meter->mode == TEXT_METERMODE) - actualWidth = meter->columnWidthCount * width + (meter->columnWidthCount - 1) * (2 * pad + 1); - else - actualWidth = width; - - meter->draw(meter, x, y, actualWidth); - y += meter->h; - } - x += width + pad; - } -} - -void Header_updateData(Header* this) { - Header_forEachColumn(this, col) { - Vector* meters = this->columns[col]; - int items = Vector_size(meters); - for (int i = 0; i < items; i++) { - Meter* meter = (Meter*) Vector_get(meters, i); - Meter_updateValues(meter); - } - } -} - -/* - * Calculate how many columns the current meter is allowed to span, - * by counting how many columns to the right are empty or contain a BlankMeter. - * Returns the number of columns to span, i.e. if the direct neighbor is occupied 1. - */ -static int calcColumnWidthCount(const Header* this, const Meter* curMeter, const int pad, const int curColumn, const int curHeight) { - for (int i = curColumn + 1; i < this->nrColumns; i++) { - const Vector* meters = this->columns[i]; - - int height = pad; - for (int j = 0; j < Vector_size(meters); j++) { - const Meter* meter = (const Meter*) Vector_get(meters, j); - - if (height >= curHeight + curMeter->h) - break; - - height += meter->h; - if (height <= curHeight) - continue; - - if (!Object_isA((const Object*) meter, (const ObjectClass*) &BlankMeter_class)) - return i - curColumn; - } - } - - return this->nrColumns - curColumn; -} - -int Header_calculateHeight(Header* this) { - const int pad = this->settings->headerMargin ? 2 : 0; - int maxHeight = pad; - - Header_forEachColumn(this, col) { - const Vector* meters = this->columns[col]; - int height = pad; - for (int i = 0; i < Vector_size(meters); i++) { - Meter* meter = (Meter*) Vector_get(meters, i); - meter->columnWidthCount = calcColumnWidthCount(this, meter, pad, col, height); - height += meter->h; - } - maxHeight = MAXIMUM(maxHeight, height); - } - this->height = maxHeight; - this->pad = pad; - return maxHeight; -} diff -Nru pcp-5.3.1/src/pcp/htop/Header.h pcp-5.3.2/src/pcp/htop/Header.h --- pcp-5.3.1/src/pcp/htop/Header.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Header.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -#ifndef HEADER_Header -#define HEADER_Header -/* -htop - Header.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" -#include "ProcessList.h" -#include "Settings.h" -#include "Vector.h" - -typedef struct Header_ { - Vector** columns; - Settings* settings; - ProcessList* pl; - int nrColumns; - int pad; - int height; -} Header; - -#define Header_forEachColumn(this_, i_) for (int (i_)=0; (i_) < (this_)->nrColumns; ++(i_)) - -Header* Header_new(ProcessList* pl, Settings* settings, int nrColumns); - -void Header_delete(Header* this); - -void Header_populateFromSettings(Header* this); - -void Header_writeBackToSettings(const Header* this); - -MeterModeId Header_addMeterByName(Header* this, const char* name, int column); - -void Header_setMode(Header* this, int i, MeterModeId mode, int column); - -Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, int column); - -int Header_size(const Header* this, int column); - -MeterModeId Header_readMeterMode(const Header* this, int i, int column); - -void Header_reinit(Header* this); - -void Header_draw(const Header* this); - -void Header_updateData(Header* this); - -int Header_calculateHeight(Header* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/HostnameMeter.c pcp-5.3.2/src/pcp/htop/HostnameMeter.c --- pcp-5.3.1/src/pcp/htop/HostnameMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/HostnameMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* -htop - HostnameMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "HostnameMeter.h" -#include "Platform.h" - -#include - -#include "CRT.h" -#include "Object.h" - - -static const int HostnameMeter_attributes[] = { - HOSTNAME -}; - -static void HostnameMeter_updateValues(Meter* this) { - Platform_getHostname(this->txtBuffer, sizeof(this->txtBuffer)); -} - -const MeterClass HostnameMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = HostnameMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 0, - .total = 100.0, - .attributes = HostnameMeter_attributes, - .name = "Hostname", - .uiName = "Hostname", - .caption = "Hostname: ", -}; diff -Nru pcp-5.3.1/src/pcp/htop/HostnameMeter.h pcp-5.3.2/src/pcp/htop/HostnameMeter.h --- pcp-5.3.1/src/pcp/htop/HostnameMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/HostnameMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_HostnameMeter -#define HEADER_HostnameMeter -/* -htop - HostnameMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass HostnameMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/htop.1.in pcp-5.3.2/src/pcp/htop/htop.1.in --- pcp-5.3.1/src/pcp/htop/htop.1.in 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/htop.1.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,507 +0,0 @@ -.TH "HTOP" "1" "2020" "@PACKAGE_STRING@" "User Commands" -.SH "NAME" -htop \- interactive process viewer -.SH "SYNOPSIS" -.B htop -.RB [ \-dCFhpustvH ] -.SH "DESCRIPTION" -.B htop -is a cross-platform ncurses-based process viewer. -.LP -It is similar to -.BR top , -but allows you to scroll vertically and horizontally, and interact using -a pointing device (mouse). -You can observe all processes running on the system, along with their -command line arguments, as well as view them in a tree format, select -multiple processes and acting on them all at once. -.LP -Tasks related to processes (killing, renicing) can be done without -entering their PIDs. -.br -.SH "COMMAND-LINE OPTIONS" -Mandatory arguments to long options are mandatory for short options too. -.TP -\fB\-d \-\-delay=DELAY\fR -Delay between updates, in tenths of seconds. If the delay value is -less than 1 it is increased to 1, i.e. 1/10 second. If the delay value -is greater than 100, it is decreased to 100, i.e. 10 seconds. -.TP -\fB\-C \-\-no-color \-\-no-colour\fR -Start -.B htop -in monochrome mode -.TP -\fB\-F \-\-filter=FILTER -Filter processes by command -.TP -\fB\-h \-\-help -Display a help message and exit -.TP -\fB\-p \-\-pid=PID,PID...\fR -Show only the given PIDs -.TP -\fB\-s \-\-sort\-key COLUMN\fR -Sort by this column (use \-\-sort\-key help for a column list). -This will force a list view unless you specify -t at the same time. -.TP -\fB\-u \-\-user=USERNAME\fR -Show only the processes of a given user -.TP -\fB\-U \-\-no-unicode\fR -Do not use unicode but ASCII characters for graph meters -.TP -\fB\-M \-\-no-mouse\fR -Disable support of mouse control -.TP -\fB\-V \-\-version -Output version information and exit -.TP -\fB\-t \-\-tree -Show processes in tree view. This can be used to force a tree view when -requesting a sort order with -s. -.TP -\fB\-H \-\-highlight-changes=DELAY\fR -Highlight new and old processes -.SH "INTERACTIVE COMMANDS" -The following commands are supported while in -.BR htop : -.TP 5 -.B Up, Alt-k -Select (highlight) the previous process in the process list. Scroll the list -if necessary. -.TP -.B Down, Alt-j -Select (highlight) the next process in the process list. Scroll the list if -necessary. -.TP -.B Left, Alt-h -Scroll the process list left. -.TP -.B Right, Alt-l -Scroll the process list right. -.TP -.B PgUp, PgDn -Scroll the process list up or down one window. -.TP -.B Home -Scroll to the top of the process list and select the first process. -.TP -.B End -Scroll to the bottom of the process list and select the last process. -.TP -.B Ctrl-A, ^ -Scroll left to the beginning of the process entry (i.e. beginning of line). -.TP -.B Ctrl-E, $ -Scroll right to the end of the process entry (i.e. end of line). -.TP -.B Space -Tag or untag a process. Commands that can operate on multiple processes, -like "kill", will then apply over the list of tagged processes, instead -of the currently highlighted one. -.TP -.B c -Tag the current process and its children. Commands that can operate on multiple -processes, like "kill", will then apply over the list of tagged processes, -instead of the currently highlighted one. -.TP -.B U -Untag all processes (remove all tags added with the Space or c keys). -.TP -.B s -Trace process system calls: if strace(1) is installed, pressing this key -will attach it to the currently selected process, presenting a live -update of system calls issued by the process. -.TP -.B l -Display open files for a process: if lsof(1) is installed, pressing this key -will display the list of file descriptors opened by the process. -.TP -.B w -Display the command line of the selected process in a separate screen, wrapped -onto multiple lines as needed. -.TP -.B x -Display the active file locks of the selected process in a separate screen. -.TP -.B F1, h, ? -Go to the help screen -.TP -.B F2, S -Go to the setup screen, where you can configure the meters displayed at the top -of the screen, set various display options, choose among color schemes, and -select which columns are displayed, in which order. -.TP -.B F3, / -Incrementally search the command lines of all the displayed processes. The -currently selected (highlighted) command will update as you type. While in -search mode, pressing F3 will cycle through matching occurrences. -Pressing Shift-F3 will cycle backwards. - -Alternatively the search can be started by simply typing the command -you are looking for, although for the first character normal key -bindings take precedence. -.TP -.B F4, \\\\ -Incremental process filtering: type in part of a process command line and -only processes whose names match will be shown. To cancel filtering, -enter the Filter option again and press Esc. -.TP -.B F5, t -Tree view: organize processes by parenthood, and layout the relations -between them as a tree. Toggling the key will switch between tree and -your previously selected sort view. Selecting a sort view will exit -tree view. -.TP -.B F6, <, > -Selects a field for sorting, also accessible through < and >. -The current sort field is indicated by a highlight in the header. -.TP -.B F7, ] -Increase the selected process's priority (subtract from 'nice' value). -This can only be done by the superuser. -.TP -.B F8, [ -Decrease the selected process's priority (add to 'nice' value) -.TP -.B F9, k -"Kill" process: sends a signal which is selected in a menu, to one or a group -of processes. If processes were tagged, sends the signal to all tagged processes. -If none is tagged, sends to the currently selected process. -.TP -.B F10, q -Quit -.TP -.B I -Invert the sort order: if sort order is increasing, switch to decreasing, and -vice-versa. -.TP -.B +, \-, * -When in tree view mode, expand or collapse subtree. When a subtree is collapsed -a "+" sign shows to the left of the process name. -Pressing "*" will expand or collapse all children of PIDs without parents, so -typically PID 1 (init) and PID 2 (kthreadd on Linux, if kernel threads are shown). -.TP -.B a (on multiprocessor machines) -Set CPU affinity: mark which CPUs a process is allowed to use. -.TP -.B u -Show only processes owned by a specified user. -.TP -.B N -Sort by PID. -.TP -.B M -Sort by memory usage (top compatibility key). -.TP -.B P -Sort by processor usage (top compatibility key). -.TP -.B T -Sort by time (top compatibility key). -.TP -.B F -"Follow" process: if the sort order causes the currently selected process -to move in the list, make the selection bar follow it. This is useful for -monitoring a process: this way, you can keep a process always visible on -screen. When a movement key is used, "follow" loses effect. -.TP -.B K -Hide kernel threads: prevent the threads belonging the kernel to be -displayed in the process list. (This is a toggle key.) -.TP -.B H -Hide user threads: on systems that represent them differently than ordinary -processes (such as recent NPTL-based systems), this can hide threads from -userspace processes in the process list. (This is a toggle key.) -.TP -.B p -Show full paths to running programs, where applicable. (This is a toggle key.) -.TP -.B Z -Pause/resume process updates. -.TP -.B m -Merge exe, comm and cmdline, where applicable. (This is a toggle key.) -.TP -.B Ctrl-L -Refresh: redraw screen and recalculate values. -.TP -.B Numbers -PID search: type in process ID and the selection highlight will be moved to it. -.PD -.SH "COLUMNS" -The following columns can display data about each process. A value of '\-' in -all the rows indicates that a column is unsupported on your system, or -currently unimplemented in -.BR htop . -The names below are the ones used in the -"Available Columns" section of the setup screen. If a different name is -shown in -.BR htop 's -main screen, it is shown below in parenthesis. -.TP 5 -.B Command -The full command line of the process (i.e. program name and arguments). If the -option 'Merge exe, comm and cmdline in Command' (toggled by the 'm' key) is set, -and if readable, the executable path (/proc/[pid]/exe) and the command name -(/proc/[pid]/comm) are also shown merged with the command line. -.TP -.B Comm -The command name of the process obtained from /proc/[pid]/comm, if readable. -.TP -.B Exe -The abbreviated basename of the executable of the process, obtained from -/proc/[pid]/exe, if readable. htop is able to read this file on linux for ALL -the processes only if it has the capability CAP_SYS_PTRACE or root privileges. -.TP -.B PID -The process ID. -.TP -.B STATE (S) -The state of the process: - \fBS\fR for sleeping (idle) - \fBR\fR for running - \fBD\fR for disk sleep (uninterruptible) - \fBZ\fR for zombie (waiting for parent to read its exit status) - \fBT\fR for traced or suspended (e.g by SIGTSTP) - \fBW\fR for paging -.TP -.B PPID -The parent process ID. -.TP -.B PGRP -The process's group ID. -.TP -.B SESSION (SID) -The process's session ID. -.TP -.B TTY_NR (TTY) -The controlling terminal of the process. -.TP -.B TPGID -The process ID of the foreground process group of the controlling terminal. -.TP -.B MINFLT -The number of page faults happening in the main memory. -.TP -.B CMINFLT -The number of minor faults for the process's waited-for children (see MINFLT above). -.TP -.B MAJFLT -The number of page faults happening out of the main memory. -.TP -.B CMAJFLT -The number of major faults for the process's waited-for children (see MAJFLT above). -.TP -.B UTIME (UTIME+) -The user CPU time, which is the amount of time the process has spent executing -on the CPU in user mode (i.e. everything but system calls), measured in clock -ticks. -.TP -.B STIME (STIME+) -The system CPU time, which is the amount of time the kernel has spent -executing system calls on behalf of the process, measured in clock ticks. -.TP -.B CUTIME (CUTIME+) -The children's user CPU time, which is the amount of time the process's -waited-for children have spent executing in user mode (see UTIME above). -.TP -.B CSTIME (CSTIME+) -The children's system CPU time, which is the amount of time the kernel has spent -executing system calls on behalf of all the process's waited-for children (see -STIME above). -.TP -.B PRIORITY (PRI) -The kernel's internal priority for the process, usually just its nice value -plus twenty. Different for real-time processes. -.TP -.B NICE (NI) -The nice value of a process, from 19 (low priority) to -20 (high priority). A -high value means the process is being nice, letting others have a higher -relative priority. The usual OS permission restrictions for adjusting priority apply. -.TP -.B STARTTIME (START) -The time the process was started. -.TP -.B PROCESSOR (CPU) -The ID of the CPU the process last executed on. -.TP -.B M_VIRT (VIRT) -The size of the virtual memory of the process. -.TP -.B M_RESIDENT (RES) -The resident set size (text + data + stack) of the process (i.e. the size of the -process's used physical memory). -.TP -.B M_SHARE (SHR) -The size of the process's shared pages. -.TP -.B M_TRS (CODE) -The text resident set size of the process (i.e. the size of the process's -executable instructions). -.TP -.B M_DRS (DATA) -The data resident set size (data + stack) of the process (i.e. the size of anything -except the process's executable instructions). -.TP -.B M_LRS (LIB) -The library size of the process. -.TP -.B M_DT (DIRTY) -The size of the dirty pages of the process. -.TP -.B M_SWAP (SWAP) -The size of the process's swapped pages. -.TP -.B M_PSS (PSS) -The proportional set size, same as M_RESIDENT but each page is divided by the -number of processes sharing it. -.TP -.B M_M_PSSWP (PSSWP) -The proportional swap share of this mapping, unlike M_SWAP this does not take -into account swapped out page of underlying shmem objects. -.TP -.B ST_UID (UID) -The user ID of the process owner. -.TP -.B PERCENT_CPU (CPU%) -The percentage of the CPU time that the process is currently using. -This is the default way to represent CPU usage in Linux. Each process can -consume up to 100% which means the full capacity of the core it is running -on. This is sometimes called "Irix mode" e.g. in -.BR top (1). -.TP -.B PERCENT_NORM_CPU (NCPU%) -The percentage of the CPU time that the process is currently using normalized -by CPU count. This is sometimes called "Solaris mode" e.g. in -.BR top (1). -.TP -.B PERCENT_MEM (MEM%) -The percentage of memory the process is currently using (based on the process's -resident memory size, see M_RESIDENT above). -.TP -.B USER -The username of the process owner, or the user ID if the name can't be -determined. -.TP -.B TIME (TIME+) -The time, measured in clock ticks that the process has spent in user and system -time (see UTIME, STIME above). -.TP -.B NLWP -The number of Light-Weight Processes (=threads) in the process. -.TP -.B TGID -The thread group ID. -.TP -.B CTID -OpenVZ container ID, a.k.a virtual environment ID. -.TP -.B VPID -OpenVZ process ID. -.TP -.B VXID -VServer process ID. -.TP -.B RCHAR (RD_CHAR) -The number of bytes the process has read. -.TP -.B WCHAR (WR_CHAR) -The number of bytes the process has written. -.TP -.B SYSCR (RD_SYSC) -The number of read(2) syscalls for the process. -.TP -.B SYSCW (WR_SYSC) -The number of write(2) syscalls for the process. -.TP -.B RBYTES (IO_RBYTES) -Bytes of read(2) I/O for the process. -.TP -.B WBYTES (IO_WBYTES) -Bytes of write(2) I/O for the process. -.TP -.B CNCLWB (IO_CANCEL) -Bytes of cancelled write(2) I/O. -.TP -.B IO_READ_RATE (DISK READ) -The I/O rate of read(2) in bytes per second, for the process. -.TP -.B IO_WRITE_RATE (DISK WRITE) -The I/O rate of write(2) in bytes per second, for the process. -.TP -.B IO_RATE (DISK R/W) -The I/O rate, IO_READ_RATE + IO_WRITE_RATE (see above). -.TP -.B CGROUP -Which cgroup the process is in. -.TP -.B OOM -OOM killer score. -.TP -.B CTXT -Incremental sum of voluntary and nonvoluntary context switches. -.TP -.B IO_PRIORITY (IO) -The I/O scheduling class followed by the priority if the class supports it: - \fBR\fR for Realtime - \fBB\fR for Best-effort - \fBid\fR for Idle -.TP -.B PERCENT_CPU_DELAY (CPUD%) -The percentage of time spent waiting for a CPU (while runnable). Requires CAP_NET_ADMIN. -.TP -.B PERCENT_IO_DELAY (IOD%) -The percentage of time spent waiting for the completion of synchronous block I/O. Requires CAP_NET_ADMIN. -.TP -.B PERCENT_SWAP_DELAY (SWAPD%) -The percentage of time spent swapping in pages. Requires CAP_NET_ADMIN. -.TP -.B COMM -The command name for the process. Requires Linux kernel 2.6.33 or newer. -.TP -.B EXE -The executable file of the process as reported by the kernel. Requires CAP_SYS_PTRACE and PTRACE_MODE_READ_FSCRED. -.TP -.B All other flags -Currently unsupported (always displays '-'). -.SH "CONFIG FILE" -By default -.B htop -reads its configuration from the XDG-compliant path -.IR ~/.config/htop/htoprc . -The configuration file is overwritten by -.BR htop 's -in-program Setup configuration, so it should not be hand-edited. -If no user configuration exists -.B htop -tries to read the system-wide configuration from -.I @sysconfdir@/htoprc -and as a last resort, falls back to its hard coded defaults. -.LP -You may override the location of the configuration file using the $HTOPRC -environment variable (so you can have multiple configurations for different -machines that share the same home directory, for example). -.SH "MEMORY SIZES" -Memory sizes in -.B htop -are displayed in a human-readable form. -Sizes are printed in powers of 1024. (e.g., 1023M = 1072693248 Bytes) -.LP -The decision to use this convention was made in order to conserve screen -space and make memory size representations consistent throughout -.BR htop . -.SH "SEE ALSO" -.BR proc (5), -.BR top (1), -.BR free (1), -.BR ps (1), -.BR uptime (1) -and -.BR limits.conf (5). -.SH "AUTHORS" -.B htop -was originally developed by Hisham Muhammad. -Nowadays it is maintained by the community at . diff -Nru pcp-5.3.1/src/pcp/htop/IncSet.c pcp-5.3.2/src/pcp/htop/IncSet.c --- pcp-5.3.1/src/pcp/htop/IncSet.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/IncSet.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,234 +0,0 @@ -/* -htop - IncSet.c -(C) 2005-2012 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "IncSet.h" - -#include -#include -#include - -#include "CRT.h" -#include "ListItem.h" -#include "Object.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static void IncMode_reset(IncMode* mode) { - mode->index = 0; - mode->buffer[0] = 0; -} - -void IncSet_reset(IncSet* this, IncType type) { - IncMode_reset(&this->modes[type]); -} - -void IncSet_setFilter(IncSet* this, const char* filter) { - IncMode* mode = &this->modes[INC_FILTER]; - size_t len = String_safeStrncpy(mode->buffer, filter, sizeof(mode->buffer)); - mode->index = len; - this->filtering = true; -} - -static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL}; -static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "}; -static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR}; - -static inline void IncMode_initSearch(IncMode* search) { - memset(search, 0, sizeof(IncMode)); - search->bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents); - search->isFilter = false; -} - -static const char* const filterFunctions[] = {"Done ", "Clear ", " Filter: ", NULL}; -static const char* const filterKeys[] = {"Enter", "Esc", " "}; -static const int filterEvents[] = {13, 27, ERR}; - -static inline void IncMode_initFilter(IncMode* filter) { - memset(filter, 0, sizeof(IncMode)); - filter->bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents); - filter->isFilter = true; -} - -static inline void IncMode_done(IncMode* mode) { - FunctionBar_delete(mode->bar); -} - -IncSet* IncSet_new(FunctionBar* bar) { - IncSet* this = xMalloc(sizeof(IncSet)); - IncMode_initSearch(&(this->modes[INC_SEARCH])); - IncMode_initFilter(&(this->modes[INC_FILTER])); - this->active = NULL; - this->defaultBar = bar; - this->filtering = false; - this->found = false; - return this; -} - -void IncSet_delete(IncSet* this) { - IncMode_done(&(this->modes[0])); - IncMode_done(&(this->modes[1])); - free(this); -} - -static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) { - const Object* selected = Panel_getSelected(panel); - Panel_prune(panel); - if (this->filtering) { - int n = 0; - const char* incFilter = this->modes[INC_FILTER].buffer; - for (int i = 0; i < Vector_size(lines); i++) { - ListItem* line = (ListItem*)Vector_get(lines, i); - if (String_contains_i(line->value, incFilter)) { - Panel_add(panel, (Object*)line); - if (selected == (Object*)line) { - Panel_setSelected(panel, n); - } - - n++; - } - } - } else { - for (int i = 0; i < Vector_size(lines); i++) { - Object* line = Vector_get(lines, i); - Panel_add(panel, line); - if (selected == line) { - Panel_setSelected(panel, i); - } - } - } -} - -static bool search(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) { - int size = Panel_size(panel); - for (int i = 0; i < size; i++) { - if (String_contains_i(getPanelValue(panel, i), mode->buffer)) { - Panel_setSelected(panel, i); - return true; - } - } - - return false; -} - -static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue, int step) { - int size = Panel_size(panel); - int here = Panel_getSelectedIndex(panel); - int i = here; - for (;;) { - i += step; - if (i == size) { - i = 0; - } - if (i == -1) { - i = size - 1; - } - if (i == here) { - return false; - } - - if (String_contains_i(getPanelValue(panel, i), mode->buffer)) { - Panel_setSelected(panel, i); - return true; - } - } -} - -bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) { - if (ch == ERR) - return true; - - IncMode* mode = this->active; - int size = Panel_size(panel); - bool filterChanged = false; - bool doSearch = true; - if (ch == KEY_F(3) || ch == KEY_F(15)) { - if (size == 0) - return true; - - IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1); - doSearch = false; - } else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) { - if (mode->index < INCMODE_MAX) { - mode->buffer[mode->index] = ch; - mode->index++; - mode->buffer[mode->index] = 0; - if (mode->isFilter) { - filterChanged = true; - if (mode->index == 1) { - this->filtering = true; - } - } - } - } else if (ch == KEY_BACKSPACE || ch == 127) { - if (mode->index > 0) { - mode->index--; - mode->buffer[mode->index] = 0; - if (mode->isFilter) { - filterChanged = true; - if (mode->index == 0) { - this->filtering = false; - IncMode_reset(mode); - } - } - } else { - doSearch = false; - } - } else if (ch == KEY_RESIZE) { - doSearch = (mode->index > 0); - } else { - if (mode->isFilter) { - filterChanged = true; - if (ch == 27) { - this->filtering = false; - IncMode_reset(mode); - } - } else { - if (ch == 27) { - IncMode_reset(mode); - } - } - this->active = NULL; - Panel_setDefaultBar(panel); - doSearch = false; - } - if (doSearch) { - this->found = search(mode, panel, getPanelValue); - } - if (filterChanged && lines) { - updateWeakPanel(this, panel, lines); - } - return filterChanged; -} - -const char* IncSet_getListItemValue(Panel* panel, int i) { - const ListItem* l = (const ListItem*) Panel_get(panel, i); - return l ? l->value : ""; -} - -void IncSet_activate(IncSet* this, IncType type, Panel* panel) { - this->active = &(this->modes[type]); - panel->currentBar = this->active->bar; -} - -void IncSet_drawBar(const IncSet* this) { - if (this->active) { - FunctionBar_drawExtra(this->active->bar, this->active->buffer, (this->active->isFilter || this->found) ? -1 : CRT_colors[FAILED_SEARCH], true); - } else { - FunctionBar_draw(this->defaultBar); - } -} - -int IncSet_synthesizeEvent(IncSet* this, int x) { - if (this->active) { - return FunctionBar_synthesizeEvent(this->active->bar, x); - } else { - return FunctionBar_synthesizeEvent(this->defaultBar, x); - } -} diff -Nru pcp-5.3.1/src/pcp/htop/IncSet.h pcp-5.3.2/src/pcp/htop/IncSet.h --- pcp-5.3.1/src/pcp/htop/IncSet.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/IncSet.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -#ifndef HEADER_IncSet -#define HEADER_IncSet -/* -htop - IncSet.h -(C) 2005-2012 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include -#include - -#include "FunctionBar.h" -#include "Panel.h" -#include "Vector.h" - -#define INCMODE_MAX 40 - -typedef enum { - INC_SEARCH = 0, - INC_FILTER = 1 -} IncType; - -typedef struct IncMode_ { - char buffer[INCMODE_MAX + 1]; - int index; - FunctionBar* bar; - bool isFilter; -} IncMode; - -typedef struct IncSet_ { - IncMode modes[2]; - IncMode* active; - FunctionBar* defaultBar; - bool filtering; - bool found; -} IncSet; - -static inline const char* IncSet_filter(const IncSet* this) { - return this->filtering ? this->modes[INC_FILTER].buffer : NULL; -} - -void IncSet_setFilter(IncSet* this, const char* filter); - -typedef const char* (*IncMode_GetPanelValue)(Panel*, int); - -void IncSet_reset(IncSet* this, IncType type); - -IncSet* IncSet_new(FunctionBar* bar); - -void IncSet_delete(IncSet* this); - -bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines); - -const char* IncSet_getListItemValue(Panel* panel, int i); - -void IncSet_activate(IncSet* this, IncType type, Panel* panel); - -void IncSet_drawBar(const IncSet* this); - -int IncSet_synthesizeEvent(IncSet* this, int x); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/InfoScreen.c pcp-5.3.2/src/pcp/htop/InfoScreen.c --- pcp-5.3.1/src/pcp/htop/InfoScreen.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/InfoScreen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -#include "config.h" // IWYU pragma: keep - -#include "InfoScreen.h" - -#include -#include -#include -#include - -#include "CRT.h" -#include "IncSet.h" -#include "ListItem.h" -#include "Object.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; - -static const char* const InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"}; - -static const int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; - -InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader) { - this->process = process; - if (!bar) { - bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents); - } - this->display = Panel_new(0, 1, COLS, height, Class(ListItem), false, bar); - this->inc = IncSet_new(bar); - this->lines = Vector_new(Vector_type(this->display->items), true, DEFAULT_SIZE); - Panel_setHeader(this->display, panelHeader); - return this; -} - -InfoScreen* InfoScreen_done(InfoScreen* this) { - Panel_delete((Object*)this->display); - IncSet_delete(this->inc); - Vector_delete(this->lines); - return this; -} - -void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - - char title[COLS + 1]; - int len = vsnprintf(title, sizeof(title), fmt, ap); - va_end(ap); - - if (len > COLS) { - memset(&title[COLS - 3], '.', 3); - } - - attrset(CRT_colors[METER_TEXT]); - mvhline(0, 0, ' ', COLS); - mvaddstr(0, 0, title); - attrset(CRT_colors[DEFAULT_COLOR]); - Panel_draw(this->display, true, true, true, false); - - IncSet_drawBar(this->inc); -} - -void InfoScreen_addLine(InfoScreen* this, const char* line) { - Vector_add(this->lines, (Object*) ListItem_new(line, 0)); - const char* incFilter = IncSet_filter(this->inc); - if (!incFilter || String_contains_i(line, incFilter)) { - Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines) - 1)); - } -} - -void InfoScreen_appendLine(InfoScreen* this, const char* line) { - ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1); - ListItem_append(last, line); - const char* incFilter = IncSet_filter(this->inc); - if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter)) { - Panel_add(this->display, (Object*)last); - } -} - -void InfoScreen_run(InfoScreen* this) { - Panel* panel = this->display; - - if (As_InfoScreen(this)->scan) - InfoScreen_scan(this); - - InfoScreen_draw(this); - - bool looping = true; - while (looping) { - - Panel_draw(panel, false, true, true, false); - IncSet_drawBar(this->inc); - - if (this->inc->active) { - (void) move(LINES - 1, CRT_cursorX); - } - set_escdelay(25); - int ch = getch(); - - if (ch == ERR) { - if (As_InfoScreen(this)->onErr) { - InfoScreen_onErr(this); - continue; - } - } - - if (ch == KEY_MOUSE) { - MEVENT mevent; - int ok = getmouse(&mevent); - if (ok == OK) { - if (mevent.bstate & BUTTON1_RELEASED) { - if (mevent.y >= panel->y && mevent.y < LINES - 1) { - Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1); - ch = 0; - } else if (mevent.y == LINES - 1) { - ch = IncSet_synthesizeEvent(this->inc, mevent.x); - } - } - #if NCURSES_MOUSE_VERSION > 1 - else if (mevent.bstate & BUTTON4_PRESSED) { - ch = KEY_WHEELUP; - } else if (mevent.bstate & BUTTON5_PRESSED) { - ch = KEY_WHEELDOWN; - } - #endif - } - } - - if (this->inc->active) { - IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines); - continue; - } - - switch(ch) { - case ERR: - continue; - case KEY_F(3): - case '/': - IncSet_activate(this->inc, INC_SEARCH, panel); - break; - case KEY_F(4): - case '\\': - IncSet_activate(this->inc, INC_FILTER, panel); - break; - case KEY_F(5): - clear(); - if (As_InfoScreen(this)->scan) { - Vector_prune(this->lines); - InfoScreen_scan(this); - } - - InfoScreen_draw(this); - break; - case '\014': // Ctrl+L - clear(); - InfoScreen_draw(this); - break; - case 27: - case 'q': - case KEY_F(10): - looping = false; - break; - case KEY_RESIZE: - Panel_resize(panel, COLS, LINES - 2); - if (As_InfoScreen(this)->scan) { - Vector_prune(this->lines); - InfoScreen_scan(this); - } - - InfoScreen_draw(this); - break; - default: - if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) { - continue; - } - Panel_onKey(panel, ch); - } - } -} diff -Nru pcp-5.3.1/src/pcp/htop/InfoScreen.h pcp-5.3.2/src/pcp/htop/InfoScreen.h --- pcp-5.3.1/src/pcp/htop/InfoScreen.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/InfoScreen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -#ifndef HEADER_InfoScreen -#define HEADER_InfoScreen - -#include - -#include "FunctionBar.h" -#include "IncSet.h" -#include "Macros.h" -#include "Object.h" -#include "Panel.h" -#include "Process.h" -#include "Vector.h" - - -typedef struct InfoScreen_ { - Object super; - const Process* process; - Panel* display; - IncSet* inc; - Vector* lines; -} InfoScreen; - -typedef void(*InfoScreen_Scan)(InfoScreen*); -typedef void(*InfoScreen_Draw)(InfoScreen*); -typedef void(*InfoScreen_OnErr)(InfoScreen*); -typedef bool(*InfoScreen_OnKey)(InfoScreen*, int); - -typedef struct InfoScreenClass_ { - const ObjectClass super; - const InfoScreen_Scan scan; - const InfoScreen_Draw draw; - const InfoScreen_OnErr onErr; - const InfoScreen_OnKey onKey; -} InfoScreenClass; - -#define As_InfoScreen(this_) ((const InfoScreenClass*)(((InfoScreen*)(this_))->super.klass)) -#define InfoScreen_scan(this_) As_InfoScreen(this_)->scan((InfoScreen*)(this_)) -#define InfoScreen_draw(this_) As_InfoScreen(this_)->draw((InfoScreen*)(this_)) -#define InfoScreen_onErr(this_) As_InfoScreen(this_)->onErr((InfoScreen*)(this_)) -#define InfoScreen_onKey(this_, ch_) As_InfoScreen(this_)->onKey((InfoScreen*)(this_), ch_) - -InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader); - -InfoScreen* InfoScreen_done(InfoScreen* this); - -ATTR_FORMAT(printf, 2, 3) -void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...); - -void InfoScreen_addLine(InfoScreen* this, const char* line); - -void InfoScreen_appendLine(InfoScreen* this, const char* line); - -void InfoScreen_run(InfoScreen* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/linux/PressureStallMeter.c pcp-5.3.2/src/pcp/htop/linux/PressureStallMeter.c --- pcp-5.3.1/src/pcp/htop/linux/PressureStallMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/linux/PressureStallMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -/* -htop - PressureStallMeter.c -(C) 2004-2011 Hisham H. Muhammad -(C) 2019 Ran Benita -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "PressureStallMeter.h" - -#include -#include - -#include "CRT.h" -#include "Meter.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" -#include "XUtils.h" - - -static const int PressureStallMeter_attributes[] = { - PRESSURE_STALL_TEN, - PRESSURE_STALL_SIXTY, - PRESSURE_STALL_THREEHUNDRED -}; - -static void PressureStallMeter_updateValues(Meter* this) { - const char* file; - if (strstr(Meter_name(this), "CPU")) { - file = "cpu"; - } else if (strstr(Meter_name(this), "IO")) { - file = "io"; - } else { - file = "memory"; - } - - bool some; - if (strstr(Meter_name(this), "Some")) { - some = true; - } else { - some = false; - } - - Platform_getPressureStall(file, some, &this->values[0], &this->values[1], &this->values[2]); - - /* only print bar for ten (not sixty and threehundred), cause the sum is meaningless */ - this->curItems = 1; - - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s %s %5.2lf%% %5.2lf%% %5.2lf%%", some ? "some" : "full", file, this->values[0], this->values[1], this->values[2]); -} - -static void PressureStallMeter_display(const Object* cast, RichString* out) { - const Meter* this = (const Meter*)cast; - char buffer[20]; - xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[0]); - RichString_writeAscii(out, CRT_colors[PRESSURE_STALL_TEN], buffer); - xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[1]); - RichString_appendAscii(out, CRT_colors[PRESSURE_STALL_SIXTY], buffer); - xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[2]); - RichString_appendAscii(out, CRT_colors[PRESSURE_STALL_THREEHUNDRED], buffer); -} - -const MeterClass PressureStallCPUSomeMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = PressureStallMeter_display, - }, - .updateValues = PressureStallMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 3, - .total = 100.0, - .attributes = PressureStallMeter_attributes, - .name = "PressureStallCPUSome", - .uiName = "PSI some CPU", - .caption = "PSI some CPU: ", - .description = "Pressure Stall Information, some cpu" -}; - -const MeterClass PressureStallIOSomeMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = PressureStallMeter_display, - }, - .updateValues = PressureStallMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 3, - .total = 100.0, - .attributes = PressureStallMeter_attributes, - .name = "PressureStallIOSome", - .uiName = "PSI some IO", - .caption = "PSI some IO: ", - .description = "Pressure Stall Information, some io" -}; - -const MeterClass PressureStallIOFullMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = PressureStallMeter_display, - }, - .updateValues = PressureStallMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 3, - .total = 100.0, - .attributes = PressureStallMeter_attributes, - .name = "PressureStallIOFull", - .uiName = "PSI full IO", - .caption = "PSI full IO: ", - .description = "Pressure Stall Information, full io" -}; - -const MeterClass PressureStallMemorySomeMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = PressureStallMeter_display, - }, - .updateValues = PressureStallMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 3, - .total = 100.0, - .attributes = PressureStallMeter_attributes, - .name = "PressureStallMemorySome", - .uiName = "PSI some memory", - .caption = "PSI some memory: ", - .description = "Pressure Stall Information, some memory" -}; - -const MeterClass PressureStallMemoryFullMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = PressureStallMeter_display, - }, - .updateValues = PressureStallMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 3, - .total = 100.0, - .attributes = PressureStallMeter_attributes, - .name = "PressureStallMemoryFull", - .uiName = "PSI full memory", - .caption = "PSI full memory: ", - .description = "Pressure Stall Information, full memory" -}; diff -Nru pcp-5.3.1/src/pcp/htop/linux/PressureStallMeter.h pcp-5.3.2/src/pcp/htop/linux/PressureStallMeter.h --- pcp-5.3.1/src/pcp/htop/linux/PressureStallMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/linux/PressureStallMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -/* Do not edit this file. It was automatically generated. */ - -#ifndef HEADER_PressureStallMeter -#define HEADER_PressureStallMeter -/* -htop - PressureStallMeter.h -(C) 2004-2011 Hisham H. Muhammad -(C) 2019 Ran Benita -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass PressureStallCPUSomeMeter_class; - -extern const MeterClass PressureStallIOSomeMeter_class; - -extern const MeterClass PressureStallIOFullMeter_class; - -extern const MeterClass PressureStallMemorySomeMeter_class; - -extern const MeterClass PressureStallMemoryFullMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/linux/ZramMeter.c pcp-5.3.2/src/pcp/htop/linux/ZramMeter.c --- pcp-5.3.1/src/pcp/htop/linux/ZramMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/linux/ZramMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -#include "ZramMeter.h" - -#include "CRT.h" -#include "Meter.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" - - -static const int ZramMeter_attributes[] = { - ZRAM -}; - -static void ZramMeter_updateValues(Meter* this) { - char* buffer = this->txtBuffer; - size_t size = sizeof(this->txtBuffer); - int written; - - Platform_setZramValues(this); - - /* on print bar for compressed data size, not uncompressed */ - this->curItems = 1; - - written = Meter_humanUnit(buffer, this->values[0], size); - METER_BUFFER_CHECK(buffer, size, written); - - METER_BUFFER_APPEND_CHR(buffer, size, '('); - - written = Meter_humanUnit(buffer, this->values[1], size); - METER_BUFFER_CHECK(buffer, size, written); - - METER_BUFFER_APPEND_CHR(buffer, size, ')'); - - METER_BUFFER_APPEND_CHR(buffer, size, '/'); - - Meter_humanUnit(buffer, this->total, size); -} - -static void ZramMeter_display(const Object* cast, RichString* out) { - char buffer[50]; - const Meter* this = (const Meter*)cast; - - RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); - - Meter_humanUnit(buffer, this->total, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - - Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - - Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " uncompressed:"); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); -} - -const MeterClass ZramMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = ZramMeter_display, - }, - .updateValues = ZramMeter_updateValues, - .defaultMode = BAR_METERMODE, - .maxItems = 2, - .total = 100.0, - .attributes = ZramMeter_attributes, - .name = "Zram", - .uiName = "Zram", - .caption = "zrm" -}; diff -Nru pcp-5.3.1/src/pcp/htop/linux/ZramMeter.h pcp-5.3.2/src/pcp/htop/linux/ZramMeter.h --- pcp-5.3.1/src/pcp/htop/linux/ZramMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/linux/ZramMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#ifndef HEADER_ZramMeter -#define HEADER_ZramMeter - -#include "Meter.h" - -extern const MeterClass ZramMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/linux/ZramStats.h pcp-5.3.2/src/pcp/htop/linux/ZramStats.h --- pcp-5.3.1/src/pcp/htop/linux/ZramStats.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/linux/ZramStats.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#ifndef HEADER_ZramStats -#define HEADER_ZramStats - -typedef struct ZramStats_ { - memory_t totalZram; - memory_t usedZramComp; - memory_t usedZramOrig; -} ZramStats; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ListItem.c pcp-5.3.2/src/pcp/htop/ListItem.c --- pcp-5.3.1/src/pcp/htop/ListItem.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ListItem.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* -htop - ListItem.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "ListItem.h" - -#include -#include -#include - -#include "CRT.h" -#include "RichString.h" -#include "XUtils.h" - - -static void ListItem_delete(Object* cast) { - ListItem* this = (ListItem*)cast; - free(this->value); - free(this); -} - -static void ListItem_display(const Object* cast, RichString* out) { - const ListItem* const this = (const ListItem*)cast; - assert (this != NULL); - - if (this->moving) { - RichString_writeWide(out, CRT_colors[DEFAULT_COLOR], -#ifdef HAVE_LIBNCURSESW - CRT_utf8 ? "↕ " : -#endif - "+ "); - } - RichString_appendWide(out, CRT_colors[DEFAULT_COLOR], this->value); -} - -ListItem* ListItem_new(const char* value, int key) { - ListItem* this = AllocThis(ListItem); - this->value = xStrdup(value); - this->key = key; - this->moving = false; - return this; -} - -void ListItem_append(ListItem* this, const char* text) { - size_t oldLen = strlen(this->value); - size_t textLen = strlen(text); - size_t newLen = oldLen + textLen; - this->value = xRealloc(this->value, newLen + 1); - memcpy(this->value + oldLen, text, textLen); - this->value[newLen] = '\0'; -} - -static int ListItem_compare(const void* cast1, const void* cast2) { - const ListItem* obj1 = (const ListItem*) cast1; - const ListItem* obj2 = (const ListItem*) cast2; - return strcmp(obj1->value, obj2->value); -} - -const ObjectClass ListItem_class = { - .display = ListItem_display, - .delete = ListItem_delete, - .compare = ListItem_compare -}; diff -Nru pcp-5.3.1/src/pcp/htop/ListItem.h pcp-5.3.2/src/pcp/htop/ListItem.h --- pcp-5.3.1/src/pcp/htop/ListItem.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ListItem.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -#ifndef HEADER_ListItem -#define HEADER_ListItem -/* -htop - ListItem.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "Object.h" - -typedef struct ListItem_ { - Object super; - char* value; - int key; - bool moving; -} ListItem; - -extern const ObjectClass ListItem_class; - -ListItem* ListItem_new(const char* value, int key); - -void ListItem_append(ListItem* this, const char* text); - -static inline const char* ListItem_getRef(const ListItem* this) { - return this->value; -} - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/LoadAverageMeter.c pcp-5.3.2/src/pcp/htop/LoadAverageMeter.c --- pcp-5.3.1/src/pcp/htop/LoadAverageMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/LoadAverageMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -/* -htop - LoadAverageMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "LoadAverageMeter.h" - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" -#include "XUtils.h" - - -static const int LoadAverageMeter_attributes[] = { - LOAD_AVERAGE_ONE, - LOAD_AVERAGE_FIVE, - LOAD_AVERAGE_FIFTEEN -}; - -static const int LoadMeter_attributes[] = { - LOAD -}; - -static const int OK_attributes[] = { - METER_VALUE_OK -}; - -static const int Medium_attributes[] = { - METER_VALUE_WARN -}; - -static const int High_attributes[] = { - METER_VALUE_ERROR -}; - -static void LoadAverageMeter_updateValues(Meter* this) { - Platform_getLoadAverage(&this->values[0], &this->values[1], &this->values[2]); - - // only show bar for 1min value - this->curItems = 1; - - // change bar color and total based on value - if (this->values[0] < 1.0) { - this->curAttributes = OK_attributes; - this->total = 1.0; - } else if (this->values[0] < this->pl->cpuCount) { - this->curAttributes = Medium_attributes; - this->total = this->pl->cpuCount; - } else { - this->curAttributes = High_attributes; - this->total = 2 * this->pl->cpuCount; - } - - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.2f/%.2f/%.2f", this->values[0], this->values[1], this->values[2]); -} - -static void LoadAverageMeter_display(const Object* cast, RichString* out) { - const Meter* this = (const Meter*)cast; - char buffer[20]; - xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[0]); - RichString_writeAscii(out, CRT_colors[LOAD_AVERAGE_ONE], buffer); - xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[1]); - RichString_appendAscii(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer); - xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[2]); - RichString_appendAscii(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer); -} - -static void LoadMeter_updateValues(Meter* this) { - double five, fifteen; - Platform_getLoadAverage(&this->values[0], &five, &fifteen); - - // change bar color and total based on value - if (this->values[0] < 1.0) { - this->curAttributes = OK_attributes; - this->total = 1.0; - } else if (this->values[0] < this->pl->cpuCount) { - this->curAttributes = Medium_attributes; - this->total = this->pl->cpuCount; - } else { - this->curAttributes = High_attributes; - this->total = 2 * this->pl->cpuCount; - } - - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.2f", this->values[0]); -} - -static void LoadMeter_display(const Object* cast, RichString* out) { - const Meter* this = (const Meter*)cast; - char buffer[20]; - xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[0]); - RichString_writeAscii(out, CRT_colors[LOAD], buffer); -} - -const MeterClass LoadAverageMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = LoadAverageMeter_display, - }, - .updateValues = LoadAverageMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 3, - .total = 100.0, - .attributes = LoadAverageMeter_attributes, - .name = "LoadAverage", - .uiName = "Load average", - .description = "Load averages: 1 minute, 5 minutes, 15 minutes", - .caption = "Load average: " -}; - -const MeterClass LoadMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = LoadMeter_display, - }, - .updateValues = LoadMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 100.0, - .attributes = LoadMeter_attributes, - .name = "Load", - .uiName = "Load", - .description = "Load: average of ready processes in the last minute", - .caption = "Load: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/LoadAverageMeter.h pcp-5.3.2/src/pcp/htop/LoadAverageMeter.h --- pcp-5.3.1/src/pcp/htop/LoadAverageMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/LoadAverageMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#ifndef HEADER_LoadAverageMeter -#define HEADER_LoadAverageMeter -/* -htop - LoadAverageMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass LoadAverageMeter_class; - -extern const MeterClass LoadMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Macros.h pcp-5.3.2/src/pcp/htop/Macros.h --- pcp-5.3.1/src/pcp/htop/Macros.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Macros.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -#ifndef HEADER_Macros -#define HEADER_Macros - -#include // IWYU pragma: keep - -#ifndef MINIMUM -#define MINIMUM(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef MAXIMUM -#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef CLAMP -#define CLAMP(x, low, high) (assert((low) <= (high)), ((x) > (high)) ? (high) : MAXIMUM(x, low)) -#endif - -#ifndef ARRAYSIZE -#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - -#ifndef SPACESHIP_NUMBER -#define SPACESHIP_NUMBER(a, b) (((a) > (b)) - ((a) < (b))) -#endif - -#ifndef SPACESHIP_NULLSTR -#define SPACESHIP_NULLSTR(a, b) strcmp((a) ? (a) : "", (b) ? (b) : "") -#endif - -#ifdef __GNUC__ // defined by GCC and Clang - -#define ATTR_FORMAT(type, index, check) __attribute__((format (type, index, check))) -#define ATTR_NONNULL __attribute__((nonnull)) -#define ATTR_NORETURN __attribute__((noreturn)) -#define ATTR_UNUSED __attribute__((unused)) -#define ATTR_ALLOC_SIZE1(a) __attribute__((alloc_size (a))) -#define ATTR_ALLOC_SIZE2(a, b) __attribute__((alloc_size (a, b))) -#define ATTR_MALLOC __attribute__((malloc)) - -#else /* __GNUC__ */ - -#define ATTR_FORMAT(type, index, check) -#define ATTR_NONNULL -#define ATTR_NORETURN -#define ATTR_UNUSED -#define ATTR_ALLOC_SIZE1(a) -#define ATTR_ALLOC_SIZE2(a, b) -#define ATTR_MALLOC - -#endif /* __GNUC__ */ - -// ignore casts discarding const specifier, e.g. -// const char [] -> char * / void * -// const char *[2]' -> char *const * -#if defined(__clang__) -#define IGNORE_WCASTQUAL_BEGIN _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#define IGNORE_WCASTQUAL_END _Pragma("clang diagnostic pop") -#elif defined(__GNUC__) -#define IGNORE_WCASTQUAL_BEGIN _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#define IGNORE_WCASTQUAL_END _Pragma("GCC diagnostic pop") -#else -#define IGNORE_WCASTQUAL_BEGIN -#define IGNORE_WCASTQUAL_END -#endif - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/MainPanel.c pcp-5.3.2/src/pcp/htop/MainPanel.c --- pcp-5.3.1/src/pcp/htop/MainPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/MainPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -/* -htop - ColumnsPanel.c -(C) 2004-2015 Hisham H. Muhammad -(C) 2020 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "MainPanel.h" - -#include -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "Platform.h" -#include "Process.h" -#include "ProcessList.h" -#include "ProvideCurses.h" -#include "Settings.h" -#include "XUtils.h" - - -static const char* const MainFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL}; - -void MainPanel_updateTreeFunctions(MainPanel* this, bool mode) { - FunctionBar* bar = MainPanel_getFunctionBar(this); - FunctionBar_setLabel(bar, KEY_F(5), mode ? "List " : "Tree "); -} - -void MainPanel_pidSearch(MainPanel* this, int ch) { - Panel* super = (Panel*) this; - pid_t pid = ch - 48 + this->pidSearch; - for (int i = 0; i < Panel_size(super); i++) { - const Process* p = (const Process*) Panel_get(super, i); - if (p && p->pid == pid) { - Panel_setSelected(super, i); - break; - } - } - this->pidSearch = pid * 10; - if (this->pidSearch > 10000000) { - this->pidSearch = 0; - } -} - -static const char* MainPanel_getValue(Panel* this, int i) { - const Process* p = (const Process*) Panel_get(this, i); - return Process_getCommand(p); -} - -static HandlerResult MainPanel_eventHandler(Panel* super, int ch) { - MainPanel* this = (MainPanel*) super; - - HandlerResult result = IGNORED; - - Htop_Reaction reaction = HTOP_OK; - - /* Let supervising ScreenManager handle resize */ - if (ch == KEY_RESIZE) - return IGNORED; - - /* reset on every normal key */ - if (ch != ERR) - this->state->hideProcessSelection = false; - - if (EVENT_IS_HEADER_CLICK(ch)) { - int x = EVENT_HEADER_CLICK_GET_X(ch); - const ProcessList* pl = this->state->pl; - Settings* settings = this->state->settings; - int hx = super->scrollH + x + 1; - ProcessField field = ProcessList_keyAt(pl, hx); - if (settings->treeView && settings->treeViewAlwaysByPID) { - settings->treeView = false; - settings->direction = 1; - reaction |= Action_setSortKey(settings, field); - } else if (field == Settings_getActiveSortKey(settings)) { - Settings_invertSortOrder(settings); - } else { - reaction |= Action_setSortKey(settings, field); - } - reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS; - result = HANDLED; - } else if (ch != ERR && this->inc->active) { - bool filterChanged = IncSet_handleKey(this->inc, ch, super, MainPanel_getValue, NULL); - if (filterChanged) { - this->state->pl->incFilter = IncSet_filter(this->inc); - reaction = HTOP_REFRESH | HTOP_REDRAW_BAR; - } - if (this->inc->found) { - reaction |= Action_follow(this->state); - reaction |= HTOP_KEEP_FOLLOWING; - } - result = HANDLED; - } else if (ch == 27) { - this->state->hideProcessSelection = true; - return HANDLED; - } else if (ch != ERR && ch > 0 && ch < KEY_MAX && this->keys[ch]) { - reaction |= (this->keys[ch])(this->state); - result = HANDLED; - } else if (0 < ch && ch < 255 && isdigit((unsigned char)ch)) { - MainPanel_pidSearch(this, ch); - } else { - if (ch != ERR) { - this->pidSearch = 0; - } else { - reaction |= HTOP_KEEP_FOLLOWING; - } - } - - if (reaction & HTOP_REDRAW_BAR) { - MainPanel_updateTreeFunctions(this, this->state->settings->treeView); - } - if (reaction & HTOP_UPDATE_PANELHDR) { - result |= REDRAW; - } - if (reaction & HTOP_REFRESH) { - result |= REFRESH; - } - if (reaction & HTOP_RECALCULATE) { - result |= RESCAN; - } - if (reaction & HTOP_SAVE_SETTINGS) { - this->state->settings->changed = true; - } - if (reaction & HTOP_QUIT) { - return BREAK_LOOP; - } - if (!(reaction & HTOP_KEEP_FOLLOWING)) { - this->state->pl->following = -1; - Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS); - } - return result; -} - -int MainPanel_selectedPid(MainPanel* this) { - const Process* p = (const Process*) Panel_getSelected((Panel*)this); - if (p) { - return p->pid; - } - return -1; -} - -bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged) { - Panel* super = (Panel*) this; - bool ok = true; - bool anyTagged = false; - for (int i = 0; i < Panel_size(super); i++) { - Process* p = (Process*) Panel_get(super, i); - if (p->tag) { - ok = fn(p, arg) && ok; - anyTagged = true; - } - } - if (!anyTagged) { - Process* p = (Process*) Panel_getSelected(super); - if (p) { - ok &= fn(p, arg); - } - } - - if (wasAnyTagged) - *wasAnyTagged = anyTagged; - - return ok; -} - -static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) { - MainPanel* this = (MainPanel*) super; - - // Do not hide active search and filter bar. - if (hideFunctionBar && !this->inc->active) - return; - - IncSet_drawBar(this->inc); - if (this->state->pauseProcessUpdate) { - FunctionBar_append("PAUSED", CRT_colors[PAUSED]); - } -} - -static void MainPanel_printHeader(Panel* super) { - MainPanel* this = (MainPanel*) super; - ProcessList_printHeader(this->state->pl, &super->header); -} - -const PanelClass MainPanel_class = { - .super = { - .extends = Class(Panel), - .delete = MainPanel_delete - }, - .eventHandler = MainPanel_eventHandler, - .drawFunctionBar = MainPanel_drawFunctionBar, - .printHeader = MainPanel_printHeader -}; - -MainPanel* MainPanel_new() { - MainPanel* this = AllocThis(MainPanel); - Panel_init((Panel*) this, 1, 1, 1, 1, Class(Process), false, FunctionBar_new(MainFunctions, NULL, NULL)); - this->keys = xCalloc(KEY_MAX, sizeof(Htop_Action)); - this->inc = IncSet_new(MainPanel_getFunctionBar(this)); - - Action_setBindings(this->keys); - Platform_setBindings(this->keys); - - return this; -} - -void MainPanel_setState(MainPanel* this, State* state) { - this->state = state; -} - -void MainPanel_delete(Object* object) { - Panel* super = (Panel*) object; - MainPanel* this = (MainPanel*) object; - Panel_done(super); - IncSet_delete(this->inc); - free(this->keys); - free(this); -} diff -Nru pcp-5.3.1/src/pcp/htop/MainPanel.h pcp-5.3.2/src/pcp/htop/MainPanel.h --- pcp-5.3.1/src/pcp/htop/MainPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/MainPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -#ifndef HEADER_MainPanel -#define HEADER_MainPanel -/* -htop - ColumnsPanel.h -(C) 2004-2015 Hisham H. Muhammad -(C) 2020 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include - -#include "Action.h" -#include "IncSet.h" -#include "Object.h" -#include "Panel.h" -#include "Process.h" - - -typedef struct MainPanel_ { - Panel super; - State* state; - IncSet* inc; - Htop_Action* keys; - pid_t pidSearch; -} MainPanel; - -typedef bool(*MainPanel_ForeachProcessFn)(Process*, Arg); - -#define MainPanel_getFunctionBar(this_) (((Panel*)(this_))->defaultBar) - -void MainPanel_updateTreeFunctions(MainPanel* this, bool mode); - -void MainPanel_pidSearch(MainPanel* this, int ch); - -int MainPanel_selectedPid(MainPanel* this); - -bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged); - -extern const PanelClass MainPanel_class; - -MainPanel* MainPanel_new(void); - -void MainPanel_setState(MainPanel* this, State* state); - -void MainPanel_delete(Object* object); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/MemoryMeter.c pcp-5.3.2/src/pcp/htop/MemoryMeter.c --- pcp-5.3.1/src/pcp/htop/MemoryMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/MemoryMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* -htop - MemoryMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "MemoryMeter.h" - -#include - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" - - -static const int MemoryMeter_attributes[] = { - MEMORY_USED, - MEMORY_BUFFERS, - MEMORY_SHARED, - MEMORY_CACHE -}; - -static void MemoryMeter_updateValues(Meter* this) { - char* buffer = this->txtBuffer; - size_t size = sizeof(this->txtBuffer); - int written; - - /* shared and available memory are not supported on all platforms */ - this->values[2] = NAN; - this->values[4] = NAN; - Platform_setMemoryValues(this); - - /* Do not print available memory in bar mode */ - this->curItems = 4; - - written = Meter_humanUnit(buffer, isnan(this->values[4]) ? this->values[0] : this->total - this->values[4], size); - METER_BUFFER_CHECK(buffer, size, written); - - METER_BUFFER_APPEND_CHR(buffer, size, '/'); - - Meter_humanUnit(buffer, this->total, size); -} - -static void MemoryMeter_display(const Object* cast, RichString* out) { - char buffer[50]; - const Meter* this = (const Meter*)cast; - - RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); - Meter_humanUnit(buffer, this->total, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - - Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); - RichString_appendAscii(out, CRT_colors[MEMORY_USED], buffer); - - Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " buffers:"); - RichString_appendAscii(out, CRT_colors[MEMORY_BUFFERS_TEXT], buffer); - - /* shared memory is not supported on all platforms */ - if (!isnan(this->values[2])) { - Meter_humanUnit(buffer, this->values[2], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " shared:"); - RichString_appendAscii(out, CRT_colors[MEMORY_SHARED], buffer); - } - - Meter_humanUnit(buffer, this->values[3], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:"); - RichString_appendAscii(out, CRT_colors[MEMORY_CACHE], buffer); - - /* available memory is not supported on all platforms */ - if (!isnan(this->values[4])) { - Meter_humanUnit(buffer, this->values[4], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " available:"); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - } -} - -const MeterClass MemoryMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = MemoryMeter_display, - }, - .updateValues = MemoryMeter_updateValues, - .defaultMode = BAR_METERMODE, - .maxItems = 5, - .total = 100.0, - .attributes = MemoryMeter_attributes, - .name = "Memory", - .uiName = "Memory", - .caption = "Mem" -}; diff -Nru pcp-5.3.1/src/pcp/htop/MemoryMeter.h pcp-5.3.2/src/pcp/htop/MemoryMeter.h --- pcp-5.3.1/src/pcp/htop/MemoryMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/MemoryMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_MemoryMeter -#define HEADER_MemoryMeter -/* -htop - MemoryMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass MemoryMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Meter.c pcp-5.3.2/src/pcp/htop/Meter.c --- pcp-5.3.1/src/pcp/htop/Meter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Meter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,480 +0,0 @@ -/* -htop - Meter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "Meter.h" - -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Object.h" -#include "Platform.h" -#include "ProvideCurses.h" -#include "RichString.h" -#include "Settings.h" -#include "XUtils.h" - - -#define GRAPH_HEIGHT 4 /* Unit: rows (lines) */ - -const MeterClass Meter_class = { - .super = { - .extends = Class(Object) - } -}; - -Meter* Meter_new(const struct ProcessList_* pl, unsigned int param, const MeterClass* type) { - Meter* this = xCalloc(1, sizeof(Meter)); - Object_setClass(this, type); - this->h = 1; - this->param = param; - this->pl = pl; - this->curItems = type->maxItems; - this->curAttributes = NULL; - this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL; - this->total = type->total; - this->caption = xStrdup(type->caption); - if (Meter_initFn(this)) { - Meter_init(this); - } - Meter_setMode(this, type->defaultMode); - return this; -} - -int Meter_humanUnit(char* buffer, unsigned long int value, size_t size) { - const char* prefix = "KMGTPEZY"; - unsigned long int powi = 1; - unsigned int powj = 1, precision = 2; - - for (;;) { - if (value / 1024 < powi) - break; - - if (prefix[1] == '\0') - break; - - powi *= 1024; - ++prefix; - } - - if (*prefix == 'K') - precision = 0; - - for (; precision > 0; precision--) { - powj *= 10; - if (value / powi < powj) - break; - } - - return snprintf(buffer, size, "%.*f%c", precision, (double) value / powi, *prefix); -} - -void Meter_delete(Object* cast) { - if (!cast) - return; - - Meter* this = (Meter*) cast; - if (Meter_doneFn(this)) { - Meter_done(this); - } - free(this->drawData); - free(this->caption); - free(this->values); - free(this); -} - -void Meter_setCaption(Meter* this, const char* caption) { - free_and_xStrdup(&this->caption, caption); -} - -static inline void Meter_displayBuffer(const Meter* this, RichString* out) { - if (Object_displayFn(this)) { - Object_display(this, out); - } else { - RichString_writeWide(out, CRT_colors[Meter_attributes(this)[0]], this->txtBuffer); - } -} - -void Meter_setMode(Meter* this, int modeIndex) { - if (modeIndex > 0 && modeIndex == this->mode) { - return; - } - - if (!modeIndex) { - modeIndex = 1; - } - - assert(modeIndex < LAST_METERMODE); - if (Meter_defaultMode(this) == CUSTOM_METERMODE) { - this->draw = Meter_drawFn(this); - if (Meter_updateModeFn(this)) { - Meter_updateMode(this, modeIndex); - } - } else { - assert(modeIndex >= 1); - free(this->drawData); - this->drawData = NULL; - - const MeterMode* mode = Meter_modes[modeIndex]; - this->draw = mode->draw; - this->h = mode->h; - } - this->mode = modeIndex; -} - -ListItem* Meter_toListItem(const Meter* this, bool moving) { - char mode[20]; - if (this->mode) { - xSnprintf(mode, sizeof(mode), " [%s]", Meter_modes[this->mode]->uiName); - } else { - mode[0] = '\0'; - } - char number[10]; - if (this->param > 0) { - xSnprintf(number, sizeof(number), " %u", this->param); - } else { - number[0] = '\0'; - } - char buffer[50]; - xSnprintf(buffer, sizeof(buffer), "%s%s%s", Meter_uiName(this), number, mode); - ListItem* li = ListItem_new(buffer, 0); - li->moving = moving; - return li; -} - -/* ---------- TextMeterMode ---------- */ - -static void TextMeterMode_draw(Meter* this, int x, int y, int w) { - attrset(CRT_colors[METER_TEXT]); - mvaddnstr(y, x, this->caption, w - 1); - attrset(CRT_colors[RESET_COLOR]); - - int captionLen = strlen(this->caption); - x += captionLen; - w -= captionLen; - if (w <= 0) - return; - - RichString_begin(out); - Meter_displayBuffer(this, &out); - RichString_printoffnVal(out, y, x, 0, w - 1); - RichString_delete(&out); -} - -/* ---------- BarMeterMode ---------- */ - -static const char BarMeterMode_characters[] = "|#*@$%&."; - -static void BarMeterMode_draw(Meter* this, int x, int y, int w) { - w -= 2; - attrset(CRT_colors[METER_TEXT]); - int captionLen = 3; - mvaddnstr(y, x, this->caption, captionLen); - x += captionLen; - w -= captionLen; - attrset(CRT_colors[BAR_BORDER]); - mvaddch(y, x, '['); - mvaddch(y, x + MAXIMUM(w, 0), ']'); - attrset(CRT_colors[RESET_COLOR]); - - w--; - x++; - - if (w < 1) - return; - - // The text in the bar is right aligned; - // Pad with maximal spaces and then calculate needed starting position offset - RichString_begin(bar); - RichString_appendChr(&bar, 0, ' ', w); - RichString_appendWide(&bar, 0, this->txtBuffer); - int startPos = RichString_sizeVal(bar) - w; - if (startPos > w) { - // Text is too large for bar - // Truncate meter text at a space character - for (int pos = 2 * w; pos > w; pos--) { - if (RichString_getCharVal(bar, pos) == ' ') { - while (pos > w && RichString_getCharVal(bar, pos - 1) == ' ') - pos--; - startPos = pos - w; - break; - } - } - - // If still too large, print the start not the end - startPos = MINIMUM(startPos, w); - } - assert(startPos >= 0); - assert(startPos <= w); - assert(startPos + w <= RichString_sizeVal(bar)); - - int blockSizes[10]; - - // First draw in the bar[] buffer... - int offset = 0; - for (uint8_t i = 0; i < this->curItems; i++) { - double value = this->values[i]; - value = CLAMP(value, 0.0, this->total); - if (value > 0) { - blockSizes[i] = ceil((value / this->total) * w); - } else { - blockSizes[i] = 0; - } - int nextOffset = offset + blockSizes[i]; - // (Control against invalid values) - nextOffset = CLAMP(nextOffset, 0, w); - for (int j = offset; j < nextOffset; j++) - if (RichString_getCharVal(bar, startPos + j) == ' ') { - if (CRT_colorScheme == COLORSCHEME_MONOCHROME) { - RichString_setChar(&bar, startPos + j, BarMeterMode_characters[i]); - } else { - RichString_setChar(&bar, startPos + j, '|'); - } - } - offset = nextOffset; - } - - // ...then print the buffer. - offset = 0; - for (uint8_t i = 0; i < this->curItems; i++) { - int attr = this->curAttributes ? this->curAttributes[i] : Meter_attributes(this)[i]; - RichString_setAttrn(&bar, CRT_colors[attr], startPos + offset, blockSizes[i]); - RichString_printoffnVal(bar, y, x + offset, startPos + offset, MINIMUM(blockSizes[i], w - offset)); - offset += blockSizes[i]; - offset = CLAMP(offset, 0, w); - } - if (offset < w) { - RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, w - offset); - RichString_printoffnVal(bar, y, x + offset, startPos + offset, w - offset); - } - - RichString_delete(&bar); - - move(y, x + w + 1); - attrset(CRT_colors[RESET_COLOR]); -} - -/* ---------- GraphMeterMode ---------- */ - -#ifdef HAVE_LIBNCURSESW - -#define PIXPERROW_UTF8 4 -static const char* const GraphMeterMode_dotsUtf8[] = { - /*00*/" ", /*01*/"⢀", /*02*/"⢠", /*03*/"⢰", /*04*/ "⢸", - /*10*/"⡀", /*11*/"⣀", /*12*/"⣠", /*13*/"⣰", /*14*/ "⣸", - /*20*/"⡄", /*21*/"⣄", /*22*/"⣤", /*23*/"⣴", /*24*/ "⣼", - /*30*/"⡆", /*31*/"⣆", /*32*/"⣦", /*33*/"⣶", /*34*/ "⣾", - /*40*/"⡇", /*41*/"⣇", /*42*/"⣧", /*43*/"⣷", /*44*/ "⣿" -}; - -#endif - -#define PIXPERROW_ASCII 2 -static const char* const GraphMeterMode_dotsAscii[] = { - /*00*/" ", /*01*/".", /*02*/":", - /*10*/".", /*11*/".", /*12*/":", - /*20*/":", /*21*/":", /*22*/":" -}; - -static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { - const ProcessList* pl = this->pl; - - if (!this->drawData) { - this->drawData = xCalloc(1, sizeof(GraphData)); - } - GraphData* data = this->drawData; - const int nValues = METER_GRAPHDATA_SIZE; - - const char* const* GraphMeterMode_dots; - int GraphMeterMode_pixPerRow; -#ifdef HAVE_LIBNCURSESW - if (CRT_utf8) { - GraphMeterMode_dots = GraphMeterMode_dotsUtf8; - GraphMeterMode_pixPerRow = PIXPERROW_UTF8; - } else -#endif - { - GraphMeterMode_dots = GraphMeterMode_dotsAscii; - GraphMeterMode_pixPerRow = PIXPERROW_ASCII; - } - - attrset(CRT_colors[METER_TEXT]); - int captionLen = 3; - mvaddnstr(y, x, this->caption, captionLen); - x += captionLen; - w -= captionLen; - - if (!timercmp(&pl->realtime, &(data->time), <)) { - int globalDelay = this->pl->settings->delay; - struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay - ((globalDelay / 10) * 10)) * 100000 }; - timeradd(&pl->realtime, &delay, &(data->time)); - - for (int i = 0; i < nValues - 1; i++) - data->values[i] = data->values[i + 1]; - - double value = 0.0; - for (uint8_t i = 0; i < this->curItems; i++) - value += this->values[i]; - data->values[nValues - 1] = value; - } - - int i = nValues - (w * 2) + 2, k = 0; - if (i < 0) { - k = -i / 2; - i = 0; - } - for (; i < nValues - 1; i += 2, k++) { - int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT; - if (this->total < 1) - this->total = 1; - int v1 = CLAMP((int) lround(data->values[i] / this->total * pix), 1, pix); - int v2 = CLAMP((int) lround(data->values[i + 1] / this->total * pix), 1, pix); - - int colorIdx = GRAPH_1; - for (int line = 0; line < GRAPH_HEIGHT; line++) { - int line1 = CLAMP(v1 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow); - int line2 = CLAMP(v2 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow); - - attrset(CRT_colors[colorIdx]); - mvaddstr(y + line, x + k, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]); - colorIdx = GRAPH_2; - } - } - attrset(CRT_colors[RESET_COLOR]); -} - -/* ---------- LEDMeterMode ---------- */ - -static const char* const LEDMeterMode_digitsAscii[] = { - " __ ", " ", " __ ", " __ ", " ", " __ ", " __ ", " __ ", " __ ", " __ ", - "| |", " |", " __|", " __|", "|__|", "|__ ", "|__ ", " |", "|__|", "|__|", - "|__|", " |", "|__ ", " __|", " |", " __|", "|__|", " |", "|__|", " __|" -}; - -#ifdef HAVE_LIBNCURSESW - -static const char* const LEDMeterMode_digitsUtf8[] = { - "┌──┐", " ┐ ", "╶──┐", "╶──┐", "╷ ╷", "┌──╴", "┌──╴", "╶──┐", "┌──┐", "┌──┐", - "│ │", " │ ", "┌──┘", " ──┤", "└──┤", "└──┐", "├──┐", " │", "├──┤", "└──┤", - "└──┘", " ╵ ", "└──╴", "╶──┘", " ╵", "╶──┘", "└──┘", " ╵", "└──┘", " ──┘" -}; - -#endif - -static const char* const* LEDMeterMode_digits; - -static void LEDMeterMode_drawDigit(int x, int y, int n) { - for (int i = 0; i < 3; i++) - mvaddstr(y+i, x, LEDMeterMode_digits[i * 10 + n]); -} - -static void LEDMeterMode_draw(Meter* this, int x, int y, ATTR_UNUSED int w) { -#ifdef HAVE_LIBNCURSESW - if (CRT_utf8) - LEDMeterMode_digits = LEDMeterMode_digitsUtf8; - else -#endif - LEDMeterMode_digits = LEDMeterMode_digitsAscii; - - RichString_begin(out); - Meter_displayBuffer(this, &out); - - int yText = -#ifdef HAVE_LIBNCURSESW - CRT_utf8 ? y + 1 : -#endif - y + 2; - attrset(CRT_colors[LED_COLOR]); - mvaddstr(yText, x, this->caption); - int xx = x + strlen(this->caption); - int len = RichString_sizeVal(out); - for (int i = 0; i < len; i++) { - int c = RichString_getCharVal(out, i); - if (c >= '0' && c <= '9') { - LEDMeterMode_drawDigit(xx, y, c - '0'); - xx += 4; - } else { -#ifdef HAVE_LIBNCURSESW - const cchar_t wc = { .chars = { c, '\0' }, .attr = 0 }; /* use LED_COLOR from attrset() */ - mvadd_wch(yText, xx, &wc); -#else - mvaddch(yText, xx, c); -#endif - xx += 1; - } - } - attrset(CRT_colors[RESET_COLOR]); - RichString_delete(&out); -} - -static MeterMode BarMeterMode = { - .uiName = "Bar", - .h = 1, - .draw = BarMeterMode_draw, -}; - -static MeterMode TextMeterMode = { - .uiName = "Text", - .h = 1, - .draw = TextMeterMode_draw, -}; - -static MeterMode GraphMeterMode = { - .uiName = "Graph", - .h = GRAPH_HEIGHT, - .draw = GraphMeterMode_draw, -}; - -static MeterMode LEDMeterMode = { - .uiName = "LED", - .h = 3, - .draw = LEDMeterMode_draw, -}; - -const MeterMode* const Meter_modes[] = { - NULL, - &BarMeterMode, - &TextMeterMode, - &GraphMeterMode, - &LEDMeterMode, - NULL -}; - -/* Blank meter */ - -static void BlankMeter_updateValues(Meter* this) { - this->txtBuffer[0] = '\0'; -} - -static void BlankMeter_display(ATTR_UNUSED const Object* cast, ATTR_UNUSED RichString* out) { -} - -static const int BlankMeter_attributes[] = { - DEFAULT_COLOR -}; - -const MeterClass BlankMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = BlankMeter_display, - }, - .updateValues = BlankMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 0, - .total = 100.0, - .attributes = BlankMeter_attributes, - .name = "Blank", - .uiName = "Blank", - .caption = "" -}; diff -Nru pcp-5.3.1/src/pcp/htop/Meter.h pcp-5.3.2/src/pcp/htop/Meter.h --- pcp-5.3.1/src/pcp/htop/Meter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Meter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -#ifndef HEADER_Meter -#define HEADER_Meter -/* -htop - Meter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include -#include - -#include "ListItem.h" -#include "Object.h" -#include "ProcessList.h" - - -#define METER_TXTBUFFER_LEN 256 -#define METER_GRAPHDATA_SIZE 256 - -#define METER_BUFFER_CHECK(buffer, size, written) \ - do { \ - if ((written) < 0 || (size_t)(written) >= (size)) { \ - return; \ - } \ - (buffer) += (written); \ - (size) -= (size_t)(written); \ - } while (0) - -#define METER_BUFFER_APPEND_CHR(buffer, size, c) \ - do { \ - if ((size) < 2) { \ - return; \ - } \ - *(buffer)++ = c; \ - *(buffer) = '\0'; \ - (size)--; \ - if ((size) == 0) { \ - return; \ - } \ - } while (0) - - -struct Meter_; -typedef struct Meter_ Meter; - -typedef void(*Meter_Init)(Meter*); -typedef void(*Meter_Done)(Meter*); -typedef void(*Meter_UpdateMode)(Meter*, int); -typedef void(*Meter_UpdateValues)(Meter*); -typedef void(*Meter_Draw)(Meter*, int, int, int); - -typedef struct MeterClass_ { - const ObjectClass super; - const Meter_Init init; - const Meter_Done done; - const Meter_UpdateMode updateMode; - const Meter_Draw draw; - const Meter_UpdateValues updateValues; - const int defaultMode; - const double total; - const int* const attributes; - const char* const name; /* internal name of the meter, must not contain any space */ - const char* const uiName; /* display name in header setup menu */ - const char* const caption; /* prefix in the actual header */ - const char* const description; /* optional meter description in header setup menu */ - const uint8_t maxItems; -} MeterClass; - -#define As_Meter(this_) ((const MeterClass*)((this_)->super.klass)) -#define Meter_initFn(this_) As_Meter(this_)->init -#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_)) -#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_)) -#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode -#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_) -#define Meter_drawFn(this_) As_Meter(this_)->draw -#define Meter_doneFn(this_) As_Meter(this_)->done -#define Meter_updateValues(this_) As_Meter(this_)->updateValues((Meter*)(this_)) -#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode -#define Meter_attributes(this_) As_Meter(this_)->attributes -#define Meter_name(this_) As_Meter(this_)->name -#define Meter_uiName(this_) As_Meter(this_)->uiName - -typedef struct GraphData_ { - struct timeval time; - double values[METER_GRAPHDATA_SIZE]; -} GraphData; - -struct Meter_ { - Object super; - Meter_Draw draw; - - char* caption; - int mode; - unsigned int param; - GraphData* drawData; - int h; - int columnWidthCount; /*<< only used internally by the Header */ - const ProcessList* pl; - uint8_t curItems; - const int* curAttributes; - char txtBuffer[METER_TXTBUFFER_LEN]; - double* values; - double total; - void* meterData; -}; - -typedef struct MeterMode_ { - Meter_Draw draw; - const char* uiName; - int h; -} MeterMode; - -typedef enum { - CUSTOM_METERMODE = 0, - BAR_METERMODE, - TEXT_METERMODE, - GRAPH_METERMODE, - LED_METERMODE, - LAST_METERMODE -} MeterModeId; - -extern const MeterClass Meter_class; - -Meter* Meter_new(const ProcessList* pl, unsigned int param, const MeterClass* type); - -int Meter_humanUnit(char* buffer, unsigned long int value, size_t size); - -void Meter_delete(Object* cast); - -void Meter_setCaption(Meter* this, const char* caption); - -void Meter_setMode(Meter* this, int modeIndex); - -ListItem* Meter_toListItem(const Meter* this, bool moving); - -extern const MeterMode* const Meter_modes[]; - -extern const MeterClass BlankMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/MetersPanel.c pcp-5.3.2/src/pcp/htop/MetersPanel.c --- pcp-5.3.1/src/pcp/htop/MetersPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/MetersPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,223 +0,0 @@ -/* -htop - MetersPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "MetersPanel.h" - -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "Header.h" -#include "ListItem.h" -#include "Meter.h" -#include "Object.h" -#include "ProvideCurses.h" - - -// Note: In code the meters are known to have bar/text/graph "Modes", but in UI -// we call them "Styles". -static const char* const MetersFunctions[] = {"Style ", "Move ", " ", "Delete", "Done ", NULL}; -static const char* const MetersKeys[] = {"Space", "Enter", "", "Del", "F10"}; -static const int MetersEvents[] = {' ', 13, ERR, KEY_DC, KEY_F(10)}; - -// We avoid UTF-8 arrows ← → here as they might display full-width on Chinese -// terminals, breaking our aligning. -// In , arrows (U+2019..U+2199) are -// considered "Ambiguous characters". -static const char* const MetersMovingFunctions[] = {"Style ", "Lock ", "Up ", "Down ", "Left ", "Right ", " ", "Delete", "Done ", NULL}; -static const char* const MetersMovingKeys[] = {"Space", "Enter", "Up", "Dn", "<-", "->", " ", "Del", "F10"}; -static const int MetersMovingEvents[] = {' ', 13, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, ERR, KEY_DC, KEY_F(10)}; -static FunctionBar* Meters_movingBar = NULL; - -void MetersPanel_cleanup() { - if (Meters_movingBar) { - FunctionBar_delete(Meters_movingBar); - Meters_movingBar = NULL; - } -} - -static void MetersPanel_delete(Object* object) { - Panel* super = (Panel*) object; - MetersPanel* this = (MetersPanel*) object; - Panel_done(super); - free(this); -} - -void MetersPanel_setMoving(MetersPanel* this, bool moving) { - Panel* super = (Panel*) this; - this->moving = moving; - ListItem* selected = (ListItem*)Panel_getSelected(super); - if (selected) { - selected->moving = moving; - } - if (!moving) { - Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS); - Panel_setDefaultBar(super); - } else { - Panel_setSelectionColor(super, PANEL_SELECTION_FOLLOW); - super->currentBar = Meters_movingBar; - } -} - -static inline bool moveToNeighbor(MetersPanel* this, MetersPanel* neighbor, int selected) { - Panel* super = (Panel*) this; - if (this->moving) { - if (neighbor) { - if (selected < Vector_size(this->meters)) { - MetersPanel_setMoving(this, false); - - Meter* meter = (Meter*) Vector_take(this->meters, selected); - Panel_remove(super, selected); - Vector_insert(neighbor->meters, selected, meter); - Panel_insert(&(neighbor->super), selected, (Object*) Meter_toListItem(meter, false)); - Panel_setSelected(&(neighbor->super), selected); - - MetersPanel_setMoving(neighbor, true); - return true; - } - } - } - return false; -} - -static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) { - MetersPanel* this = (MetersPanel*) super; - - int selected = Panel_getSelectedIndex(super); - HandlerResult result = IGNORED; - bool sideMove = false; - - switch(ch) { - case 0x0a: - case 0x0d: - case KEY_ENTER: - { - if (!Vector_size(this->meters)) - break; - MetersPanel_setMoving(this, !(this->moving)); - result = HANDLED; - break; - } - case ' ': - case KEY_F(4): - case 't': - { - if (!Vector_size(this->meters)) - break; - Meter* meter = (Meter*) Vector_get(this->meters, selected); - int mode = meter->mode + 1; - if (mode == LAST_METERMODE) mode = 1; - Meter_setMode(meter, mode); - Panel_set(super, selected, (Object*) Meter_toListItem(meter, this->moving)); - result = HANDLED; - break; - } - case KEY_UP: - { - if (!this->moving) { - break; - } - } - /* else fallthrough */ - case KEY_F(7): - case '[': - case '-': - { - Vector_moveUp(this->meters, selected); - Panel_moveSelectedUp(super); - result = HANDLED; - break; - } - case KEY_DOWN: - { - if (!this->moving) { - break; - } - } - /* else fallthrough */ - case KEY_F(8): - case ']': - case '+': - { - Vector_moveDown(this->meters, selected); - Panel_moveSelectedDown(super); - result = HANDLED; - break; - } - case KEY_RIGHT: - { - sideMove = moveToNeighbor(this, this->rightNeighbor, selected); - if (this->moving && !sideMove) { - // lock user here until it exits positioning-mode - result = HANDLED; - } - // if user is free, don't set HANDLED; - // let ScreenManager handle focus. - break; - } - case KEY_LEFT: - { - sideMove = moveToNeighbor(this, this->leftNeighbor, selected); - if (this->moving && !sideMove) { - result = HANDLED; - } - break; - } - case KEY_F(9): - case KEY_DC: - { - if (!Vector_size(this->meters)) - break; - if (selected < Vector_size(this->meters)) { - Vector_remove(this->meters, selected); - Panel_remove(super, selected); - } - MetersPanel_setMoving(this, false); - result = HANDLED; - break; - } - } - if (result == HANDLED || sideMove) { - Header* header = this->scr->header; - this->settings->changed = true; - Header_calculateHeight(header); - Header_draw(header); - ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); - } - return result; -} - -const PanelClass MetersPanel_class = { - .super = { - .extends = Class(Panel), - .delete = MetersPanel_delete - }, - .eventHandler = MetersPanel_eventHandler -}; - -MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr) { - MetersPanel* this = AllocThis(MetersPanel); - Panel* super = (Panel*) this; - FunctionBar* fuBar = FunctionBar_new(MetersFunctions, MetersKeys, MetersEvents); - if (!Meters_movingBar) { - Meters_movingBar = FunctionBar_new(MetersMovingFunctions, MetersMovingKeys, MetersMovingEvents); - } - Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); - - this->settings = settings; - this->meters = meters; - this->scr = scr; - this->moving = false; - this->rightNeighbor = NULL; - this->leftNeighbor = NULL; - Panel_setHeader(super, header); - for (int i = 0; i < Vector_size(meters); i++) { - const Meter* meter = (const Meter*) Vector_get(meters, i); - Panel_add(super, (Object*) Meter_toListItem(meter, false)); - } - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/MetersPanel.h pcp-5.3.2/src/pcp/htop/MetersPanel.h --- pcp-5.3.1/src/pcp/htop/MetersPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/MetersPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#ifndef HEADER_MetersPanel -#define HEADER_MetersPanel -/* -htop - MetersPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "Panel.h" -#include "ScreenManager.h" -#include "Settings.h" -#include "Vector.h" - - -struct MetersPanel_; -typedef struct MetersPanel_ MetersPanel; - -struct MetersPanel_ { - Panel super; - - Settings* settings; - Vector* meters; - ScreenManager* scr; - MetersPanel* leftNeighbor; - MetersPanel* rightNeighbor; - bool moving; -}; - -void MetersPanel_cleanup(void); - -void MetersPanel_setMoving(MetersPanel* this, bool moving); - -extern const PanelClass MetersPanel_class; - -MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/NetworkIOMeter.c pcp-5.3.2/src/pcp/htop/NetworkIOMeter.c --- pcp-5.3.1/src/pcp/htop/NetworkIOMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/NetworkIOMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -#include "NetworkIOMeter.h" - -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" -#include "XUtils.h" - - -static const int NetworkIOMeter_attributes[] = { - METER_VALUE_IOREAD, - METER_VALUE_IOWRITE, -}; - -static bool hasData = false; - -static uint32_t cached_rxb_diff; -static uint32_t cached_rxp_diff; -static uint32_t cached_txb_diff; -static uint32_t cached_txp_diff; - -static void NetworkIOMeter_updateValues(Meter* this) { - const ProcessList* pl = this->pl; - static uint64_t cached_last_update = 0; - - uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update; - - /* update only every 500ms */ - if (passedTimeInMs > 500) { - static uint64_t cached_rxb_total; - static uint64_t cached_rxp_total; - static uint64_t cached_txb_total; - static uint64_t cached_txp_total; - uint64_t diff; - - cached_last_update = pl->realtimeMs; - - NetworkIOData data; - hasData = Platform_getNetworkIO(&data); - if (!hasData) { - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "no data"); - return; - } - - if (data.bytesReceived > cached_rxb_total) { - diff = data.bytesReceived - cached_rxb_total; - diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */ - diff = (1000 * diff) / passedTimeInMs; /* convert to per second */ - cached_rxb_diff = (uint32_t)diff; - } else { - cached_rxb_diff = 0; - } - cached_rxb_total = data.bytesReceived; - - if (data.packetsReceived > cached_rxp_total) { - diff = data.packetsReceived - cached_rxp_total; - cached_rxp_diff = (uint32_t)diff; - } else { - cached_rxp_diff = 0; - } - cached_rxp_total = data.packetsReceived; - - if (data.bytesTransmitted > cached_txb_total) { - diff = data.bytesTransmitted - cached_txb_total; - diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */ - diff = (1000 * diff) / passedTimeInMs; /* convert to per second */ - cached_txb_diff = (uint32_t)diff; - } else { - cached_txb_diff = 0; - } - cached_txb_total = data.bytesTransmitted; - - if (data.packetsTransmitted > cached_txp_total) { - diff = data.packetsTransmitted - cached_txp_total; - cached_txp_diff = (uint32_t)diff; - } else { - cached_txp_diff = 0; - } - cached_txp_total = data.packetsTransmitted; - } - - this->values[0] = cached_rxb_diff; - this->values[1] = cached_txb_diff; - if (cached_rxb_diff + cached_txb_diff > this->total) { - this->total = cached_rxb_diff + cached_txb_diff; - } - - char bufferBytesReceived[12], bufferBytesTransmitted[12]; - Meter_humanUnit(bufferBytesReceived, cached_rxb_diff, sizeof(bufferBytesReceived)); - Meter_humanUnit(bufferBytesTransmitted, cached_txb_diff, sizeof(bufferBytesTransmitted)); - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "rx:%siB/s tx:%siB/s", bufferBytesReceived, bufferBytesTransmitted); -} - -static void NetworkIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) { - if (!hasData) { - RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data"); - return; - } - - char buffer[64]; - - RichString_writeAscii(out, CRT_colors[METER_TEXT], "rx: "); - Meter_humanUnit(buffer, cached_rxb_diff, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer); - RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], "iB/s"); - - RichString_appendAscii(out, CRT_colors[METER_TEXT], " tx: "); - Meter_humanUnit(buffer, cached_txb_diff, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer); - RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], "iB/s"); - - xSnprintf(buffer, sizeof(buffer), " (%u/%u packets) ", cached_rxp_diff, cached_txp_diff); - RichString_appendAscii(out, CRT_colors[METER_TEXT], buffer); -} - -const MeterClass NetworkIOMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = NetworkIOMeter_display - }, - .updateValues = NetworkIOMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 2, - .total = 100.0, - .attributes = NetworkIOMeter_attributes, - .name = "NetworkIO", - .uiName = "Network IO", - .caption = "Network: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/NetworkIOMeter.h pcp-5.3.2/src/pcp/htop/NetworkIOMeter.h --- pcp-5.3.1/src/pcp/htop/NetworkIOMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/NetworkIOMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#ifndef HEADER_NetworkIOMeter -#define HEADER_NetworkIOMeter - -#include "Meter.h" - -typedef struct NetworkIOData_ { - uint64_t bytesReceived; - uint64_t packetsReceived; - uint64_t bytesTransmitted; - uint64_t packetsTransmitted; -} NetworkIOData; - -extern const MeterClass NetworkIOMeter_class; - -#endif /* HEADER_NetworkIOMeter */ diff -Nru pcp-5.3.1/src/pcp/htop/Object.c pcp-5.3.2/src/pcp/htop/Object.c --- pcp-5.3.1/src/pcp/htop/Object.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Object.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* -htop - Object.c -(C) 2004-2012 Hisham H. Muhammad -(C) 2020 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Object.h" - -#include - - -const ObjectClass Object_class = { - .extends = NULL -}; - -bool Object_isA(const Object* o, const ObjectClass* klass) { - if (!o) - return false; - - for (const ObjectClass* type = o->klass; type; type = type->extends) { - if (type == klass) { - return true; - } - } - - return false; -} diff -Nru pcp-5.3.1/src/pcp/htop/Object.h pcp-5.3.2/src/pcp/htop/Object.h --- pcp-5.3.1/src/pcp/htop/Object.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Object.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#ifndef HEADER_Object -#define HEADER_Object -/* -htop - Object.h -(C) 2004-2012 Hisham H. Muhammad -(C) 2020 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include - -#include "RichString.h" -#include "XUtils.h" // IWYU pragma: keep - - -struct Object_; -typedef struct Object_ Object; - -typedef void(*Object_Display)(const Object*, RichString*); -typedef int(*Object_Compare)(const void*, const void*); -typedef void(*Object_Delete)(Object*); - -#define Object_getClass(obj_) ((const Object*)(obj_))->klass -#define Object_setClass(obj_, class_) (((Object*)(obj_))->klass = (const ObjectClass*) (class_)) - -#define Object_delete(obj_) (assert(Object_getClass(obj_)->delete), Object_getClass(obj_)->delete((Object*)(obj_))) -#define Object_displayFn(obj_) Object_getClass(obj_)->display -#define Object_display(obj_, str_) (assert(Object_getClass(obj_)->display), Object_getClass(obj_)->display((const Object*)(obj_), str_)) -#define Object_compare(obj_, other_) (assert(Object_getClass(obj_)->compare), Object_getClass(obj_)->compare((const void*)(obj_), other_)) - -#define Class(class_) ((const ObjectClass*)(&(class_ ## _class))) - -#define AllocThis(class_) (class_*) xMalloc(sizeof(class_)); Object_setClass(this, Class(class_)) - -typedef struct ObjectClass_ { - const void* const extends; - const Object_Display display; - const Object_Delete delete; - const Object_Compare compare; -} ObjectClass; - -struct Object_ { - const ObjectClass* klass; -}; - -typedef union { - int i; - void* v; -} Arg; - -extern const ObjectClass Object_class; - -bool Object_isA(const Object* o, const ObjectClass* klass); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/OpenFilesScreen.c pcp-5.3.2/src/pcp/htop/OpenFilesScreen.c --- pcp-5.3.1/src/pcp/htop/OpenFilesScreen.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/OpenFilesScreen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,247 +0,0 @@ -/* -htop - OpenFilesScreen.c -(C) 2005-2006 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "OpenFilesScreen.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "Macros.h" -#include "Panel.h" -#include "ProvideCurses.h" -#include "Vector.h" -#include "XUtils.h" - - -typedef struct OpenFiles_Data_ { - char* data[7]; -} OpenFiles_Data; - -typedef struct OpenFiles_ProcessData_ { - OpenFiles_Data data; - int error; - struct OpenFiles_FileData_* files; -} OpenFiles_ProcessData; - -typedef struct OpenFiles_FileData_ { - OpenFiles_Data data; - struct OpenFiles_FileData_* next; -} OpenFiles_FileData; - -static size_t getIndexForType(char type) { - switch (type) { - case 'f': - return 0; - case 'a': - return 1; - case 'D': - return 2; - case 'i': - return 3; - case 'n': - return 4; - case 's': - return 5; - case 't': - return 6; - } - - /* should never reach here */ - abort(); -} - -static const char* getDataForType(const OpenFiles_Data* data, char type) { - size_t index = getIndexForType(type); - return data->data[index] ? data->data[index] : ""; -} - -OpenFilesScreen* OpenFilesScreen_new(const Process* process) { - OpenFilesScreen* this = xMalloc(sizeof(OpenFilesScreen)); - Object_setClass(this, Class(OpenFilesScreen)); - if (Process_isThread(process)) { - this->pid = process->tgid; - } else { - this->pid = process->pid; - } - return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE MODE DEVICE SIZE NODE NAME"); -} - -void OpenFilesScreen_delete(Object* this) { - free(InfoScreen_done((InfoScreen*)this)); -} - -static void OpenFilesScreen_draw(InfoScreen* this) { - InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, Process_getCommand(this->process)); -} - -static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { - OpenFiles_ProcessData* pdata = xCalloc(1, sizeof(OpenFiles_ProcessData)); - - int fdpair[2] = {0, 0}; - if (pipe(fdpair) == -1) { - pdata->error = 1; - return pdata; - } - - pid_t child = fork(); - if (child == -1) { - close(fdpair[1]); - close(fdpair[0]); - pdata->error = 1; - return pdata; - } - - if (child == 0) { - close(fdpair[0]); - dup2(fdpair[1], STDOUT_FILENO); - close(fdpair[1]); - int fdnull = open("/dev/null", O_WRONLY); - if (fdnull < 0) { - exit(1); - } - - dup2(fdnull, STDERR_FILENO); - close(fdnull); - char buffer[32] = {0}; - xSnprintf(buffer, sizeof(buffer), "%d", pid); - execlp("lsof", "lsof", "-P", "-p", buffer, "-F", NULL); - exit(127); - } - close(fdpair[1]); - - OpenFiles_Data* item = &(pdata->data); - OpenFiles_FileData* fdata = NULL; - - FILE* fd = fdopen(fdpair[0], "r"); - if (!fd) { - pdata->error = 1; - return pdata; - } - for (;;) { - char* line = String_readLine(fd); - if (!line) { - break; - } - - unsigned char cmd = line[0]; - switch (cmd) { - case 'f': /* file descriptor */ - { - OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData)); - if (fdata == NULL) { - pdata->files = nextFile; - } else { - fdata->next = nextFile; - } - fdata = nextFile; - item = &(fdata->data); - } /* FALLTHRU */ - case 'a': /* file access mode */ - case 'D': /* file's major/minor device number */ - case 'i': /* file's inode number */ - case 'n': /* file name, comment, Internet address */ - case 's': /* file's size */ - case 't': /* file's type */ - { - size_t index = getIndexForType(cmd); - free(item->data[index]); - item->data[index] = xStrdup(line + 1); - break; - } - case 'c': /* process command name */ - case 'd': /* file's device character code */ - case 'g': /* process group ID */ - case 'G': /* file flags */ - case 'k': /* link count */ - case 'l': /* file's lock status */ - case 'L': /* process login name */ - case 'o': /* file's offset */ - case 'p': /* process ID */ - case 'P': /* protocol name */ - case 'R': /* parent process ID */ - case 'T': /* TCP/TPI information, identified by prefixes */ - case 'u': /* process user ID */ - /* ignore */ - break; - } - free(line); - } - fclose(fd); - - int wstatus; - if (waitpid(child, &wstatus, 0) == -1) { - pdata->error = 1; - return pdata; - } - - if (!WIFEXITED(wstatus)) { - pdata->error = 1; - } else { - pdata->error = WEXITSTATUS(wstatus); - } - - return pdata; -} - -static void OpenFiles_Data_clear(OpenFiles_Data* data) { - for (size_t i = 0; i < ARRAYSIZE(data->data); i++) - free(data->data[i]); -} - -static void OpenFilesScreen_scan(InfoScreen* this) { - Panel* panel = this->display; - int idx = Panel_getSelectedIndex(panel); - Panel_prune(panel); - OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(((OpenFilesScreen*)this)->pid); - if (pdata->error == 127) { - InfoScreen_addLine(this, "Could not execute 'lsof'. Please make sure it is available in your $PATH."); - } else if (pdata->error == 1) { - InfoScreen_addLine(this, "Failed listing open files."); - } else { - OpenFiles_FileData* fdata = pdata->files; - while (fdata) { - OpenFiles_Data* data = &fdata->data; - size_t lenN = strlen(getDataForType(data, 'n')); - size_t sizeEntry = 5 + 7 + 4 + 10 + 10 + 10 + lenN + 7 /*spaces*/ + 1 /*null*/; - char entry[sizeEntry]; - xSnprintf(entry, sizeof(entry), "%5.5s %-7.7s %-4.4s %-10.10s %10.10s %10.10s %s", - getDataForType(data, 'f'), - getDataForType(data, 't'), - getDataForType(data, 'a'), - getDataForType(data, 'D'), - getDataForType(data, 's'), - getDataForType(data, 'i'), - getDataForType(data, 'n')); - InfoScreen_addLine(this, entry); - OpenFiles_Data_clear(data); - OpenFiles_FileData* old = fdata; - fdata = fdata->next; - free(old); - } - OpenFiles_Data_clear(&pdata->data); - } - free(pdata); - Vector_insertionSort(this->lines); - Vector_insertionSort(panel->items); - Panel_setSelected(panel, idx); -} - -const InfoScreenClass OpenFilesScreen_class = { - .super = { - .extends = Class(Object), - .delete = OpenFilesScreen_delete - }, - .scan = OpenFilesScreen_scan, - .draw = OpenFilesScreen_draw -}; diff -Nru pcp-5.3.1/src/pcp/htop/OpenFilesScreen.h pcp-5.3.2/src/pcp/htop/OpenFilesScreen.h --- pcp-5.3.1/src/pcp/htop/OpenFilesScreen.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/OpenFilesScreen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#ifndef HEADER_OpenFilesScreen -#define HEADER_OpenFilesScreen -/* -htop - OpenFilesScreen.h -(C) 2005-2006 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "InfoScreen.h" -#include "Object.h" -#include "Process.h" - -typedef struct OpenFilesScreen_ { - InfoScreen super; - pid_t pid; -} OpenFilesScreen; - -extern const InfoScreenClass OpenFilesScreen_class; - -OpenFilesScreen* OpenFilesScreen_new(const Process* process); - -void OpenFilesScreen_delete(Object* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/OptionItem.c pcp-5.3.2/src/pcp/htop/OptionItem.c --- pcp-5.3.1/src/pcp/htop/OptionItem.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/OptionItem.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,191 +0,0 @@ -/* -htop - OptionItem.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "OptionItem.h" - -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "RichString.h" -#include "XUtils.h" - - -static void OptionItem_delete(Object* cast) { - OptionItem* this = (OptionItem*)cast; - assert (this != NULL); - - free(this->text); - free(this); -} - -static void CheckItem_display(const Object* cast, RichString* out) { - const CheckItem* this = (const CheckItem*)cast; - assert (this != NULL); - - RichString_writeAscii(out, CRT_colors[CHECK_BOX], "["); - if (CheckItem_get(this)) { - RichString_appendAscii(out, CRT_colors[CHECK_MARK], "x"); - } else { - RichString_appendAscii(out, CRT_colors[CHECK_MARK], " "); - } - RichString_appendAscii(out, CRT_colors[CHECK_BOX], "] "); - RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text); -} - -static void NumberItem_display(const Object* cast, RichString* out) { - const NumberItem* this = (const NumberItem*)cast; - assert (this != NULL); - - char buffer[12]; - RichString_writeAscii(out, CRT_colors[CHECK_BOX], "["); - int written; - if (this->scale < 0) { - written = xSnprintf(buffer, sizeof(buffer), "%.*f", -this->scale, pow(10, this->scale) * NumberItem_get(this)); - } else if (this->scale > 0) { - written = xSnprintf(buffer, sizeof(buffer), "%d", (int) (pow(10, this->scale) * NumberItem_get(this))); - } else { - written = xSnprintf(buffer, sizeof(buffer), "%d", NumberItem_get(this)); - } - RichString_appendAscii(out, CRT_colors[CHECK_MARK], buffer); - RichString_appendAscii(out, CRT_colors[CHECK_BOX], "]"); - for (int i = written; i < 5; i++) { - RichString_appendAscii(out, CRT_colors[CHECK_BOX], " "); - } - RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text); -} - -const OptionItemClass OptionItem_class = { - .super = { - .extends = Class(Object), - .delete = OptionItem_delete - } -}; - -const OptionItemClass CheckItem_class = { - .super = { - .extends = Class(OptionItem), - .delete = OptionItem_delete, - .display = CheckItem_display - }, - .kind = OPTION_ITEM_CHECK -}; - -const OptionItemClass NumberItem_class = { - .super = { - .extends = Class(OptionItem), - .delete = OptionItem_delete, - .display = NumberItem_display - }, - .kind = OPTION_ITEM_NUMBER -}; - -CheckItem* CheckItem_newByRef(const char* text, bool* ref) { - CheckItem* this = AllocThis(CheckItem); - this->super.text = xStrdup(text); - this->value = false; - this->ref = ref; - return this; -} - -CheckItem* CheckItem_newByVal(const char* text, bool value) { - CheckItem* this = AllocThis(CheckItem); - this->super.text = xStrdup(text); - this->value = value; - this->ref = NULL; - return this; -} - -bool CheckItem_get(const CheckItem* this) { - if (this->ref) { - return *(this->ref); - } else { - return this->value; - } -} - -void CheckItem_set(CheckItem* this, bool value) { - if (this->ref) { - *(this->ref) = value; - } else { - this->value = value; - } -} - -void CheckItem_toggle(CheckItem* this) { - if (this->ref) { - *(this->ref) = !*(this->ref); - } else { - this->value = !this->value; - } -} - -NumberItem* NumberItem_newByRef(const char* text, int* ref, int scale, int min, int max) { - assert(min <= max); - - NumberItem* this = AllocThis(NumberItem); - this->super.text = xStrdup(text); - this->value = 0; - this->ref = ref; - this->scale = scale; - this->min = min; - this->max = max; - return this; -} - -NumberItem* NumberItem_newByVal(const char* text, int value, int scale, int min, int max) { - assert(min <= max); - - NumberItem* this = AllocThis(NumberItem); - this->super.text = xStrdup(text); - this->value = CLAMP(value, min, max); - this->ref = NULL; - this->scale = scale; - this->min = min; - this->max = max; - return this; -} - -int NumberItem_get(const NumberItem* this) { - if (this->ref) { - return *(this->ref); - } else { - return this->value; - } -} - -void NumberItem_decrease(NumberItem* this) { - if (this->ref) { - *(this->ref) = CLAMP(*(this->ref) - 1, this->min, this->max); - } else { - this->value = CLAMP(this->value - 1, this->min, this->max); - } -} - -void NumberItem_increase(NumberItem* this) { - if (this->ref) { - *(this->ref) = CLAMP(*(this->ref) + 1, this->min, this->max); - } else { - this->value = CLAMP(this->value + 1, this->min, this->max); - } -} - -void NumberItem_toggle(NumberItem* this) { - if (this->ref) { - if (*(this->ref) >= this->max) - *(this->ref) = this->min; - else - *(this->ref) += 1; - } else { - if (this->value >= this->max) - this->value = this->min; - else - this->value += 1; - } -} diff -Nru pcp-5.3.1/src/pcp/htop/OptionItem.h pcp-5.3.2/src/pcp/htop/OptionItem.h --- pcp-5.3.1/src/pcp/htop/OptionItem.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/OptionItem.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -#ifndef HEADER_OptionItem -#define HEADER_OptionItem -/* -htop - OptionItem.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "Object.h" - - -enum OptionItemType { - OPTION_ITEM_CHECK, - OPTION_ITEM_NUMBER, -}; - -typedef struct OptionItemClass_ { - const ObjectClass super; - - enum OptionItemType kind; -} OptionItemClass; - -#define As_OptionItem(this_) ((const OptionItemClass*)((this_)->super.klass)) -#define OptionItem_kind(this_) As_OptionItem(this_)->kind - -typedef struct OptionItem_ { - Object super; - - char* text; -} OptionItem; - -typedef struct CheckItem_ { - OptionItem super; - - bool* ref; - bool value; -} CheckItem; - -typedef struct NumberItem_ { - OptionItem super; - - char* text; - int* ref; - int value; - int scale; - int min; - int max; -} NumberItem; - -extern const OptionItemClass OptionItem_class; -extern const OptionItemClass CheckItem_class; -extern const OptionItemClass NumberItem_class; - -CheckItem* CheckItem_newByRef(const char* text, bool* ref); -CheckItem* CheckItem_newByVal(const char* text, bool value); -bool CheckItem_get(const CheckItem* this); -void CheckItem_set(CheckItem* this, bool value); -void CheckItem_toggle(CheckItem* this); - -NumberItem* NumberItem_newByRef(const char* text, int* ref, int scale, int min, int max); -NumberItem* NumberItem_newByVal(const char* text, int value, int scale, int min, int max); -int NumberItem_get(const NumberItem* this); -void NumberItem_decrease(NumberItem* this); -void NumberItem_increase(NumberItem* this); -void NumberItem_toggle(NumberItem* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Panel.c pcp-5.3.2/src/pcp/htop/Panel.c --- pcp-5.3.1/src/pcp/htop/Panel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Panel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,487 +0,0 @@ -/* -htop - Panel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Panel.h" - -#include -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "ListItem.h" -#include "Macros.h" -#include "ProvideCurses.h" -#include "RichString.h" -#include "XUtils.h" - - -const PanelClass Panel_class = { - .super = { - .extends = Class(Object), - .delete = Panel_delete - }, - .eventHandler = Panel_selectByTyping, -}; - -Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) { - Panel* this; - this = xMalloc(sizeof(Panel)); - Object_setClass(this, Class(Panel)); - Panel_init(this, x, y, w, h, type, owner, fuBar); - return this; -} - -void Panel_delete(Object* cast) { - Panel* this = (Panel*)cast; - Panel_done(this); - free(this); -} - -void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) { - this->x = x; - this->y = y; - this->w = w; - this->h = h; - this->eventHandlerState = NULL; - this->items = Vector_new(type, owner, DEFAULT_SIZE); - this->scrollV = 0; - this->scrollH = 0; - this->selected = 0; - this->oldSelected = 0; - this->selectedLen = 0; - this->needsRedraw = true; - this->wasFocus = false; - RichString_beginAllocated(this->header); - this->defaultBar = fuBar; - this->currentBar = fuBar; - this->selectionColorId = PANEL_SELECTION_FOCUS; -} - -void Panel_done(Panel* this) { - assert (this != NULL); - free(this->eventHandlerState); - Vector_delete(this->items); - FunctionBar_delete(this->defaultBar); - RichString_delete(&this->header); -} - -void Panel_setSelectionColor(Panel* this, ColorElements colorId) { - this->selectionColorId = colorId; -} - -inline void Panel_setHeader(Panel* this, const char* header) { - RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header); - this->needsRedraw = true; -} - -void Panel_move(Panel* this, int x, int y) { - assert (this != NULL); - - this->x = x; - this->y = y; - this->needsRedraw = true; -} - -void Panel_resize(Panel* this, int w, int h) { - assert (this != NULL); - - this->w = w; - this->h = h; - this->needsRedraw = true; -} - -void Panel_prune(Panel* this) { - assert (this != NULL); - - Vector_prune(this->items); - this->scrollV = 0; - this->selected = 0; - this->oldSelected = 0; - this->needsRedraw = true; -} - -void Panel_add(Panel* this, Object* o) { - assert (this != NULL); - - Vector_add(this->items, o); - this->needsRedraw = true; -} - -void Panel_insert(Panel* this, int i, Object* o) { - assert (this != NULL); - - Vector_insert(this->items, i, o); - this->needsRedraw = true; -} - -void Panel_set(Panel* this, int i, Object* o) { - assert (this != NULL); - - Vector_set(this->items, i, o); -} - -Object* Panel_get(Panel* this, int i) { - assert (this != NULL); - - return Vector_get(this->items, i); -} - -Object* Panel_remove(Panel* this, int i) { - assert (this != NULL); - - this->needsRedraw = true; - Object* removed = Vector_remove(this->items, i); - if (this->selected > 0 && this->selected >= Vector_size(this->items)) { - this->selected--; - } - - return removed; -} - -Object* Panel_getSelected(Panel* this) { - assert (this != NULL); - if (Vector_size(this->items) > 0) { - return Vector_get(this->items, this->selected); - } else { - return NULL; - } -} - -void Panel_moveSelectedUp(Panel* this) { - assert (this != NULL); - - Vector_moveUp(this->items, this->selected); - if (this->selected > 0) { - this->selected--; - } -} - -void Panel_moveSelectedDown(Panel* this) { - assert (this != NULL); - - Vector_moveDown(this->items, this->selected); - if (this->selected + 1 < Vector_size(this->items)) { - this->selected++; - } -} - -int Panel_getSelectedIndex(const Panel* this) { - assert (this != NULL); - - return this->selected; -} - -int Panel_size(const Panel* this) { - assert (this != NULL); - - return Vector_size(this->items); -} - -void Panel_setSelected(Panel* this, int selected) { - assert (this != NULL); - - int size = Vector_size(this->items); - if (selected >= size) { - selected = size - 1; - } - if (selected < 0) { - selected = 0; - } - this->selected = selected; - if (Panel_eventHandlerFn(this)) { - Panel_eventHandler(this, EVENT_SET_SELECTED); - } -} - -void Panel_splice(Panel* this, Vector* from) { - assert (this != NULL); - assert (from != NULL); - - Vector_splice(this->items, from); - this->needsRedraw = true; -} - -void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar) { - assert (this != NULL); - - int size = Vector_size(this->items); - int scrollH = this->scrollH; - int y = this->y; - int x = this->x; - int h = this->h; - - if (hideFunctionBar) - h++; - - const int header_attr = focus - ? CRT_colors[PANEL_HEADER_FOCUS] - : CRT_colors[PANEL_HEADER_UNFOCUS]; - if (force_redraw) { - if (Panel_printHeaderFn(this)) - Panel_printHeader(this); - else - RichString_setAttr(&this->header, header_attr); - } - int headerLen = RichString_sizeVal(this->header); - if (headerLen > 0) { - attrset(header_attr); - mvhline(y, x, ' ', this->w); - if (scrollH < headerLen) { - RichString_printoffnVal(this->header, y, x, scrollH, - MINIMUM(headerLen - scrollH, this->w)); - } - attrset(CRT_colors[RESET_COLOR]); - y++; - h--; - } - - // ensure scroll area is on screen - if (this->scrollV < 0) { - this->scrollV = 0; - this->needsRedraw = true; - } else if (this->scrollV > size - h) { - this->scrollV = MAXIMUM(size - h, 0); - this->needsRedraw = true; - } - // ensure selection is on screen - if (this->selected < this->scrollV) { - this->scrollV = this->selected; - this->needsRedraw = true; - } else if (this->selected >= this->scrollV + h) { - this->scrollV = this->selected - h + 1; - this->needsRedraw = true; - } - - int first = this->scrollV; - int upTo = MINIMUM(first + h, size); - - int selectionColor = focus - ? CRT_colors[this->selectionColorId] - : CRT_colors[PANEL_SELECTION_UNFOCUS]; - - if (this->needsRedraw || force_redraw) { - int line = 0; - for (int i = first; line < h && i < upTo; i++) { - const Object* itemObj = Vector_get(this->items, i); - RichString_begin(item); - Object_display(itemObj, &item); - int itemLen = RichString_sizeVal(item); - int amt = MINIMUM(itemLen - scrollH, this->w); - if (highlightSelected && i == this->selected) { - item.highlightAttr = selectionColor; - } - if (item.highlightAttr) { - attrset(item.highlightAttr); - RichString_setAttr(&item, item.highlightAttr); - this->selectedLen = itemLen; - } - mvhline(y + line, x, ' ', this->w); - if (amt > 0) - RichString_printoffnVal(item, y + line, x, scrollH, amt); - if (item.highlightAttr) - attrset(CRT_colors[RESET_COLOR]); - RichString_delete(&item); - line++; - } - while (line < h) { - mvhline(y + line, x, ' ', this->w); - line++; - } - - } else { - const Object* oldObj = Vector_get(this->items, this->oldSelected); - RichString_begin(old); - Object_display(oldObj, &old); - int oldLen = RichString_sizeVal(old); - const Object* newObj = Vector_get(this->items, this->selected); - RichString_begin(new); - Object_display(newObj, &new); - int newLen = RichString_sizeVal(new); - this->selectedLen = newLen; - mvhline(y + this->oldSelected - first, x + 0, ' ', this->w); - if (scrollH < oldLen) - RichString_printoffnVal(old, y + this->oldSelected - first, x, - scrollH, MINIMUM(oldLen - scrollH, this->w)); - attrset(selectionColor); - mvhline(y + this->selected - first, x + 0, ' ', this->w); - RichString_setAttr(&new, selectionColor); - if (scrollH < newLen) - RichString_printoffnVal(new, y + this->selected - first, x, - scrollH, MINIMUM(newLen - scrollH, this->w)); - attrset(CRT_colors[RESET_COLOR]); - RichString_delete(&new); - RichString_delete(&old); - } - - if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) { - if (Panel_drawFunctionBarFn(this)) - Panel_drawFunctionBar(this, hideFunctionBar); - else if (!hideFunctionBar) - FunctionBar_draw(this->currentBar); - } - - this->oldSelected = this->selected; - this->wasFocus = focus; - this->needsRedraw = false; - move(0, 0); -} - -static int Panel_headerHeight(const Panel* this) { - return RichString_sizeVal(this->header) > 0 ? 1 : 0; -} - -bool Panel_onKey(Panel* this, int key) { - assert (this != NULL); - - const int size = Vector_size(this->items); - - #define PANEL_SCROLL(amount) \ - do { \ - this->selected += (amount); \ - this->scrollV = CLAMP(this->scrollV + (amount), 0, MAXIMUM(0, (size - this->h - Panel_headerHeight(this)))); \ - this->needsRedraw = true; \ - } while (0) - - switch (key) { - case KEY_DOWN: - case KEY_CTRL('N'): - #ifdef KEY_C_DOWN - case KEY_C_DOWN: - #endif - this->selected++; - break; - - case KEY_UP: - case KEY_CTRL('P'): - #ifdef KEY_C_UP - case KEY_C_UP: - #endif - this->selected--; - break; - - case KEY_LEFT: - case KEY_CTRL('B'): - if (this->scrollH > 0) { - this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0); - this->needsRedraw = true; - } - break; - - case KEY_RIGHT: - case KEY_CTRL('F'): - this->scrollH += CRT_scrollHAmount; - this->needsRedraw = true; - break; - - case KEY_PPAGE: - PANEL_SCROLL(-(this->h - Panel_headerHeight(this))); - break; - - case KEY_NPAGE: - PANEL_SCROLL(+(this->h - Panel_headerHeight(this))); - break; - - case KEY_WHEELUP: - PANEL_SCROLL(-CRT_scrollWheelVAmount); - break; - - case KEY_WHEELDOWN: - PANEL_SCROLL(+CRT_scrollWheelVAmount); - break; - - case KEY_HOME: - this->selected = 0; - break; - - case KEY_END: - this->selected = size - 1; - break; - - case KEY_CTRL('A'): - case '^': - this->scrollH = 0; - this->needsRedraw = true; - break; - case KEY_CTRL('E'): - case '$': - this->scrollH = MAXIMUM(this->selectedLen - this->w, 0); - this->needsRedraw = true; - break; - default: - return false; - } - - #undef PANEL_SCROLL - - // ensure selection within bounds - if (this->selected < 0 || size == 0) { - this->selected = 0; - this->needsRedraw = true; - } else if (this->selected >= size) { - this->selected = size - 1; - this->needsRedraw = true; - } - - return true; -} - - -HandlerResult Panel_selectByTyping(Panel* this, int ch) { - int size = Panel_size(this); - - if (!this->eventHandlerState) - this->eventHandlerState = xCalloc(100, sizeof(char)); - char* buffer = this->eventHandlerState; - - if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) { - int len = strlen(buffer); - if (!len) { - if ('/' == ch) { - ch = '\001'; - } else if ('q' == ch) { - return BREAK_LOOP; - } - } else if (1 == len && '\001' == buffer[0]) { - len--; - } - - if (len < 99) { - buffer[len] = ch; - buffer[len+1] = '\0'; - } - - for (int try = 0; try < 2; try++) { - len = strlen(buffer); - for (int i = 0; i < size; i++) { - const char* cur = ((ListItem*) Panel_get(this, i))->value; - while (*cur == ' ') cur++; - if (strncasecmp(cur, buffer, len) == 0) { - Panel_setSelected(this, i); - return HANDLED; - } - } - - // if current word did not match, - // retry considering the character the start of a new word. - buffer[0] = ch; - buffer[1] = '\0'; - } - - return HANDLED; - } else if (ch != ERR) { - buffer[0] = '\0'; - } - - if (ch == 13) { - return BREAK_LOOP; - } - - return IGNORED; -} diff -Nru pcp-5.3.1/src/pcp/htop/Panel.h pcp-5.3.2/src/pcp/htop/Panel.h --- pcp-5.3.1/src/pcp/htop/Panel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Panel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -#ifndef HEADER_Panel -#define HEADER_Panel -/* -htop - Panel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "Object.h" -#include "RichString.h" -#include "Vector.h" - - -struct Panel_; -typedef struct Panel_ Panel; - -typedef enum HandlerResult_ { - HANDLED = 0x01, - IGNORED = 0x02, - BREAK_LOOP = 0x04, - REFRESH = 0x08, - REDRAW = 0x10, - RESCAN = 0x20, - SYNTH_KEY = 0x40, -} HandlerResult; - -#define EVENT_SET_SELECTED (-1) - -#define EVENT_HEADER_CLICK(x_) (-10000 + (x_)) -#define EVENT_IS_HEADER_CLICK(ev_) ((ev_) >= -10000 && (ev_) <= -9000) -#define EVENT_HEADER_CLICK_GET_X(ev_) ((ev_) + 10000) - -typedef HandlerResult (*Panel_EventHandler)(Panel*, int); -typedef void (*Panel_DrawFunctionBar)(Panel*, bool); -typedef void (*Panel_PrintHeader)(Panel*); - -typedef struct PanelClass_ { - const ObjectClass super; - const Panel_EventHandler eventHandler; - const Panel_DrawFunctionBar drawFunctionBar; - const Panel_PrintHeader printHeader; -} PanelClass; - -#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass)) -#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler -#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_)) -#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar -#define Panel_drawFunctionBar(this_, hideFB_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_), hideFB_)) -#define Panel_printHeaderFn(this_) As_Panel(this_)->printHeader -#define Panel_printHeader(this_) (assert(As_Panel(this_)->printHeader), As_Panel(this_)->printHeader((Panel*)(this_))) - -struct Panel_ { - Object super; - int x, y, w, h; - Vector* items; - int selected; - int oldSelected; - int selectedLen; - void* eventHandlerState; - int scrollV; - short scrollH; - bool needsRedraw; - bool wasFocus; - FunctionBar* currentBar; - FunctionBar* defaultBar; - RichString header; - ColorElements selectionColorId; -}; - -#define Panel_setDefaultBar(this_) do { (this_)->currentBar = (this_)->defaultBar; } while (0) - -#define KEY_CTRL(l) ((l)-'A'+1) - -extern const PanelClass Panel_class; - -Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar); - -void Panel_delete(Object* cast); - -void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar); - -void Panel_done(Panel* this); - -void Panel_setSelectionColor(Panel* this, ColorElements colorId); - -void Panel_setHeader(Panel* this, const char* header); - -void Panel_move(Panel* this, int x, int y); - -void Panel_resize(Panel* this, int w, int h); - -void Panel_prune(Panel* this); - -void Panel_add(Panel* this, Object* o); - -void Panel_insert(Panel* this, int i, Object* o); - -void Panel_set(Panel* this, int i, Object* o); - -Object* Panel_get(Panel* this, int i); - -Object* Panel_remove(Panel* this, int i); - -Object* Panel_getSelected(Panel* this); - -void Panel_moveSelectedUp(Panel* this); - -void Panel_moveSelectedDown(Panel* this); - -int Panel_getSelectedIndex(const Panel* this); - -int Panel_size(const Panel* this); - -void Panel_setSelected(Panel* this, int selected); - -void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar); - -void Panel_splice(Panel* this, Vector* from); - -bool Panel_onKey(Panel* this, int key); - -HandlerResult Panel_selectByTyping(Panel* this, int ch); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/pcp/PCPProcess.c pcp-5.3.2/src/pcp/htop/pcp/PCPProcess.c --- pcp-5.3.1/src/pcp/htop/pcp/PCPProcess.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/PCPProcess.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,517 +0,0 @@ -/* -htop - PCPProcess.c -(C) 2014 Hisham H. Muhammad -(C) 2020 htop dev team -(C) 2020-2021 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "PCPProcess.h" - -#include -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "Process.h" -#include "ProvideCurses.h" -#include "XUtils.h" - -/* Used to identify kernel threads in Comm column */ -static const char *const kthreadID = "KTHREAD"; - -const ProcessFieldData Process_fields[] = { - [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, - [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, - [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, - [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging, I idle)", .flags = 0, }, - [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, }, - [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, }, - [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, }, - [TTY_NR] = { .name = "TTY_NR", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, - [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, }, - [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, - [CMINFLT] = { .name = "CMINFLT", .title = " CMINFLT ", .description = "Children processes' minor faults", .flags = 0, .defaultSortDesc = true, }, - [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, - [CMAJFLT] = { .name = "CMAJFLT", .title = " CMAJFLT ", .description = "Children processes' major faults", .flags = 0, .defaultSortDesc = true, }, - [UTIME] = { .name = "UTIME", .title = " UTIME+ ", .description = "User CPU time - time the process spent executing in user mode", .flags = 0, .defaultSortDesc = true, }, - [STIME] = { .name = "STIME", .title = " STIME+ ", .description = "System CPU time - time the kernel spent running system calls for this process", .flags = 0, .defaultSortDesc = true, }, - [CUTIME] = { .name = "CUTIME", .title = " CUTIME+ ", .description = "Children processes' user CPU time", .flags = 0, .defaultSortDesc = true, }, - [CSTIME] = { .name = "CSTIME", .title = " CSTIME+ ", .description = "Children processes' system CPU time", .flags = 0, .defaultSortDesc = true, }, - [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, - [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, - [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, - [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "If of the CPU the process last executed on", .flags = 0, }, - [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, - [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, - [M_SHARE] = { .name = "M_SHARE", .title = " SHR ", .description = "Size of the process's shared pages", .flags = 0, .defaultSortDesc = true, }, - [M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the text segment of the process", .flags = 0, .defaultSortDesc = true, }, - [M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, }, - [M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, }, - [M_DT] = { .name = "M_DT", .title = " DIRTY ", .description = "Size of the dirty pages of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, }, - [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, - [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, - [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, - [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, - [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, - [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, - [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, - [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, }, - [RCHAR] = { .name = "RCHAR", .title = "RCHAR ", .description = "Number of bytes the process has read", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [WCHAR] = { .name = "WCHAR", .title = "WCHAR ", .description = "Number of bytes the process has written", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [SYSCR] = { .name = "SYSCR", .title = " READ_SYSC ", .description = "Number of read(2) syscalls for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [SYSCW] = { .name = "SYSCW", .title = " WRITE_SYSC ", .description = "Number of write(2) syscalls for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [RBYTES] = { .name = "RBYTES", .title = " IO_R ", .description = "Bytes of read(2) I/O for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [WBYTES] = { .name = "WBYTES", .title = " IO_W ", .description = "Bytes of write(2) I/O for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [CNCLWB] = { .name = "CNCLWB", .title = " IO_C ", .description = "Bytes of cancelled write(2) I/O", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [IO_READ_RATE] = { .name = "IO_READ_RATE", .title = " DISK READ ", .description = "The I/O rate of read(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [IO_WRITE_RATE] = { .name = "IO_WRITE_RATE", .title = " DISK WRITE ", .description = "The I/O rate of write(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [IO_RATE] = { .name = "IO_RATE", .title = " DISK R/W ", .description = "Total I/O rate in bytes per second", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, - [CGROUP] = { .name = "CGROUP", .title = " CGROUP ", .description = "Which cgroup the process is in", .flags = PROCESS_FLAG_LINUX_CGROUP, }, - [OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, .defaultSortDesc = true, }, - [PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = 0, .defaultSortDesc = true, }, - [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = 0, .defaultSortDesc = true, }, - [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = 0, .defaultSortDesc = true, }, - [M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it.", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, - [M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, - [M_PSSWP] = { .name = "M_PSSWP", .title = " PSSWP ", .description = "shows proportional swap share of this mapping, Unlike \"Swap\", this does not take into account swapped out page of underlying shmem objects.", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, - [CTXT] = { .name = "CTXT", .title = " CTXT ", .description = "Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches)", .flags = PROCESS_FLAG_LINUX_CTXT, .defaultSortDesc = true, }, - [SECATTR] = { .name = "SECATTR", .title = " Security Attribute ", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, }, - [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process from /proc/[pid]/comm", .flags = 0, }, -}; - -/* This function returns the string displayed in Command column, so that sorting - * happens on what is displayed - whether comm, full path, basename, etc.. So - * this follows PCPProcess_writeField(COMM) and PCPProcess_writeCommand */ -static const char* PCPProcess_getCommandStr(const Process *this) { - const PCPProcess *pp = (const PCPProcess *)this; - if ((Process_isUserlandThread(this) && this->settings->showThreadNames) || !pp->mergedCommand.str) { - return this->comm; - } - return pp->mergedCommand.str; -} - -Process* PCPProcess_new(const Settings* settings) { - PCPProcess* this = xCalloc(1, sizeof(PCPProcess)); - Object_setClass(this, Class(PCPProcess)); - Process_init(&this->super, settings); - return &this->super; -} - -void Process_delete(Object* cast) { - PCPProcess* this = (PCPProcess*) cast; - Process_done((Process*)cast); - free(this->cgroup); - free(this->secattr); - free(this->ttyDevice); - free(this->procComm); - free(this->mergedCommand.str); - free(this); -} - -static void PCPProcess_printDelay(float delay_percent, char* buffer, int n) { - if (isnan(delay_percent)) { - xSnprintf(buffer, n, " N/A "); - } else { - xSnprintf(buffer, n, "%4.1f ", delay_percent); - } -} - -/* -TASK_COMM_LEN is defined to be 16 for /proc/[pid]/comm in man proc(5), but is -not available in an userspace header - so define it. Note: when colorizing a -basename with the comm prefix, the entire basename (not just the comm prefix) -is colorized for better readability, and it is implicit that only up to -(TASK_COMM_LEN - 1) could be comm. -*/ -#define TASK_COMM_LEN 16 - -/* -This function makes the merged Command string. It also stores the offsets of -the basename, comm w.r.t the merged Command string - these offsets will be used -by PCPProcess_writeCommand() for coloring. The merged Command string is also -returned by PCPProcess_getCommandStr() for searching, sorting and filtering. -*/ -void PCPProcess_makeCommandStr(Process* this) { - PCPProcess *pp = (PCPProcess *)this; - PCPProcessMergedCommand *mc = &pp->mergedCommand; - - bool showMergedCommand = this->settings->showMergedCommand; - bool showProgramPath = this->settings->showProgramPath; - bool searchCommInCmdline = this->settings->findCommInCmdline; - - /* pp->mergedCommand.str needs updating only if its state or contents - * changed. Its content is based on the fields cmdline and comm. */ - if ( - mc->prevMergeSet == showMergedCommand && - mc->prevPathSet == showProgramPath && - mc->prevCommSet == searchCommInCmdline && - !mc->cmdlineChanged && - !mc->commChanged - ) { - return; - } - - /* The field separtor "│" has been chosen such that it will not match any - * valid string used for searching or filtering */ - const char *SEPARATOR = CRT_treeStr[TREE_STR_VERT]; - const int SEPARATOR_LEN = strlen(SEPARATOR); - - /* Check for any changed fields since we last built this string */ - if (mc->cmdlineChanged || mc->commChanged) { - free(mc->str); - /* Accommodate the column text, two field separators and terminating NUL */ - mc->str = xCalloc(1, mc->maxLen + 2*SEPARATOR_LEN + 1); - } - - /* Preserve the settings used in this run */ - mc->prevMergeSet = showMergedCommand; - mc->prevPathSet = showProgramPath; - mc->prevCommSet = searchCommInCmdline; - - /* Mark everything as unchanged */ - mc->cmdlineChanged = false; - mc->commChanged = false; - - /* Clear any separators */ - mc->sep1 = 0; - mc->sep2 = 0; - /* Clear any highlighting locations */ - mc->baseStart = 0; - mc->baseEnd = 0; - mc->commStart = 0; - mc->commEnd = 0; - - const char *cmdline = this->comm; - const char *procComm = pp->procComm; - - char *strStart = mc->str; - char *str = strStart; - - int cmdlineBasenameOffset = pp->procCmdlineBasenameOffset; - int cmdlineBasenameEnd = pp->procCmdlineBasenameEnd; - - if (!cmdline) { - cmdlineBasenameOffset = 0; - cmdlineBasenameEnd = 0; - cmdline = "(zombie)"; - } - - assert(cmdlineBasenameOffset >= 0); - assert(cmdlineBasenameOffset <= (int)strlen(cmdline)); - - if (showMergedCommand && procComm && strlen(procComm)) { /* Prefix column with comm */ - if (strncmp(cmdline + cmdlineBasenameOffset, procComm, MINIMUM(TASK_COMM_LEN - 1, strlen(procComm))) != 0) { - mc->commStart = 0; - mc->commEnd = strlen(procComm); - - str = stpcpy(str, procComm); - - mc->sep1 = str - strStart; - str = stpcpy(str, SEPARATOR); - } - } - - if (showProgramPath) { - (void) stpcpy(str, cmdline); - mc->baseStart = cmdlineBasenameOffset; - mc->baseEnd = cmdlineBasenameEnd; - } else { - (void) stpcpy(str, cmdline + cmdlineBasenameOffset); - mc->baseStart = 0; - mc->baseEnd = cmdlineBasenameEnd - cmdlineBasenameOffset; - } - - if (mc->sep1) { - mc->baseStart += str - strStart - SEPARATOR_LEN + 1; - mc->baseEnd += str - strStart - SEPARATOR_LEN + 1; - } -} - -static void PCPProcess_writeCommand(const Process* this, int attr, int baseAttr, RichString* str) { - const PCPProcess *pp = (const PCPProcess *)this; - const PCPProcessMergedCommand *mc = &pp->mergedCommand; - - int strStart = RichString_size(str); - - int baseStart = strStart + pp->mergedCommand.baseStart; - int baseEnd = strStart + pp->mergedCommand.baseEnd; - int commStart = strStart + pp->mergedCommand.commStart; - int commEnd = strStart + pp->mergedCommand.commEnd; - - int commAttr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM]; - - bool highlightBaseName = this->settings->highlightBaseName; - - RichString_appendWide(str, attr, pp->mergedCommand.str); - - if (pp->mergedCommand.commEnd) { - if (!pp->mergedCommand.separateComm && commStart == baseStart && highlightBaseName) { - /* If it was matched with binaries basename, make it bold if needed */ - if (commEnd > baseEnd) { - RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - baseStart); - RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - baseEnd); - } else if (commEnd < baseEnd) { - RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - commStart); - RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - commEnd); - } else { - // Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise - RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - commStart); - } - - baseStart = baseEnd; - } else { - RichString_setAttrn(str, commAttr, commStart, commEnd - commStart); - } - } - - if (baseStart < baseEnd && highlightBaseName) { - RichString_setAttrn(str, baseAttr, baseStart, baseEnd - baseStart); - } - - if (mc->sep1) - RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, 1); - if (mc->sep2) - RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, 1); -} - -static void PCPProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) { - /* This code is from Process_writeField for COMM, but we invoke - * PCPProcess_writeCommand to display the full binary path - * (or its basename)│/proc/pid/comm│/proc/pid/cmdline */ - int baseattr = CRT_colors[PROCESS_BASENAME]; - if (this->settings->highlightThreads && Process_isThread(this)) { - attr = CRT_colors[PROCESS_THREAD]; - baseattr = CRT_colors[PROCESS_THREAD_BASENAME]; - } - if (!this->settings->treeView || this->indent == 0) { - PCPProcess_writeCommand(this, attr, baseattr, str); - } else { - char* buf = buffer; - int maxIndent = 0; - bool lastItem = (this->indent < 0); - int indent = (this->indent < 0 ? -this->indent : this->indent); - int vertLen = strlen(CRT_treeStr[TREE_STR_VERT]); - - for (int i = 0; i < 32; i++) { - if (indent & (1U << i)) { - maxIndent = i+1; - } - } - for (int i = 0; i < maxIndent - 1; i++) { - if (indent & (1 << i)) { - if (buf - buffer + (vertLen + 3) > n) { - break; - } - buf = stpcpy(buf, CRT_treeStr[TREE_STR_VERT]); - buf = stpcpy(buf, " "); - } else { - if (buf - buffer + 4 > n) { - break; - } - buf = stpcpy(buf, " "); - } - } - - n -= (buf - buffer); - const char* draw = CRT_treeStr[lastItem ? TREE_STR_BEND : TREE_STR_RTEE]; - xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] ); - RichString_appendWide(str, CRT_colors[PROCESS_TREE], buffer); - PCPProcess_writeCommand(this, attr, baseattr, str); - } -} - -static void PCPProcess_writeField(const Process* this, RichString* str, ProcessField field) { - const PCPProcess* pp = (const PCPProcess*) this; - bool coloring = this->settings->highlightMegabytes; - char buffer[256]; buffer[255] = '\0'; - int attr = CRT_colors[DEFAULT_COLOR]; - int n = sizeof(buffer) - 1; - switch ((int)field) { - case TTY_NR: - if (pp->ttyDevice) { - xSnprintf(buffer, n, "%-8s", pp->ttyDevice + 5 /* skip "/dev/" */); - break; - } - Process_writeField(this, str, field); - break; - case CMINFLT: Process_colorNumber(str, pp->cminflt, coloring); return; - case CMAJFLT: Process_colorNumber(str, pp->cmajflt, coloring); return; - case M_DRS: Process_humanNumber(str, pp->m_drs, coloring); return; - case M_DT: Process_humanNumber(str, pp->m_dt, coloring); return; - case M_LRS: Process_humanNumber(str, pp->m_lrs, coloring); return; - case M_TRS: Process_humanNumber(str, pp->m_trs, coloring); return; - case M_SHARE: Process_humanNumber(str, pp->m_share, coloring); return; - case M_PSS: Process_humanNumber(str, pp->m_pss, coloring); return; - case M_SWAP: Process_humanNumber(str, pp->m_swap, coloring); return; - case M_PSSWP: Process_humanNumber(str, pp->m_psswp, coloring); return; - case UTIME: Process_printTime(str, pp->utime); return; - case STIME: Process_printTime(str, pp->stime); return; - case CUTIME: Process_printTime(str, pp->cutime); return; - case CSTIME: Process_printTime(str, pp->cstime); return; - case RCHAR: Process_humanNumber(str, pp->io_rchar, coloring); return; - case WCHAR: Process_humanNumber(str, pp->io_wchar, coloring); return; - case SYSCR: Process_colorNumber(str, pp->io_syscr, coloring); return; - case SYSCW: Process_colorNumber(str, pp->io_syscw, coloring); return; - case RBYTES: Process_humanNumber(str, pp->io_read_bytes, coloring); return; - case WBYTES: Process_humanNumber(str, pp->io_write_bytes, coloring); return; - case CNCLWB: Process_humanNumber(str, pp->io_cancelled_write_bytes, coloring); return; - case IO_READ_RATE: Process_outputRate(str, buffer, n, pp->io_rate_read_bps, coloring); return; - case IO_WRITE_RATE: Process_outputRate(str, buffer, n, pp->io_rate_write_bps, coloring); return; - case IO_RATE: { - double totalRate = NAN; - if (!isnan(pp->io_rate_read_bps) && !isnan(pp->io_rate_write_bps)) - totalRate = pp->io_rate_read_bps + pp->io_rate_write_bps; - else if (!isnan(pp->io_rate_read_bps)) - totalRate = pp->io_rate_read_bps; - else if (!isnan(pp->io_rate_write_bps)) - totalRate = pp->io_rate_write_bps; - else - totalRate = NAN; - Process_outputRate(str, buffer, n, totalRate, coloring); return; - } - case CGROUP: xSnprintf(buffer, n, "%-10s ", pp->cgroup ? pp->cgroup : ""); break; - case OOM: xSnprintf(buffer, n, "%4u ", pp->oom); break; - case PERCENT_CPU_DELAY: - PCPProcess_printDelay(pp->cpu_delay_percent, buffer, n); - break; - case PERCENT_IO_DELAY: - PCPProcess_printDelay(pp->blkio_delay_percent, buffer, n); - break; - case PERCENT_SWAP_DELAY: - PCPProcess_printDelay(pp->swapin_delay_percent, buffer, n); - break; - case CTXT: - if (pp->ctxt_diff > 1000) { - attr |= A_BOLD; - } - xSnprintf(buffer, n, "%5lu ", pp->ctxt_diff); - break; - case SECATTR: snprintf(buffer, n, "%-30s ", pp->secattr ? pp->secattr : "?"); break; - case COMM: { - if ((Process_isUserlandThread(this) && this->settings->showThreadNames) || !pp->mergedCommand.str) { - Process_writeField(this, str, field); - } else { - PCPProcess_writeCommandField(this, str, buffer, n, attr); - } - return; - } - case PROC_COMM: { - const char* procComm; - if (pp->procComm) { - attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM]; - procComm = pp->procComm; - } else { - attr = CRT_colors[PROCESS_SHADOW]; - procComm = Process_isKernelThread(this) ? kthreadID : "N/A"; - } - /* 15 being (TASK_COMM_LEN - 1) */ - Process_printLeftAlignedField(str, attr, procComm, 15); - return; - } - default: - Process_writeField(this, str, field); - return; - } - RichString_appendWide(str, attr, buffer); -} - -static double adjustNaN(double num) { - if (isnan(num)) - return -0.0005; - - return num; -} - -static int PCPProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { - const PCPProcess* p1 = (const PCPProcess*)v1; - const PCPProcess* p2 = (const PCPProcess*)v2; - - switch (key) { - case M_DRS: - return SPACESHIP_NUMBER(p1->m_drs, p2->m_drs); - case M_DT: - return SPACESHIP_NUMBER(p1->m_dt, p2->m_dt); - case M_LRS: - return SPACESHIP_NUMBER(p1->m_lrs, p2->m_lrs); - case M_TRS: - return SPACESHIP_NUMBER(p1->m_trs, p2->m_trs); - case M_SHARE: - return SPACESHIP_NUMBER(p1->m_share, p2->m_share); - case M_PSS: - return SPACESHIP_NUMBER(p1->m_pss, p2->m_pss); - case M_SWAP: - return SPACESHIP_NUMBER(p1->m_swap, p2->m_swap); - case M_PSSWP: - return SPACESHIP_NUMBER(p1->m_psswp, p2->m_psswp); - case UTIME: - return SPACESHIP_NUMBER(p1->utime, p2->utime); - case CUTIME: - return SPACESHIP_NUMBER(p1->cutime, p2->cutime); - case STIME: - return SPACESHIP_NUMBER(p1->stime, p2->stime); - case CSTIME: - return SPACESHIP_NUMBER(p1->cstime, p2->cstime); - case RCHAR: - return SPACESHIP_NUMBER(p1->io_rchar, p2->io_rchar); - case WCHAR: - return SPACESHIP_NUMBER(p1->io_wchar, p2->io_wchar); - case SYSCR: - return SPACESHIP_NUMBER(p1->io_syscr, p2->io_syscr); - case SYSCW: - return SPACESHIP_NUMBER(p1->io_syscw, p2->io_syscw); - case RBYTES: - return SPACESHIP_NUMBER(p1->io_read_bytes, p2->io_read_bytes); - case WBYTES: - return SPACESHIP_NUMBER(p1->io_write_bytes, p2->io_write_bytes); - case CNCLWB: - return SPACESHIP_NUMBER(p1->io_cancelled_write_bytes, p2->io_cancelled_write_bytes); - case IO_READ_RATE: - return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps), adjustNaN(p2->io_rate_read_bps)); - case IO_WRITE_RATE: - return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_write_bps)); - case IO_RATE: - return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps) + adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_read_bps) + adjustNaN(p2->io_rate_write_bps)); - case CGROUP: - return SPACESHIP_NULLSTR(p1->cgroup, p2->cgroup); - case OOM: - return SPACESHIP_NUMBER(p1->oom, p1->oom); - case PERCENT_CPU_DELAY: - return SPACESHIP_NUMBER(p1->cpu_delay_percent, p1->cpu_delay_percent); - case PERCENT_IO_DELAY: - return SPACESHIP_NUMBER(p1->blkio_delay_percent, p1->blkio_delay_percent); - case PERCENT_SWAP_DELAY: - return SPACESHIP_NUMBER(p1->swapin_delay_percent, p1->swapin_delay_percent); - case CTXT: - return SPACESHIP_NUMBER(p1->ctxt_diff, p1->ctxt_diff); - case SECATTR: - return SPACESHIP_NULLSTR(p1->secattr, p2->secattr); - case PROC_COMM: { - const char *comm1 = p1->procComm ? p1->procComm : (Process_isKernelThread(v1) ? kthreadID : ""); - const char *comm2 = p2->procComm ? p2->procComm : (Process_isKernelThread(v2) ? kthreadID : ""); - return strcmp(comm1, comm2); - } - default: - return Process_compareByKey_Base(v1, v2, key); - } -} - -bool Process_isThread(const Process* this) { - return (Process_isUserlandThread(this) || Process_isKernelThread(this)); -} - -const ProcessClass PCPProcess_class = { - .super = { - .extends = Class(Process), - .display = Process_display, - .delete = Process_delete, - .compare = Process_compare - }, - .writeField = PCPProcess_writeField, - .getCommandStr = PCPProcess_getCommandStr, - .compareByKey = PCPProcess_compareByKey -}; diff -Nru pcp-5.3.1/src/pcp/htop/pcp/PCPProcess.h pcp-5.3.2/src/pcp/htop/pcp/PCPProcess.h --- pcp-5.3.1/src/pcp/htop/pcp/PCPProcess.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/PCPProcess.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,140 +0,0 @@ -#ifndef HEADER_PCPProcess -#define HEADER_PCPProcess -/* -htop - PCPProcess.h -(C) 2014 Hisham H. Muhammad -(C) 2020 htop dev team -(C) 2020-2021 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" - -#include -#include - -#include "Object.h" -#include "Process.h" -#include "RichString.h" -#include "Settings.h" - -#define PROCESS_FLAG_LINUX_CGROUP 0x0800 -#define PROCESS_FLAG_LINUX_OOM 0x1000 -#define PROCESS_FLAG_LINUX_SMAPS 0x2000 -#define PROCESS_FLAG_LINUX_CTXT 0x4000 -#define PROCESS_FLAG_LINUX_SECATTR 0x8000 - -/* PCPProcessMergedCommand is populated by PCPProcess_makeCommandStr: It - * contains the merged Command string, and the information needed by - * PCPProcess_writeCommand to color the string. str will be NULL for kernel - * threads and zombies */ -typedef struct PCPProcessMergedCommand_ { - char *str; /* merged Command string */ - int maxLen; /* maximum expected length of Command string */ - int baseStart; /* basename's start offset */ - int baseEnd; /* basename's end offset */ - int commStart; /* comm's start offset */ - int commEnd; /* comm's end offset */ - int sep1; /* first field separator, used if non-zero */ - int sep2; /* second field separator, used if non-zero */ - bool separateComm; /* whether comm is a separate field */ - bool cmdlineChanged; /* whether cmdline changed */ - bool commChanged; /* whether comm changed */ - bool prevMergeSet; /* whether showMergedCommand was set */ - bool prevPathSet; /* whether showProgramPath was set */ - bool prevCommSet; /* whether findCommInCmdline was set */ - bool prevCmdlineSet; /* whether findCommInCmdline was set */ -} PCPProcessMergedCommand; - -typedef struct PCPProcess_ { - Process super; - char *procComm; - int procCmdlineBasenameOffset; - int procCmdlineBasenameEnd; - PCPProcessMergedCommand mergedCommand; - bool isKernelThread; - unsigned long int cminflt; - unsigned long int cmajflt; - unsigned long long int utime; - unsigned long long int stime; - unsigned long long int cutime; - unsigned long long int cstime; - long m_share; - long m_pss; - long m_swap; - long m_psswp; - long m_trs; - long m_drs; - long m_lrs; - long m_dt; - - /* Data read (in kilobytes) */ - unsigned long long io_rchar; - - /* Data written (in kilobytes) */ - unsigned long long io_wchar; - - /* Number of read(2) syscalls */ - unsigned long long io_syscr; - - /* Number of write(2) syscalls */ - unsigned long long io_syscw; - - /* Storage data read (in kilobytes) */ - unsigned long long io_read_bytes; - - /* Storage data written (in kilobytes) */ - unsigned long long io_write_bytes; - - /* Storage data cancelled (in kilobytes) */ - unsigned long long io_cancelled_write_bytes; - - /* Point in time of last io scan (in seconds elapsed since the Epoch) */ - unsigned long long io_last_scan_time; - - double io_rate_read_bps; - double io_rate_write_bps; - char* cgroup; - unsigned int oom; - char* ttyDevice; - unsigned long long int delay_read_time; - unsigned long long cpu_delay_total; - unsigned long long blkio_delay_total; - unsigned long long swapin_delay_total; - float cpu_delay_percent; - float blkio_delay_percent; - float swapin_delay_percent; - unsigned long ctxt_total; - unsigned long ctxt_diff; - char* secattr; - unsigned long long int last_mlrs_calctime; -} PCPProcess; - -static inline void Process_setKernelThread(Process* this, bool truth) { - ((PCPProcess*)this)->isKernelThread = truth; -} - -static inline bool Process_isKernelThread(const Process* this) { - return ((const PCPProcess*)this)->isKernelThread; -} - -static inline bool Process_isUserlandThread(const Process* this) { - return this->pid != this->tgid; -} - -extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; - -extern const ProcessClass PCPProcess_class; - -Process* PCPProcess_new(const Settings* settings); - -void Process_delete(Object* cast); - -/* This function constructs the string that is displayed by - * PCPProcess_writeCommand and also returned by PCPProcess_getCommandStr */ -void PCPProcess_makeCommandStr(Process *this); - -bool Process_isThread(const Process* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/pcp/PCPProcessList.c pcp-5.3.2/src/pcp/htop/pcp/PCPProcessList.c --- pcp-5.3.1/src/pcp/htop/pcp/PCPProcessList.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/PCPProcessList.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,816 +0,0 @@ -/* -htop - PCPProcessList.c -(C) 2014 Hisham H. Muhammad -(C) 2020-2021 htop dev team -(C) 2020-2021 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "PCPProcessList.h" - -#include - -#include "CRT.h" -#include "Macros.h" -#include "Object.h" -#include "PCPProcess.h" -#include "Process.h" -#include "Settings.h" -#include "XUtils.h" - - -static int PCPProcessList_computeCPUcount(void) { - int cpus; - if ((cpus = Platform_getMaxCPU()) <= 0) - cpus = Metric_instanceCount(PCP_PERCPU_SYSTEM); - return cpus > 1 ? cpus : 1; -} - -static void PCPProcessList_updateCPUcount(PCPProcessList* this) { - ProcessList* pl = &(this->super); - unsigned int cpus = PCPProcessList_computeCPUcount(); - if (cpus == pl->cpuCount) - return; - - pl->cpuCount = cpus; - free(this->percpu); - free(this->values); - - this->percpu = xCalloc(cpus, sizeof(pmAtomValue *)); - for (unsigned int i = 0; i < cpus; i++) - this->percpu[i] = xCalloc(CPU_METRIC_COUNT, sizeof(pmAtomValue)); - this->values = xCalloc(cpus, sizeof(pmAtomValue)); -} - -static char* setUser(UsersTable* this, unsigned int uid, int pid, int offset) { - char* name = Hashtable_get(this->users, uid); - if (name) - return name; - - pmAtomValue value; - if (Metric_instance(PCP_PROC_ID_USER, pid, offset, &value, PM_TYPE_STRING)) { - Hashtable_put(this->users, uid, value.cp); - name = value.cp; - } - return name; -} - -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) { - PCPProcessList* this = xCalloc(1, sizeof(PCPProcessList)); - ProcessList* super = &(this->super); - - ProcessList_init(super, Class(PCPProcess), usersTable, pidMatchList, userId); - - struct timeval timestamp; - gettimeofday(×tamp, NULL); - this->timestamp = pmtimevalToReal(×tamp); - - this->cpu = xCalloc(CPU_METRIC_COUNT, sizeof(pmAtomValue)); - PCPProcessList_updateCPUcount(this); - - return super; -} - -void ProcessList_delete(ProcessList* pl) { - PCPProcessList* this = (PCPProcessList*) pl; - ProcessList_done(pl); - free(this->values); - for (unsigned int i = 0; i < pl->cpuCount; i++) - free(this->percpu[i]); - free(this->percpu); - free(this->cpu); - free(this); -} - -static inline unsigned long long PCPProcessList_adjustTime(unsigned long long t) { - return t / 10; -} - -static void PCPProcessList_updateID(Process* process, int pid, int offset) { - pmAtomValue value; - - if (Metric_instance(PCP_PROC_TGID, pid, offset, &value, PM_TYPE_U32)) - process->tgid = value.ul; - else - process->tgid = 1; - - if (Metric_instance(PCP_PROC_PPID, pid, offset, &value, PM_TYPE_U32)) - process->ppid = value.ul; - else - process->ppid = 1; - - if (Metric_instance(PCP_PROC_STATE, pid, offset, &value, PM_TYPE_STRING)) { - process->state = value.cp[0]; - free(value.cp); - } else { - process->state = 'X'; - } -} - -static void PCPProcessList_updateInfo(Process* process, int pid, int offset, char* command, size_t commLen) { - PCPProcess* pp = (PCPProcess*) process; - pmAtomValue value; - - if (!Metric_instance(PCP_PROC_CMD, pid, offset, &value, PM_TYPE_STRING)) - value.cp = xStrdup(""); - String_safeStrncpy(command, value.cp, commLen); - free(value.cp); - - if (Metric_instance(PCP_PROC_PGRP, pid, offset, &value, PM_TYPE_U32)) - process->pgrp = value.ul; - else - process->pgrp = 0; - - if (Metric_instance(PCP_PROC_SESSION, pid, offset, &value, PM_TYPE_U32)) - process->session = value.ul; - else - process->session = 0; - - if (Metric_instance(PCP_PROC_TTY, pid, offset, &value, PM_TYPE_U32)) - process->tty_nr = value.ul; - else - process->tty_nr = 0; - - if (Metric_instance(PCP_PROC_TTYPGRP, pid, offset, &value, PM_TYPE_U32)) - process->tpgid = value.ul; - else - process->tpgid = 0; - - if (Metric_instance(PCP_PROC_MINFLT, pid, offset, &value, PM_TYPE_U32)) - process->minflt = value.ul; - else - process->minflt = 0; - - if (Metric_instance(PCP_PROC_CMINFLT, pid, offset, &value, PM_TYPE_U32)) - pp->cminflt = value.ul; - else - pp->cminflt = 0; - - if (Metric_instance(PCP_PROC_MAJFLT, pid, offset, &value, PM_TYPE_U32)) - process->majflt = value.ul; - else - process->majflt = 0; - - if (Metric_instance(PCP_PROC_CMAJFLT, pid, offset, &value, PM_TYPE_U32)) - pp->cmajflt = value.ul; - else - pp->cmajflt = 0; - - if (Metric_instance(PCP_PROC_UTIME, pid, offset, &value, PM_TYPE_U64)) - pp->utime = PCPProcessList_adjustTime(value.ull); - else - pp->utime = 0; - - if (Metric_instance(PCP_PROC_STIME, pid, offset, &value, PM_TYPE_U64)) - pp->stime = PCPProcessList_adjustTime(value.ull); - else - pp->stime = 0; - - if (Metric_instance(PCP_PROC_CUTIME, pid, offset, &value, PM_TYPE_U64)) - pp->cutime = PCPProcessList_adjustTime(value.ull); - else - pp->cutime = 0; - - if (Metric_instance(PCP_PROC_CSTIME, pid, offset, &value, PM_TYPE_U64)) - pp->cstime = PCPProcessList_adjustTime(value.ull); - else - pp->cstime = 0; - - if (Metric_instance(PCP_PROC_PRIORITY, pid, offset, &value, PM_TYPE_U32)) - process->priority = value.ul; - else - process->priority = 0; - - if (Metric_instance(PCP_PROC_NICE, pid, offset, &value, PM_TYPE_32)) - process->nice = value.l; - else - process->nice = 0; - - if (Metric_instance(PCP_PROC_THREADS, pid, offset, &value, PM_TYPE_U32)) - process->nlwp = value.ul; - else - process->nlwp = 0; - - if (Metric_instance(PCP_PROC_STARTTIME, pid, offset, &value, PM_TYPE_U64)) - process->starttime_ctime = PCPProcessList_adjustTime(value.ull); - else - process->starttime_ctime = 0; - - if (Metric_instance(PCP_PROC_PROCESSOR, pid, offset, &value, PM_TYPE_U32)) - process->processor = value.ul; - else - process->processor = 0; - - process->time = pp->utime + pp->stime; -} - -static void PCPProcessList_updateIO(PCPProcess* process, int pid, int offset, unsigned long long now) { - pmAtomValue value; - - if (Metric_instance(PCP_PROC_IO_RCHAR, pid, offset, &value, PM_TYPE_U64)) - process->io_rchar = value.ull / ONE_K; - else - process->io_rchar = ULLONG_MAX; - - if (Metric_instance(PCP_PROC_IO_WCHAR, pid, offset, &value, PM_TYPE_U64)) - process->io_wchar = value.ull / ONE_K; - else - process->io_wchar = ULLONG_MAX; - - if (Metric_instance(PCP_PROC_IO_SYSCR, pid, offset, &value, PM_TYPE_U64)) - process->io_syscr = value.ull; - else - process->io_syscr = ULLONG_MAX; - - if (Metric_instance(PCP_PROC_IO_SYSCW, pid, offset, &value, PM_TYPE_U64)) - process->io_syscw = value.ull; - else - process->io_syscw = ULLONG_MAX; - - if (Metric_instance(PCP_PROC_IO_CANCELLED, pid, offset, &value, PM_TYPE_U64)) - process->io_cancelled_write_bytes = value.ull / ONE_K; - else - process->io_cancelled_write_bytes = ULLONG_MAX; - - if (Metric_instance(PCP_PROC_IO_READB, pid, offset, &value, PM_TYPE_U64)) { - unsigned long long last_read = process->io_read_bytes; - process->io_read_bytes = value.ull / ONE_K; - process->io_rate_read_bps = - ONE_K * (process->io_read_bytes - last_read) / - (now - process->io_last_scan_time); - } else { - process->io_read_bytes = ULLONG_MAX; - process->io_rate_read_bps = NAN; - } - - if (Metric_instance(PCP_PROC_IO_WRITEB, pid, offset, &value, PM_TYPE_U64)) { - unsigned long long last_write = process->io_write_bytes; - process->io_write_bytes = value.ull; - process->io_rate_write_bps = - ONE_K * (process->io_write_bytes - last_write) / - (now - process->io_last_scan_time); - } else { - process->io_write_bytes = ULLONG_MAX; - process->io_rate_write_bps = NAN; - } - - process->io_last_scan_time = now; -} - -static void PCPProcessList_updateMemory(PCPProcess* process, int pid, int offset) { - pmAtomValue value; - - if (Metric_instance(PCP_PROC_MEM_SIZE, pid, offset, &value, PM_TYPE_U32)) - process->super.m_virt = value.ul; - else - process->super.m_virt = 0; - - if (Metric_instance(PCP_PROC_MEM_RSS, pid, offset, &value, PM_TYPE_U32)) - process->super.m_resident = value.ul; - else - process->super.m_resident = 0; - - if (Metric_instance(PCP_PROC_MEM_SHARE, pid, offset, &value, PM_TYPE_U32)) - process->m_share = value.ul; - else - process->m_share = 0; - - if (Metric_instance(PCP_PROC_MEM_TEXTRS, pid, offset, &value, PM_TYPE_U32)) - process->m_trs = value.ul; - else - process->m_trs = 0; - - if (Metric_instance(PCP_PROC_MEM_LIBRS, pid, offset, &value, PM_TYPE_U32)) - process->m_lrs = value.ul; - else - process->m_lrs = 0; - - if (Metric_instance(PCP_PROC_MEM_DATRS, pid, offset, &value, PM_TYPE_U32)) - process->m_drs = value.ul; - else - process->m_drs = 0; - - if (Metric_instance(PCP_PROC_MEM_DIRTY, pid, offset, &value, PM_TYPE_U32)) - process->m_dt = value.ul; - else - process->m_dt = 0; -} - -static void PCPProcessList_updateSmaps(PCPProcess* process, pid_t pid, int offset) { - pmAtomValue value; - - if (Metric_instance(PCP_PROC_SMAPS_PSS, pid, offset, &value, PM_TYPE_U64)) - process->m_pss = value.ull; - else - process->m_pss = 0LL; - - if (Metric_instance(PCP_PROC_SMAPS_SWAP, pid, offset, &value, PM_TYPE_U64)) - process->m_swap = value.ull; - else - process->m_swap = 0LL; - - if (Metric_instance(PCP_PROC_SMAPS_SWAPPSS, pid, offset, &value, PM_TYPE_U64)) - process->m_psswp = value.ull; - else - process->m_psswp = 0LL; -} - -static void PCPProcessList_readOomData(PCPProcess* process, int pid, int offset) { - pmAtomValue value; - if (Metric_instance(PCP_PROC_OOMSCORE, pid, offset, &value, PM_TYPE_U32)) - process->oom = value.ul; - else - process->oom = 0; -} - -static void PCPProcessList_readCtxtData(PCPProcess* process, int pid, int offset) { - pmAtomValue value; - unsigned long ctxt = 0; - - if (Metric_instance(PCP_PROC_VCTXSW, pid, offset, &value, PM_TYPE_U32)) - ctxt += value.ul; - if (Metric_instance(PCP_PROC_NVCTXSW, pid, offset, &value, PM_TYPE_U32)) - ctxt += value.ul; - if (ctxt > process->ctxt_total) - process->ctxt_diff = ctxt - process->ctxt_total; - else - process->ctxt_diff = 0; - process->ctxt_total = ctxt; -} - -static char* setString(Metric metric, int pid, int offset, char* string) { - if (string) - free(string); - pmAtomValue value; - if (Metric_instance(metric, pid, offset, &value, PM_TYPE_STRING)) - string = value.cp; - else - string = NULL; - return string; -} - -static void PCPProcessList_updateTTY(PCPProcess* process, int pid, int offset) { - process->ttyDevice = setString(PCP_PROC_TTYNAME, pid, offset, process->ttyDevice); -} - -static void PCPProcessList_readCGroups(PCPProcess* process, int pid, int offset) { - process->cgroup = setString(PCP_PROC_CGROUPS, pid, offset, process->cgroup); -} - -static void PCPProcessList_readSecattrData(PCPProcess* process, int pid, int offset) { - process->secattr = setString(PCP_PROC_LABELS, pid, offset, process->secattr); -} - -static void PCPProcessList_updateUsername(Process* process, int pid, int offset, UsersTable* users) { - unsigned int uid = 0; - pmAtomValue value; - if (Metric_instance(PCP_PROC_ID_UID, pid, offset, &value, PM_TYPE_U32)) - uid = value.ul; - process->st_uid = uid; - process->user = setUser(users, uid, pid, offset); -} - -static void PCPProcessList_updateCmdline(Process* process, int pid, int offset, const char* comm) { - pmAtomValue value; - if (!Metric_instance(PCP_PROC_PSARGS, pid, offset, &value, PM_TYPE_STRING)) { - if (process->state != 'Z') - Process_setKernelThread(process, true); - else - process->basenameOffset = 0; - return; - } - - char *command = value.cp; - int length = strlen(command); - if (command[0] != '(') { - Process_setKernelThread(process, false); - } else { - ++command; - --length; - if (command[length-1] == ')') - command[length-1] = '\0'; - Process_setKernelThread(process, true); - } - - int tokenEnd = 0; - int tokenStart = 0; - int lastChar = 0; - for (int i = 0; i < length; i++) { - /* htop considers the next character after the last / that is before - * basenameOffset, as the start of the basename in cmdline - see - * Process_writeCommand */ - if (command[i] == '/') - tokenStart = i + 1; - lastChar = i; - } - tokenEnd = length; - - PCPProcess *pp = (PCPProcess *)process; - pp->mergedCommand.maxLen = lastChar + 1; /* accommodate cmdline */ - if (!process->comm || !String_eq(command, process->comm)) { - process->basenameOffset = tokenEnd; - free_and_xStrdup(&process->comm, command); - pp->procCmdlineBasenameOffset = tokenStart; - pp->procCmdlineBasenameEnd = tokenEnd; - pp->mergedCommand.cmdlineChanged = true; - } - - /* comm could change, so should be updated */ - if ((length = strlen(comm)) > 0) { - pp->mergedCommand.maxLen += length; - if (!pp->procComm || !String_eq(command, pp->procComm)) { - free_and_xStrdup(&pp->procComm, command); - pp->mergedCommand.commChanged = true; - } - } else if (pp->procComm) { - free(pp->procComm); - pp->procComm = NULL; - pp->mergedCommand.commChanged = true; - } - - free(value.cp); -} - -static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period, struct timeval* tv) { - ProcessList* pl = (ProcessList*) this; - const Settings* settings = pl->settings; - - bool hideKernelThreads = settings->hideKernelThreads; - bool hideUserlandThreads = settings->hideUserlandThreads; - - unsigned long long now = tv->tv_sec * 1000LL + tv->tv_usec / 1000LL; - int pid = -1, offset = -1; - - /* for every process ... */ - while (Metric_iterate(PCP_PROC_PID, &pid, &offset)) { - - bool preExisting; - Process* proc = ProcessList_getProcess(pl, pid, &preExisting, PCPProcess_new); - PCPProcess* pp = (PCPProcess*) proc; - PCPProcessList_updateID(proc, pid, offset); - - /* - * These conditions will not trigger on first occurrence, cause we need to - * add the process to the ProcessList and do all one time scans - * (e.g. parsing the cmdline to detect a kernel thread) - * But it will short-circuit subsequent scans. - */ - if (preExisting && hideKernelThreads && Process_isKernelThread(proc)) { - proc->updated = true; - proc->show = false; - if (proc->state == 'R') - pl->runningTasks++; - pl->kernelThreads++; - pl->totalTasks++; - continue; - } - if (preExisting && hideUserlandThreads && Process_isUserlandThread(proc)) { - proc->updated = true; - proc->show = false; - if (proc->state == 'R') - pl->runningTasks++; - pl->userlandThreads++; - pl->totalTasks++; - continue; - } - - if (settings->flags & PROCESS_FLAG_IO) - PCPProcessList_updateIO(pp, pid, offset, now); - - PCPProcessList_updateMemory(pp, pid, offset); - - if ((settings->flags & PROCESS_FLAG_LINUX_SMAPS) && - (Process_isKernelThread(proc) == false)) { - if (Metric_enabled(PCP_PROC_SMAPS_PSS)) - PCPProcessList_updateSmaps(pp, pid, offset); - } - - char command[MAX_NAME + 1]; - unsigned int tty_nr = proc->tty_nr; - unsigned long long int lasttimes = pp->utime + pp->stime; - - PCPProcessList_updateInfo(proc, pid, offset, command, sizeof(command)); - proc->starttime_ctime += Platform_getBootTime(); - if (tty_nr != proc->tty_nr) - PCPProcessList_updateTTY(pp, pid, offset); - - float percent_cpu = (pp->utime + pp->stime - lasttimes) / period * 100.0; - proc->percent_cpu = isnan(percent_cpu) ? - 0.0 : CLAMP(percent_cpu, 0.0, pl->cpuCount * 100.0); - proc->percent_mem = proc->m_resident / (double)pl->totalMem * 100.0; - - if (!preExisting) { - PCPProcessList_updateUsername(proc, pid, offset, pl->usersTable); - PCPProcessList_updateCmdline(proc, pid, offset, command); - Process_fillStarttimeBuffer(proc); - ProcessList_add(pl, proc); - } else if (settings->updateProcessNames && proc->state != 'Z') { - PCPProcessList_updateCmdline(proc, pid, offset, command); - } - - /* (Re)Generate the Command string, but only if the process is: - * - not a kernel thread, and - * - not a zombie or it became zombie under htop's watch, and - * - not a user thread or if showThreadNames is not set */ - if (!Process_isKernelThread(proc) && - (proc->state != 'Z' || pp->mergedCommand.str) && - (!Process_isUserlandThread(proc) || !settings->showThreadNames)) { - PCPProcess_makeCommandStr(proc); - } - - if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) - PCPProcessList_readCGroups(pp, pid, offset); - - if (settings->flags & PROCESS_FLAG_LINUX_OOM) - PCPProcessList_readOomData(pp, pid, offset); - - if (settings->flags & PROCESS_FLAG_LINUX_CTXT) - PCPProcessList_readCtxtData(pp, pid, offset); - - if (settings->flags & PROCESS_FLAG_LINUX_SECATTR) - PCPProcessList_readSecattrData(pp, pid, offset); - - if (proc->state == 'Z' && proc->basenameOffset == 0) { - proc->basenameOffset = -1; - free_and_xStrdup(&proc->comm, command); - pp->procCmdlineBasenameOffset = 0; - pp->procCmdlineBasenameEnd = 0; - pp->mergedCommand.commChanged = true; - } else if (Process_isThread(proc)) { - if (settings->showThreadNames || Process_isKernelThread(proc)) { - proc->basenameOffset = -1; - free_and_xStrdup(&proc->comm, command); - pp->procCmdlineBasenameOffset = 0; - pp->procCmdlineBasenameEnd = 0; - pp->mergedCommand.commChanged = true; - } - if (Process_isKernelThread(proc)) { - pl->kernelThreads++; - } else { - pl->userlandThreads++; - } - } - - /* Set at the end when we know if a new entry is a thread */ - proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || - (hideUserlandThreads && Process_isUserlandThread(proc))); -//fprintf(stderr, "Updated PID %d [%s] show=%d user=%d[%d] kern=%d[%d]\n", pid, command, proc->show, Process_isUserlandThread(proc), hideUserlandThreads, Process_isKernelThread(proc), hideKernelThreads); - - pl->totalTasks++; - if (proc->state == 'R') - pl->runningTasks++; - proc->updated = true; - } -//fprintf(stderr, "Total tasks %d, running=%d\n", pl->totalTasks, pl->runningTasks); - return true; -} - -static void PCPProcessList_updateMemoryInfo(ProcessList* super) { - unsigned long long int freeMem = 0; - unsigned long long int swapFreeMem = 0; - unsigned long long int sreclaimableMem = 0; - super->totalMem = super->usedMem = super->cachedMem = 0; - super->usedSwap = super->totalSwap = 0; - - pmAtomValue value; - if (Metric_values(PCP_MEM_TOTAL, &value, 1, PM_TYPE_U64) != NULL) - super->totalMem = value.ull; - if (Metric_values(PCP_MEM_FREE, &value, 1, PM_TYPE_U64) != NULL) - freeMem = value.ull; - if (Metric_values(PCP_MEM_BUFFERS, &value, 1, PM_TYPE_U64) != NULL) - super->buffersMem = value.ull; - if (Metric_values(PCP_MEM_SRECLAIM, &value, 1, PM_TYPE_U64) != NULL) - sreclaimableMem = value.ull; - if (Metric_values(PCP_MEM_SHARED, &value, 1, PM_TYPE_U64) != NULL) - super->sharedMem = value.ull; - if (Metric_values(PCP_MEM_CACHED, &value, 1, PM_TYPE_U64) != NULL) { - super->cachedMem = value.ull; - super->cachedMem += sreclaimableMem; - } - const memory_t usedDiff = freeMem + super->cachedMem + sreclaimableMem + super->buffersMem + super->sharedMem; - super->usedMem = (super->totalMem >= usedDiff) ? - super->totalMem - usedDiff : super->totalMem - freeMem; - if (Metric_values(PCP_MEM_AVAILABLE, &value, 1, PM_TYPE_U64) != NULL) - super->availableMem = MINIMUM(value.ull, super->totalMem); - else - super->availableMem = freeMem; - if (Metric_values(PCP_MEM_SWAPFREE, &value, 1, PM_TYPE_U64) != NULL) - swapFreeMem = value.ull; - if (Metric_values(PCP_MEM_SWAPTOTAL, &value, 1, PM_TYPE_U64) != NULL) - super->totalSwap = value.ull; - if (Metric_values(PCP_MEM_SWAPCACHED, &value, 1, PM_TYPE_U64) != NULL) - super->cachedSwap = value.ull; - super->usedSwap = super->totalSwap - swapFreeMem - super->cachedSwap; -} - -/* make copies of previously sampled values to avoid overwrite */ -static inline void PCPProcessList_backupCPUTime(pmAtomValue* values) { - /* the PERIOD fields (must) mirror the TIME fields */ - for (int metric = CPU_TOTAL_TIME; metric < CPU_TOTAL_PERIOD; metric++) { - values[metric + CPU_TOTAL_PERIOD] = values[metric]; - } -} - -static inline void PCPProcessList_saveCPUTimePeriod(pmAtomValue* values, CPUMetric previous, pmAtomValue* latest) { - pmAtomValue *value; - - /* new value for period */ - value = &values[previous]; - if (latest->ull > value->ull) - value->ull = latest->ull - value->ull; - else - value->ull = 0; - - /* new value for time */ - value = &values[previous - CPU_TOTAL_PERIOD]; - value->ull = latest->ull; -} - -/* using copied sampled values and new values, calculate derivations */ -static void PCPProcessList_deriveCPUTime(pmAtomValue* values) { - - pmAtomValue* usertime = &values[CPU_USER_TIME]; - pmAtomValue* guesttime = &values[CPU_GUEST_TIME]; - usertime->ull -= guesttime->ull; - - pmAtomValue* nicetime = &values[CPU_NICE_TIME]; - pmAtomValue* guestnicetime = &values[CPU_GUESTNICE_TIME]; - nicetime->ull -= guestnicetime->ull; - - pmAtomValue* idletime = &values[CPU_IDLE_TIME]; - pmAtomValue* iowaittime = &values[CPU_IOWAIT_TIME]; - pmAtomValue* idlealltime = &values[CPU_IDLE_ALL_TIME]; - idlealltime->ull = idletime->ull + iowaittime->ull; - - pmAtomValue* systemtime = &values[CPU_SYSTEM_TIME]; - pmAtomValue* irqtime = &values[CPU_IRQ_TIME]; - pmAtomValue* softirqtime = &values[CPU_SOFTIRQ_TIME]; - pmAtomValue* systalltime = &values[CPU_SYSTEM_ALL_TIME]; - systalltime->ull = systemtime->ull + irqtime->ull + softirqtime->ull; - - pmAtomValue* virtalltime = &values[CPU_GUEST_TIME]; - virtalltime->ull = guesttime->ull + guestnicetime->ull; - - pmAtomValue* stealtime = &values[CPU_STEAL_TIME]; - pmAtomValue* totaltime = &values[CPU_TOTAL_TIME]; - totaltime->ull = usertime->ull + nicetime->ull + systalltime->ull + - idlealltime->ull + stealtime->ull + virtalltime->ull; - - PCPProcessList_saveCPUTimePeriod(values, CPU_USER_PERIOD, usertime); - PCPProcessList_saveCPUTimePeriod(values, CPU_NICE_PERIOD, nicetime); - PCPProcessList_saveCPUTimePeriod(values, CPU_SYSTEM_PERIOD, systemtime); - PCPProcessList_saveCPUTimePeriod(values, CPU_SYSTEM_ALL_PERIOD, systalltime); - PCPProcessList_saveCPUTimePeriod(values, CPU_IDLE_ALL_PERIOD, idlealltime); - PCPProcessList_saveCPUTimePeriod(values, CPU_IDLE_PERIOD, idletime); - PCPProcessList_saveCPUTimePeriod(values, CPU_IOWAIT_PERIOD, iowaittime); - PCPProcessList_saveCPUTimePeriod(values, CPU_IRQ_PERIOD, irqtime); - PCPProcessList_saveCPUTimePeriod(values, CPU_SOFTIRQ_PERIOD, softirqtime); - PCPProcessList_saveCPUTimePeriod(values, CPU_STEAL_PERIOD, stealtime); - PCPProcessList_saveCPUTimePeriod(values, CPU_GUEST_PERIOD, virtalltime); - PCPProcessList_saveCPUTimePeriod(values, CPU_TOTAL_PERIOD, totaltime); -} - -static void PCPProcessList_updateAllCPUTime(PCPProcessList* this, Metric metric, CPUMetric cpumetric) -{ - pmAtomValue* value = &this->cpu[cpumetric]; - if (Metric_values(metric, value, 1, PM_TYPE_U64) == NULL) - memset(&value, 0, sizeof(pmAtomValue)); -} - -static void PCPProcessList_updatePerCPUTime(PCPProcessList* this, Metric metric, CPUMetric cpumetric) -{ - int cpus = this->super.cpuCount; - if (Metric_values(metric, this->values, cpus, PM_TYPE_U64) == NULL) - memset(this->values, 0, cpus * sizeof(pmAtomValue)); - for (int i = 0; i < cpus; i++) - this->percpu[i][cpumetric].ull = this->values[i].ull; -} - -static void PCPProcessList_updatePerCPUReal(PCPProcessList* this, Metric metric, CPUMetric cpumetric) -{ - int cpus = this->super.cpuCount; - if (Metric_values(metric, this->values, cpus, PM_TYPE_DOUBLE) == NULL) - memset(this->values, 0, cpus * sizeof(pmAtomValue)); - for (int i = 0; i < cpus; i++) - this->percpu[i][cpumetric].d = this->values[i].d; -} - -static void PCPProcessList_updateHeader(ProcessList* super, const Settings* settings) { - PCPProcessList_updateMemoryInfo(super); - - PCPProcessList* this = (PCPProcessList*) super; - PCPProcessList_updateCPUcount(this); - - PCPProcessList_backupCPUTime(this->cpu); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_USER, CPU_USER_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_NICE, CPU_NICE_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_SYSTEM, CPU_SYSTEM_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_IDLE, CPU_IDLE_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_IOWAIT, CPU_IOWAIT_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_IRQ, CPU_IRQ_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_SOFTIRQ, CPU_SOFTIRQ_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_STEAL, CPU_STEAL_TIME); - PCPProcessList_updateAllCPUTime(this, PCP_CPU_GUEST, CPU_GUEST_TIME); - PCPProcessList_deriveCPUTime(this->cpu); - - for (unsigned int i = 0; i < super->cpuCount; i++) - PCPProcessList_backupCPUTime(this->percpu[i]); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_USER, CPU_USER_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_NICE, CPU_NICE_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_SYSTEM, CPU_SYSTEM_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_IDLE, CPU_IDLE_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_IOWAIT, CPU_IOWAIT_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_IRQ, CPU_IRQ_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_SOFTIRQ, CPU_SOFTIRQ_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_STEAL, CPU_STEAL_TIME); - PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_GUEST, CPU_GUEST_TIME); - for (unsigned int i = 0; i < super->cpuCount; i++) - PCPProcessList_deriveCPUTime(this->percpu[i]); - - if (settings->showCPUFrequency) - PCPProcessList_updatePerCPUReal(this, PCP_HINV_CPUCLOCK, CPU_FREQUENCY); -} - -static inline void PCPProcessList_scanZfsArcstats(PCPProcessList* this) { - unsigned long long int dbufSize = 0; - unsigned long long int dnodeSize = 0; - unsigned long long int bonusSize = 0; - pmAtomValue value; - - memset(&this->zfs, 0, sizeof(ZfsArcStats)); - if (Metric_values(PCP_ZFS_ARC_ANON_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.anon = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_C_MAX, &value, 1, PM_TYPE_U64)) - this->zfs.max = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_BONUS_SIZE, &value, 1, PM_TYPE_U64)) - bonusSize = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_DBUF_SIZE, &value, 1, PM_TYPE_U64)) - dbufSize = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_DNODE_SIZE, &value, 1, PM_TYPE_U64)) - dnodeSize = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_COMPRESSED_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.compressed = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_UNCOMPRESSED_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.uncompressed = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_HDR_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.header = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_MFU_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.MFU = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_MRU_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.MRU = value.ull / ONE_K; - if (Metric_values(PCP_ZFS_ARC_SIZE, &value, 1, PM_TYPE_U64)) - this->zfs.size = value.ull / ONE_K; - - this->zfs.other = (dbufSize + dnodeSize + bonusSize) / ONE_K; - this->zfs.enabled = (this->zfs.size > 0); - this->zfs.isCompressed = (this->zfs.compressed > 0); -} - -void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { - PCPProcessList* this = (PCPProcessList*) super; - const Settings* settings = super->settings; - bool enabled = !pauseProcessUpdate; - - bool flagged = settings->showCPUFrequency; - Metric_enable(PCP_HINV_CPUCLOCK, flagged); - - /* In pause mode do not sample per-process metric values at all */ - for (int metric = PCP_PROC_PID; metric < PCP_METRIC_COUNT; metric++) - Metric_enable(metric, enabled); - - flagged = settings->flags & PROCESS_FLAG_LINUX_CGROUP; - Metric_enable(PCP_PROC_CGROUPS, flagged && enabled); - flagged = settings->flags & PROCESS_FLAG_LINUX_OOM; - Metric_enable(PCP_PROC_OOMSCORE, flagged && enabled); - flagged = settings->flags & PROCESS_FLAG_LINUX_CTXT; - Metric_enable(PCP_PROC_VCTXSW, flagged && enabled); - Metric_enable(PCP_PROC_NVCTXSW, flagged && enabled); - flagged = settings->flags & PROCESS_FLAG_LINUX_SECATTR; - Metric_enable(PCP_PROC_LABELS, flagged && enabled); - - /* Sample smaps metrics on every second pass to improve performance */ - static int smaps_flag; - smaps_flag = !!smaps_flag; - Metric_enable(PCP_PROC_SMAPS_PSS, smaps_flag && enabled); - Metric_enable(PCP_PROC_SMAPS_SWAP, smaps_flag && enabled); - Metric_enable(PCP_PROC_SMAPS_SWAPPSS, smaps_flag && enabled); - - struct timeval timestamp; - Metric_fetch(×tamp); - - double sample = this->timestamp; - this->timestamp = pmtimevalToReal(×tamp); - - PCPProcessList_updateHeader(super, settings); - PCPProcessList_scanZfsArcstats(this); - - /* In pause mode only update global data for meters (CPU, memory, etc) */ - if (pauseProcessUpdate) - return; - - double period = (this->timestamp - sample) * 100; - PCPProcessList_updateProcesses(this, period, ×tamp); -} diff -Nru pcp-5.3.1/src/pcp/htop/pcp/PCPProcessList.h pcp-5.3.2/src/pcp/htop/pcp/PCPProcessList.h --- pcp-5.3.1/src/pcp/htop/pcp/PCPProcessList.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/PCPProcessList.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -#ifndef HEADER_PCPProcessList -#define HEADER_PCPProcessList -/* -htop - PCPProcessList.h -(C) 2014 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" - -#include -#include - -#include "Hashtable.h" -#include "ProcessList.h" -#include "pcp/Platform.h" -#include "UsersTable.h" -#include "zfs/ZfsArcStats.h" - -typedef enum CPUMetric_ { - CPU_TOTAL_TIME, - CPU_USER_TIME, - CPU_SYSTEM_TIME, - CPU_SYSTEM_ALL_TIME, - CPU_IDLE_ALL_TIME, - CPU_IDLE_TIME, - CPU_NICE_TIME, - CPU_IOWAIT_TIME, - CPU_IRQ_TIME, - CPU_SOFTIRQ_TIME, - CPU_STEAL_TIME, - CPU_GUEST_TIME, - CPU_GUESTNICE_TIME, - - CPU_TOTAL_PERIOD, - CPU_USER_PERIOD, - CPU_SYSTEM_PERIOD, - CPU_SYSTEM_ALL_PERIOD, - CPU_IDLE_ALL_PERIOD, - CPU_IDLE_PERIOD, - CPU_NICE_PERIOD, - CPU_IOWAIT_PERIOD, - CPU_IRQ_PERIOD, - CPU_SOFTIRQ_PERIOD, - CPU_STEAL_PERIOD, - CPU_GUEST_PERIOD, - CPU_GUESTNICE_PERIOD, - - CPU_FREQUENCY, - - CPU_METRIC_COUNT -} CPUMetric; - -typedef struct PCPProcessList_ { - ProcessList super; - double timestamp; /* previous sample timestamp */ - pmAtomValue* cpu; /* aggregate values for each metric */ - pmAtomValue** percpu; /* per-processor values for each metric */ - pmAtomValue* values; /* per-processor buffer for just one metric */ - ZfsArcStats zfs; -} PCPProcessList; - -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); - -void ProcessList_delete(ProcessList* pl); - -void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/pcp/Platform.c pcp-5.3.2/src/pcp/htop/pcp/Platform.c --- pcp-5.3.1/src/pcp/htop/pcp/Platform.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/Platform.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,874 +0,0 @@ -/* -htop - linux/Platform.c -(C) 2014 Hisham H. Muhammad -(C) 2020-2021 htop dev team -(C) 2020-2021 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" - -#include - -#include "BatteryMeter.h" -#include "ClockMeter.h" -#include "Compat.h" -#include "CPUMeter.h" -#include "DateMeter.h" -#include "DateTimeMeter.h" -#include "DiskIOMeter.h" -#include "HostnameMeter.h" -#include "LoadAverageMeter.h" -#include "Macros.h" -#include "MainPanel.h" -#include "MemoryMeter.h" -#include "Meter.h" -#include "NetworkIOMeter.h" -#include "Object.h" -#include "Panel.h" -#include "PCPProcess.h" -#include "PCPProcessList.h" -#include "Platform.h" -#include "ProcessList.h" -#include "ProvideCurses.h" -#include "Settings.h" -#include "SwapMeter.h" -#include "SysArchMeter.h" -#include "TasksMeter.h" -#include "UptimeMeter.h" -#include "XUtils.h" -#include "linux/PressureStallMeter.h" -#include "linux/ZramMeter.h" -#include "linux/ZramStats.h" -#include "zfs/ZfsArcMeter.h" -#include "zfs/ZfsArcStats.h" -#include "zfs/ZfsCompressedArcMeter.h" - - -typedef struct Platform_ { - int context; /* PMAPI(3) context identifier */ - unsigned int total; /* total number of all metrics */ - const char** names; /* name array indexed by Metric */ - pmID* pmids; /* all known metric identifiers */ - pmID* fetch; /* enabled identifiers for sampling */ - pmDesc* descs; /* metric desc array indexed by Metric */ - pmResult* result; /* sample values result indexed by Metric */ - struct timeval offset; /* time offset used in archive mode only */ - - long long btime; /* boottime in seconds since the epoch */ - char* release; /* uname and distro from this context */ - int pidmax; /* maximum platform process identifier */ - int ncpu; /* maximum processor count configured */ -} Platform; - -Platform* pcp; - -ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, (int)M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; - -int Platform_numberOfFields = LAST_PROCESSFIELD; - -const SignalItem Platform_signals[] = { - { .name = " 0 Cancel", .number = 0 }, -}; - -const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); - -const MeterClass* const Platform_meterTypes[] = { - &CPUMeter_class, - &ClockMeter_class, - &DateMeter_class, - &DateTimeMeter_class, - &LoadAverageMeter_class, - &LoadMeter_class, - &MemoryMeter_class, - &SwapMeter_class, - &TasksMeter_class, - &UptimeMeter_class, - &BatteryMeter_class, - &HostnameMeter_class, - &AllCPUsMeter_class, - &AllCPUs2Meter_class, - &AllCPUs4Meter_class, - &AllCPUs8Meter_class, - &LeftCPUsMeter_class, - &RightCPUsMeter_class, - &LeftCPUs2Meter_class, - &RightCPUs2Meter_class, - &LeftCPUs4Meter_class, - &RightCPUs4Meter_class, - &LeftCPUs8Meter_class, - &RightCPUs8Meter_class, - &BlankMeter_class, - &PressureStallCPUSomeMeter_class, - &PressureStallIOSomeMeter_class, - &PressureStallIOFullMeter_class, - &PressureStallMemorySomeMeter_class, - &PressureStallMemoryFullMeter_class, - &ZfsArcMeter_class, - &ZfsCompressedArcMeter_class, - &ZramMeter_class, - &DiskIOMeter_class, - &NetworkIOMeter_class, - &SysArchMeter_class, - NULL -}; - -static const char *Platform_metricNames[] = { - [PCP_CONTROL_THREADS] = "proc.control.perclient.threads", - - [PCP_HINV_NCPU] = "hinv.ncpu", - [PCP_HINV_CPUCLOCK] = "hinv.cpu.clock", - [PCP_UNAME_SYSNAME] = "kernel.uname.sysname", - [PCP_UNAME_RELEASE] = "kernel.uname.release", - [PCP_UNAME_MACHINE] = "kernel.uname.machine", - [PCP_UNAME_DISTRO] = "kernel.uname.distro", - [PCP_LOAD_AVERAGE] = "kernel.all.load", - [PCP_PID_MAX] = "kernel.all.pid_max", - [PCP_UPTIME] = "kernel.all.uptime", - [PCP_BOOTTIME] = "kernel.all.boottime", - [PCP_CPU_USER] = "kernel.all.cpu.user", - [PCP_CPU_NICE] = "kernel.all.cpu.nice", - [PCP_CPU_SYSTEM] = "kernel.all.cpu.sys", - [PCP_CPU_IDLE] = "kernel.all.cpu.idle", - [PCP_CPU_IOWAIT] = "kernel.all.cpu.wait.total", - [PCP_CPU_IRQ] = "kernel.all.cpu.intr", - [PCP_CPU_SOFTIRQ] = "kernel.all.cpu.irq.soft", - [PCP_CPU_STEAL] = "kernel.all.cpu.steal", - [PCP_CPU_GUEST] = "kernel.all.cpu.guest", - [PCP_CPU_GUESTNICE] = "kernel.all.cpu.guest_nice", - [PCP_PERCPU_USER] = "kernel.percpu.cpu.user", - [PCP_PERCPU_NICE] = "kernel.percpu.cpu.nice", - [PCP_PERCPU_SYSTEM] = "kernel.percpu.cpu.sys", - [PCP_PERCPU_IDLE] = "kernel.percpu.cpu.idle", - [PCP_PERCPU_IOWAIT] = "kernel.percpu.cpu.wait.total", - [PCP_PERCPU_IRQ] = "kernel.percpu.cpu.intr", - [PCP_PERCPU_SOFTIRQ] = "kernel.percpu.cpu.irq.soft", - [PCP_PERCPU_STEAL] = "kernel.percpu.cpu.steal", - [PCP_PERCPU_GUEST] = "kernel.percpu.cpu.guest", - [PCP_PERCPU_GUESTNICE] = "kernel.percpu.cpu.guest_nice", - [PCP_MEM_TOTAL] = "mem.physmem", - [PCP_MEM_FREE] = "mem.util.free", - [PCP_MEM_AVAILABLE] = "mem.util.available", - [PCP_MEM_BUFFERS] = "mem.util.bufmem", - [PCP_MEM_CACHED] = "mem.util.cached", - [PCP_MEM_SHARED] = "mem.util.shared", - [PCP_MEM_SRECLAIM] = "mem.util.slabReclaimable", - [PCP_MEM_SWAPCACHED] = "mem.util.swapCached", - [PCP_MEM_SWAPTOTAL] = "mem.util.swapTotal", - [PCP_MEM_SWAPFREE] = "mem.util.swapFree", - [PCP_DISK_READB] = "disk.all.read_bytes", - [PCP_DISK_WRITEB] = "disk.all.write_bytes", - [PCP_DISK_ACTIVE] = "disk.all.avactive", - [PCP_NET_RECVB] = "network.all.in.bytes", - [PCP_NET_SENDB] = "network.all.out.bytes", - [PCP_NET_RECVP] = "network.all.in.packets", - [PCP_NET_SENDP] = "network.all.out.packets", - - [PCP_PSI_CPUSOME] = "kernel.all.pressure.cpu.some.avg", - [PCP_PSI_IOSOME] = "kernel.all.pressure.io.some.avg", - [PCP_PSI_IOFULL] = "kernel.all.pressure.io.full.avg", - [PCP_PSI_MEMSOME] = "kernel.all.pressure.memory.some.avg", - [PCP_PSI_MEMFULL] = "kernel.all.pressure.memory.full.avg", - - [PCP_ZFS_ARC_ANON_SIZE] = "zfs.arc.anon_size", - [PCP_ZFS_ARC_BONUS_SIZE] = "zfs.arc.bonus_size", - [PCP_ZFS_ARC_COMPRESSED_SIZE] = "zfs.arc.compressed_size", - [PCP_ZFS_ARC_UNCOMPRESSED_SIZE] = "zfs.arc.uncompressed_size", - [PCP_ZFS_ARC_C_MAX] = "zfs.arc.c_max", - [PCP_ZFS_ARC_DBUF_SIZE] = "zfs.arc.dbuf_size", - [PCP_ZFS_ARC_DNODE_SIZE] = "zfs.arc.dnode_size", - [PCP_ZFS_ARC_HDR_SIZE] = "zfs.arc.hdr_size", - [PCP_ZFS_ARC_MFU_SIZE] = "zfs.arc.mfu.size", - [PCP_ZFS_ARC_MRU_SIZE] = "zfs.arc.mru.size", - [PCP_ZFS_ARC_SIZE] = "zfs.arc.size", - - [PCP_ZRAM_CAPACITY] = "zram.capacity", - [PCP_ZRAM_ORIGINAL] = "zram.mm_stat.data_size.original", - [PCP_ZRAM_COMPRESSED] = "zram.mm_stat.data_size.compressed", - - [PCP_PROC_PID] = "proc.psinfo.pid", - [PCP_PROC_PPID] = "proc.psinfo.ppid", - [PCP_PROC_TGID] = "proc.psinfo.tgid", - [PCP_PROC_PGRP] = "proc.psinfo.pgrp", - [PCP_PROC_SESSION] = "proc.psinfo.session", - [PCP_PROC_STATE] = "proc.psinfo.sname", - [PCP_PROC_TTY] = "proc.psinfo.tty", - [PCP_PROC_TTYPGRP] = "proc.psinfo.tty_pgrp", - [PCP_PROC_MINFLT] = "proc.psinfo.minflt", - [PCP_PROC_MAJFLT] = "proc.psinfo.maj_flt", - [PCP_PROC_CMINFLT] = "proc.psinfo.cmin_flt", - [PCP_PROC_CMAJFLT] = "proc.psinfo.cmaj_flt", - [PCP_PROC_UTIME] = "proc.psinfo.utime", - [PCP_PROC_STIME] = "proc.psinfo.stime", - [PCP_PROC_CUTIME] = "proc.psinfo.cutime", - [PCP_PROC_CSTIME] = "proc.psinfo.cstime", - [PCP_PROC_PRIORITY] = "proc.psinfo.priority", - [PCP_PROC_NICE] = "proc.psinfo.nice", - [PCP_PROC_THREADS] = "proc.psinfo.threads", - [PCP_PROC_STARTTIME] = "proc.psinfo.start_time", - [PCP_PROC_PROCESSOR] = "proc.psinfo.processor", - [PCP_PROC_CMD] = "proc.psinfo.cmd", - [PCP_PROC_PSARGS] = "proc.psinfo.psargs", - [PCP_PROC_CGROUPS] = "proc.psinfo.cgroups", - [PCP_PROC_OOMSCORE] = "proc.psinfo.oom_score", - [PCP_PROC_VCTXSW] = "proc.psinfo.vctxsw", - [PCP_PROC_NVCTXSW] = "proc.psinfo.nvctxsw", - [PCP_PROC_LABELS] = "proc.psinfo.labels", - [PCP_PROC_ENVIRON] = "proc.psinfo.environ", - [PCP_PROC_TTYNAME] = "proc.psinfo.ttyname", - [PCP_PROC_ID_UID] = "proc.id.uid", - [PCP_PROC_ID_USER] = "proc.id.uid_nm", - [PCP_PROC_IO_RCHAR] = "proc.io.rchar", - [PCP_PROC_IO_WCHAR] = "proc.io.wchar", - [PCP_PROC_IO_SYSCR] = "proc.io.syscr", - [PCP_PROC_IO_SYSCW] = "proc.io.syscw", - [PCP_PROC_IO_READB] = "proc.io.read_bytes", - [PCP_PROC_IO_WRITEB] = "proc.io.write_bytes", - [PCP_PROC_IO_CANCELLED] = "proc.io.cancelled_write_bytes", - [PCP_PROC_MEM_SIZE] = "proc.memory.size", - [PCP_PROC_MEM_RSS] = "proc.memory.rss", - [PCP_PROC_MEM_SHARE] = "proc.memory.share", - [PCP_PROC_MEM_TEXTRS] = "proc.memory.textrss", - [PCP_PROC_MEM_LIBRS] = "proc.memory.librss", - [PCP_PROC_MEM_DATRS] = "proc.memory.datrss", - [PCP_PROC_MEM_DIRTY] = "proc.memory.dirty", - [PCP_PROC_SMAPS_PSS] = "proc.smaps.pss", - [PCP_PROC_SMAPS_SWAP] = "proc.smaps.swap", - [PCP_PROC_SMAPS_SWAPPSS] = "proc.smaps.swappss", - - [PCP_METRIC_COUNT] = NULL -}; - -pmAtomValue* Metric_values(Metric metric, pmAtomValue *atom, int count, int type) { - - pmValueSet* vset = pcp->result->vset[metric]; - if (!vset || vset->numval <= 0) - return NULL; - - /* extract requested number of values as requested type */ - const pmDesc* desc = &pcp->descs[metric]; - for (int i = 0; i < vset->numval; i++) { - if (i == count) - break; - const pmValue *value = &vset->vlist[i]; - int sts = pmExtractValue(vset->valfmt, value, desc->type, &atom[i], type); - if (sts < 0) { - if (pmDebugOptions.appl0) - fprintf(stderr, "Error: cannot extract metric value: %s\n", - pmErrStr(sts)); - memset(&atom[i], 0, sizeof(pmAtomValue)); - } - } - return atom; -} - -int Metric_instanceCount(Metric metric) { - pmValueSet* vset = pcp->result->vset[metric]; - if (vset) - return vset->numval; - return 0; -} - -int Metric_instanceOffset(Metric metric, int inst) { - pmValueSet* vset = pcp->result->vset[metric]; - if (!vset || vset->numval <= 0) - return 0; - - /* search for optimal offset for subsequent inst lookups to begin */ - for (int i = 0; i < vset->numval; i++) { - if (inst == vset->vlist[i].inst) - return i; - } - return 0; -} - -static pmAtomValue *Metric_extract(Metric metric, int inst, int offset, pmValueSet *vset, pmAtomValue *atom, int type) { - - /* extract value (using requested type) of given metric instance */ - const pmDesc* desc = &pcp->descs[metric]; - const pmValue *value = &vset->vlist[offset]; - int sts = pmExtractValue(vset->valfmt, value, desc->type, atom, type); - if (sts < 0) { - if (pmDebugOptions.appl0) - fprintf(stderr, "Error: cannot extract %s instance %d value: %s\n", - pcp->names[metric], inst, pmErrStr(sts)); - memset(atom, 0, sizeof(pmAtomValue)); - } - return atom; -} - -pmAtomValue *Metric_instance(Metric metric, int inst, int offset, pmAtomValue *atom, int type) { - - pmValueSet* vset = pcp->result->vset[metric]; - if (!vset || vset->numval <= 0) - return NULL; - - /* fast-path using heuristic offset based on expected location */ - if (offset >= 0 && offset < vset->numval && inst == vset->vlist[offset].inst) - return Metric_extract(metric, inst, offset, vset, atom, type); - - /* slow-path using a linear search for the requested instance */ - for (int i = 0; i < vset->numval; i++) { - if (inst == vset->vlist[i].inst) - return Metric_extract(metric, inst, i, vset, atom, type); - } - return NULL; -} - -/* - * Iterate over a set of instances (incl PM_IN_NULL) - * returning the next instance identifier and offset. - * - * Start it off by passing offset -1 into the routine. - */ -bool Metric_iterate(Metric metric, int* instp, int* offsetp) { - pmValueSet* vset = pcp->result->vset[metric]; - if (!vset || vset->numval <= 0) - return false; - - int offset = *offsetp; - offset = (offset < 0) ? 0 : offset + 1; - if (offset > vset->numval - 1) - return false; - - *offsetp = offset; - *instp = vset->vlist[offset].inst; - return true; -} - -/* Switch on/off a metric for value fetching (sampling) */ -void Metric_enable(Metric metric, bool enable) { - pcp->fetch[metric] = enable ? pcp->pmids[metric] : PM_ID_NULL; -} - -bool Metric_enabled(Metric metric) { - return pcp->fetch[metric] != PM_ID_NULL; -} - -void Metric_enableThreads(void) { - pmValueSet* vset = xCalloc(1, sizeof(pmValueSet)); - vset->vlist[0].inst = PM_IN_NULL; - vset->vlist[0].value.lval = 1; - vset->valfmt = PM_VAL_INSITU; - vset->numval = 1; - vset->pmid = pcp->pmids[PCP_CONTROL_THREADS]; - - pmResult* result = xCalloc(1, sizeof(pmResult)); - result->vset[0] = vset; - result->numpmid = 1; - - int sts = pmStore(result); - if (sts < 0 && pmDebugOptions.appl0) - fprintf(stderr, "Error: cannot enable threads: %s\n", pmErrStr(sts)); - - pmFreeResult(result); -} - -bool Metric_fetch(struct timeval *timestamp) { - int sts = pmFetch(pcp->total, pcp->fetch, &pcp->result); - if (sts < 0) { - if (pmDebugOptions.appl0) - fprintf(stderr, "Error: cannot fetch metric values): %s\n", - pmErrStr(sts)); - return false; - } - if (timestamp) - *timestamp = pcp->result->timestamp; - return true; -} - -static int Platform_addMetric(Metric id, const char *name) { - unsigned int i = (unsigned int)id; - - if (i >= PCP_METRIC_COUNT && i >= pcp->total) { - /* added via configuration files */ - unsigned int j = pcp->total + 1; - pcp->fetch = xRealloc(pcp->fetch, j * sizeof(pmID)); - pcp->pmids = xRealloc(pcp->pmids, j * sizeof(pmID)); - pcp->names = xRealloc(pcp->names, j * sizeof(char*)); - pcp->descs = xRealloc(pcp->descs, j * sizeof(pmDesc)); - memset(&pcp->descs[i], 0, sizeof(pmDesc)); - } - - pcp->pmids[i] = pcp->fetch[i] = PM_ID_NULL; - pcp->names[i] = name; - return ++pcp->total; -} - -/* global state from the environment and command line arguments */ -pmOptions opts; - -void Platform_init(void) { - const char* source; - if (opts.context == PM_CONTEXT_ARCHIVE) { - source = opts.archives[0]; - } else if (opts.context == PM_CONTEXT_HOST) { - source = opts.nhosts > 0 ? opts.hosts[0] : "local:"; - } else { - opts.context = PM_CONTEXT_HOST; - source = "local:"; - } - - int sts; - sts = pmNewContext(opts.context, source); - /* with no host requested, fallback to PM_CONTEXT_LOCAL shared libraries */ - if (sts < 0 && opts.context == PM_CONTEXT_HOST && opts.nhosts == 0) { - opts.context = PM_CONTEXT_LOCAL; - sts = pmNewContext(opts.context, NULL); - } - if (sts < 0) { - fprintf(stderr, "Cannot setup PCP metric source: %s\n", pmErrStr(sts)); - exit(1); - } - /* setup timezones and other general startup preparation completion */ - if (pmGetContextOptions(sts, &opts) < 0 || opts.errors) { - pmflush(); - exit(1); - } - - pcp = xCalloc(1, sizeof(Platform)); - pcp->context = sts; - pcp->fetch = xCalloc(PCP_METRIC_COUNT, sizeof(pmID)); - pcp->pmids = xCalloc(PCP_METRIC_COUNT, sizeof(pmID)); - pcp->names = xCalloc(PCP_METRIC_COUNT, sizeof(char*)); - pcp->descs = xCalloc(PCP_METRIC_COUNT, sizeof(pmDesc)); - - if (opts.context == PM_CONTEXT_ARCHIVE) { - gettimeofday(&pcp->offset, NULL); - pmtimevalDec(&pcp->offset, &opts.start); - } - - for (unsigned int i = 0; i < PCP_METRIC_COUNT; i++) - Platform_addMetric(i, Platform_metricNames[i]); - - sts = pmLookupName(pcp->total, pcp->names, pcp->pmids); - if (sts < 0) { - fprintf(stderr, "Error: cannot lookup metric names: %s\n", pmErrStr(sts)); - exit(1); - } - - for (unsigned int i = 0; i < pcp->total; i++) { - pcp->fetch[i] = PM_ID_NULL; /* default is to not sample */ - - /* expect some metrics to be missing - e.g. PMDA not available */ - if (pcp->pmids[i] == PM_ID_NULL) - continue; - - sts = pmLookupDesc(pcp->pmids[i], &pcp->descs[i]); - if (sts < 0) { - if (pmDebugOptions.appl0) - fprintf(stderr, "Error: cannot lookup metric %s(%s): %s\n", - pcp->names[i], pmIDStr(pcp->pmids[i]), pmErrStr(sts)); - pcp->pmids[i] = PM_ID_NULL; - continue; - } - } - - /* set proc.control.perclient.threads to 1 for live contexts */ - Metric_enableThreads(); - - /* extract values needed for setup - e.g. cpu count, pid_max */ - Metric_enable(PCP_PID_MAX, true); - Metric_enable(PCP_BOOTTIME, true); - Metric_enable(PCP_HINV_NCPU, true); - Metric_enable(PCP_PERCPU_SYSTEM, true); - Metric_enable(PCP_UNAME_SYSNAME, true); - Metric_enable(PCP_UNAME_RELEASE, true); - Metric_enable(PCP_UNAME_MACHINE, true); - Metric_enable(PCP_UNAME_DISTRO, true); - - Metric_fetch(NULL); - - for (Metric metric = 0; metric < PCP_PROC_PID; metric++) - Metric_enable(metric, true); - Metric_enable(PCP_PID_MAX, false); /* needed one time only */ - Metric_enable(PCP_BOOTTIME, false); - Metric_enable(PCP_UNAME_SYSNAME, false); - Metric_enable(PCP_UNAME_RELEASE, false); - Metric_enable(PCP_UNAME_MACHINE, false); - Metric_enable(PCP_UNAME_DISTRO, false); - - /* first sample (fetch) performed above, save constants */ - Platform_getBootTime(); - Platform_getRelease(0); - Platform_getMaxCPU(); - Platform_getMaxPid(); -} - -void Platform_done(void) { - pmDestroyContext(pcp->context); - free(pcp->fetch); - free(pcp->pmids); - free(pcp->names); - free(pcp->descs); - free(pcp); -} - -void Platform_setBindings(Htop_Action* keys) { - /* no platform-specific key bindings */ - (void)keys; -} - -int Platform_getUptime(void) { - pmAtomValue value; - if (Metric_values(PCP_UPTIME, &value, 1, PM_TYPE_32) == NULL) - return 0; - return value.l; -} - -void Platform_getLoadAverage(double* one, double* five, double* fifteen) { - *one = *five = *fifteen = 0.0; - - pmAtomValue values[3] = {0}; - if (Metric_values(PCP_LOAD_AVERAGE, values, 3, PM_TYPE_DOUBLE) != NULL) { - *one = values[0].d; - *five = values[1].d; - *fifteen = values[2].d; - } -} - -int Platform_getMaxCPU(void) { - if (pcp->ncpu) - return pcp->ncpu; - - pmAtomValue value; - if (Metric_values(PCP_HINV_NCPU, &value, 1, PM_TYPE_32) != NULL) - pcp->ncpu = value.l; - else - pcp->ncpu = -1; - return pcp->ncpu; -} - -int Platform_getMaxPid(void) { - if (pcp->pidmax) - return pcp->pidmax; - - pmAtomValue value; - if (Metric_values(PCP_PID_MAX, &value, 1, PM_TYPE_32) == NULL) - return -1; - pcp->pidmax = value.l; - return pcp->pidmax; -} - -long long Platform_getBootTime(void) { - if (pcp->btime) - return pcp->btime; - - pmAtomValue value; - if (Metric_values(PCP_BOOTTIME, &value, 1, PM_TYPE_64) != NULL) - pcp->btime = value.ll; - return pcp->btime; -} - -static double Platform_setOneCPUValues(Meter* this, pmAtomValue* values) { - - unsigned long long value = values[CPU_TOTAL_PERIOD].ull; - double total = (double) (value == 0 ? 1 : value); - double percent; - - double* v = this->values; - v[CPU_METER_NICE] = values[CPU_NICE_PERIOD].ull / total * 100.0; - v[CPU_METER_NORMAL] = values[CPU_USER_PERIOD].ull / total * 100.0; - if (this->pl->settings->detailedCPUTime) { - v[CPU_METER_KERNEL] = values[CPU_SYSTEM_PERIOD].ull / total * 100.0; - v[CPU_METER_IRQ] = values[CPU_IRQ_PERIOD].ull / total * 100.0; - v[CPU_METER_SOFTIRQ] = values[CPU_SOFTIRQ_PERIOD].ull / total * 100.0; - v[CPU_METER_STEAL] = values[CPU_STEAL_PERIOD].ull / total * 100.0; - v[CPU_METER_GUEST] = values[CPU_GUEST_PERIOD].ull / total * 100.0; - v[CPU_METER_IOWAIT] = values[CPU_IOWAIT_PERIOD].ull / total * 100.0; - this->curItems = 8; - if (this->pl->settings->accountGuestInCPUMeter) - percent = v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6]; - else - percent = v[0] + v[1] + v[2] + v[3] + v[4]; - } else { - v[2] = values[CPU_SYSTEM_ALL_PERIOD].ull / total * 100.0; - value = values[CPU_STEAL_PERIOD].ull + values[CPU_GUEST_PERIOD].ull; - v[3] = value / total * 100.0; - this->curItems = 4; - percent = v[0] + v[1] + v[2] + v[3]; - } - percent = CLAMP(percent, 0.0, 100.0); - if (isnan(percent)) - percent = 0.0; - - v[CPU_METER_FREQUENCY] = values[CPU_FREQUENCY].d; - v[CPU_METER_TEMPERATURE] = NAN; - - return percent; -} - -double Platform_setCPUValues(Meter* this, int cpu) { - const PCPProcessList* pl = (const PCPProcessList*) this->pl; - if (cpu <= 0) /* use aggregate values */ - return Platform_setOneCPUValues(this, pl->cpu); - return Platform_setOneCPUValues(this, pl->percpu[cpu - 1]); -} - -void Platform_setMemoryValues(Meter* this) { - const ProcessList* pl = this->pl; - const PCPProcessList* ppl = (const PCPProcessList*) pl; - - this->total = pl->totalMem; - this->values[0] = pl->usedMem; - this->values[1] = pl->buffersMem; - this->values[2] = pl->sharedMem; - this->values[3] = pl->cachedMem; - this->values[4] = pl->availableMem; - - if (ppl->zfs.enabled != 0) { - this->values[0] -= ppl->zfs.size; - this->values[3] += ppl->zfs.size; - } -} - -void Platform_setSwapValues(Meter* this) { - const ProcessList* pl = this->pl; - this->total = pl->totalSwap; - this->values[0] = pl->usedSwap; - this->values[1] = pl->cachedSwap; -} - -void Platform_setZramValues(Meter* this) { - int i, count = Metric_instanceCount(PCP_ZRAM_CAPACITY); - if (!count) { - this->total = 0; - this->values[0] = 0; - this->values[1] = 0; - return; - } - - pmAtomValue *values = xCalloc(count, sizeof(pmAtomValue)); - ZramStats stats = {0}; - - if (Metric_values(PCP_ZRAM_CAPACITY, values, count, PM_TYPE_U64)) { - for (i = 0; i < count; i++) - stats.totalZram += values[i].ull; - } - if (Metric_values(PCP_ZRAM_ORIGINAL, values, count, PM_TYPE_U64)) { - for (i = 0; i < count; i++) - stats.usedZramOrig += values[i].ull; - } - if (Metric_values(PCP_ZRAM_COMPRESSED, values, count, PM_TYPE_U64)) { - for (i = 0; i < count; i++) - stats.usedZramComp += values[i].ull; - } - - free(values); - - this->total = stats.totalZram; - this->values[0] = stats.usedZramComp; - this->values[1] = stats.usedZramOrig; -} - -void Platform_setZfsArcValues(Meter* this) { - const PCPProcessList* ppl = (const PCPProcessList*) this->pl; - - ZfsArcMeter_readStats(this, &(ppl->zfs)); -} - -void Platform_setZfsCompressedArcValues(Meter* this) { - const PCPProcessList* ppl = (const PCPProcessList*) this->pl; - - ZfsCompressedArcMeter_readStats(this, &(ppl->zfs)); -} - -void Platform_getHostname(char* buffer, size_t size) { - const char* hostname = pmGetContextHostName(pcp->context); - String_safeStrncpy(buffer, hostname, size); -} - -void Platform_getRelease(char** string) { - /* fast-path - previously-formatted string */ - if (string) { - *string = pcp->release; - return; - } - - /* first call, extract just-sampled values */ - pmAtomValue sysname, release, machine, distro; - if (!Metric_values(PCP_UNAME_SYSNAME, &sysname, 1, PM_TYPE_STRING)) - sysname.cp = NULL; - if (!Metric_values(PCP_UNAME_RELEASE, &release, 1, PM_TYPE_STRING)) - release.cp = NULL; - if (!Metric_values(PCP_UNAME_MACHINE, &machine, 1, PM_TYPE_STRING)) - machine.cp = NULL; - if (!Metric_values(PCP_UNAME_DISTRO, &distro, 1, PM_TYPE_STRING)) - distro.cp = NULL; - - size_t length = 16; /* padded for formatting characters */ - if (sysname.cp) - length += strlen(sysname.cp); - if (release.cp) - length += strlen(release.cp); - if (machine.cp) - length += strlen(machine.cp); - if (distro.cp) - length += strlen(distro.cp); - pcp->release = xCalloc(1, length); - - if (sysname.cp) { - strcat(pcp->release, sysname.cp); - strcat(pcp->release, " "); - } - if (release.cp) { - strcat(pcp->release, release.cp); - strcat(pcp->release, " "); - } - if (machine.cp) { - strcat(pcp->release, "["); - strcat(pcp->release, machine.cp); - strcat(pcp->release, "] "); - } - if (distro.cp) { - if (pcp->release[0] != '\0') { - strcat(pcp->release, "@ "); - strcat(pcp->release, distro.cp); - } else { - strcat(pcp->release, distro.cp); - } - strcat(pcp->release, " "); - } - - if (pcp->release) /* cull trailing space */ - pcp->release[strlen(pcp->release)] = '\0'; - - free(distro.cp); - free(machine.cp); - free(release.cp); - free(sysname.cp); -} - -char* Platform_getProcessEnv(pid_t pid) { - pmAtomValue value; - if (!Metric_instance(PCP_PROC_ENVIRON, pid, 0, &value, PM_TYPE_STRING)) - return NULL; - return value.cp; -} - -char* Platform_getInodeFilename(pid_t pid, ino_t inode) { - (void)pid; - (void)inode; - return NULL; -} - -FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { - (void)pid; - return NULL; -} - -void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred) { - *ten = *sixty = *threehundred = 0; - - Metric metric; - if (String_eq(file, "cpu")) - metric = PCP_PSI_CPUSOME; - else if (String_eq(file, "io")) - metric = some ? PCP_PSI_IOSOME : PCP_PSI_IOFULL; - else if (String_eq(file, "mem")) - metric = some ? PCP_PSI_MEMSOME : PCP_PSI_MEMFULL; - else - return; - - pmAtomValue values[3] = {0}; - if (Metric_values(metric, values, 3, PM_TYPE_DOUBLE) != NULL) { - *ten = values[0].d; - *sixty = values[1].d; - *threehundred = values[2].d; - } -} - -bool Platform_getDiskIO(DiskIOData* data) { - memset(data, 0, sizeof(*data)); - - pmAtomValue value; - if (Metric_values(PCP_DISK_READB, &value, 1, PM_TYPE_U64) != NULL) - data->totalBytesRead = value.ull; - if (Metric_values(PCP_DISK_WRITEB, &value, 1, PM_TYPE_U64) != NULL) - data->totalBytesWritten = value.ull; - if (Metric_values(PCP_DISK_ACTIVE, &value, 1, PM_TYPE_U64) != NULL) - data->totalMsTimeSpend = value.ull; - return true; -} - -bool Platform_getNetworkIO(NetworkIOData* data) { - memset(data, 0, sizeof(*data)); - - pmAtomValue value; - if (Metric_values(PCP_NET_RECVB, &value, 1, PM_TYPE_U64) != NULL) - data->bytesReceived = value.ull; - if (Metric_values(PCP_NET_SENDB, &value, 1, PM_TYPE_U64) != NULL) - data->bytesTransmitted = value.ull; - if (Metric_values(PCP_NET_RECVP, &value, 1, PM_TYPE_U64) != NULL) - data->packetsReceived = value.ull; - if (Metric_values(PCP_NET_SENDP, &value, 1, PM_TYPE_U64) != NULL) - data->packetsTransmitted = value.ull; - return true; -} - -void Platform_getBattery(double* level, ACPresence* isOnAC) { - *level = NAN; - *isOnAC = AC_ERROR; -} - -void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { - printf( -" --host=HOSTSPEC metrics source is PMCD at HOSTSPEC [see PCPIntro(1)]\n" -" --hostzone set reporting timezone to local time of metrics source\n" -" --timezone=TZ set reporting timezone\n"); -} - -bool Platform_getLongOption(int opt, ATTR_UNUSED int argc, char** argv) { - /* libpcp export without a header definition */ - extern void __pmAddOptHost(pmOptions *, char *); - - switch (opt) { - case PLATFORM_LONGOPT_HOST: /* --host=HOSTSPEC */ - if (argv[optind][0] == '\0') - return false; - __pmAddOptHost(&opts, optarg); - return true; - - case PLATFORM_LONGOPT_HOSTZONE: /* --hostzone */ - if (opts.timezone) { - pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname()); - opts.errors++; - } else { - opts.tzflag = 1; - } - return true; - - case PLATFORM_LONGOPT_TIMEZONE: /* --timezone=TZ */ - if (argv[optind][0] == '\0') - return false; - if (opts.tzflag) { - pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname()); - opts.errors++; - } else { - opts.timezone = optarg; - } - return true; - - default: - break; - } - return false; -} - -void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { - if (gettimeofday(tv, NULL) == 0) { - /* shift by start offset to stay in lock-step with realtime (archives) */ - if (pcp->offset.tv_sec || pcp->offset.tv_usec) - pmtimevalDec(tv, &pcp->offset); - *msec = ((uint64_t)tv->tv_sec * 1000) + ((uint64_t)tv->tv_usec / 1000); - } else { - memset(tv, 0, sizeof(struct timeval)); - *msec = 0; - } -} - -void Platform_gettime_monotonic(uint64_t* msec) { - struct timeval* tv = &pcp->result->timestamp; - *msec = ((uint64_t)tv->tv_sec * 1000) + ((uint64_t)tv->tv_usec / 1000); -} diff -Nru pcp-5.3.1/src/pcp/htop/pcp/Platform.h pcp-5.3.2/src/pcp/htop/pcp/Platform.h --- pcp-5.3.1/src/pcp/htop/pcp/Platform.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/Platform.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -#ifndef HEADER_Platform -#define HEADER_Platform -/* -htop - pcp/Platform.h -(C) 2014 Hisham H. Muhammad -(C) 2020-2021 htop dev team -(C) 2020-2021 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include -#include -#include - -#undef PACKAGE_URL -#undef PACKAGE_NAME -#undef PACKAGE_STRING -#undef PACKAGE_TARNAME -#undef PACKAGE_VERSION -#undef PACKAGE_BUGREPORT - -#include "Action.h" -#include "BatteryMeter.h" -#include "DiskIOMeter.h" -#include "Meter.h" -#include "NetworkIOMeter.h" -#include "Process.h" -#include "ProcessLocksScreen.h" -#include "SignalsPanel.h" -#include "SysArchMeter.h" - - -extern ProcessField Platform_defaultFields[]; - -extern int Platform_numberOfFields; - -extern const SignalItem Platform_signals[]; - -extern const unsigned int Platform_numberOfSignals; - -extern const MeterClass* const Platform_meterTypes[]; - -void Platform_init(void); - -void Platform_done(void); - -void Platform_setBindings(Htop_Action* keys); - -int Platform_getUptime(void); - -void Platform_getLoadAverage(double* one, double* five, double* fifteen); - -long long Platform_getBootTime(void); - -int Platform_getMaxCPU(void); - -int Platform_getMaxPid(void); - -double Platform_setCPUValues(Meter* this, int cpu); - -void Platform_setMemoryValues(Meter* this); - -void Platform_setSwapValues(Meter* this); - -void Platform_setZramValues(Meter* this); - -void Platform_setZfsArcValues(Meter* this); - -void Platform_setZfsCompressedArcValues(Meter* this); - -char* Platform_getProcessEnv(pid_t pid); - -char* Platform_getInodeFilename(pid_t pid, ino_t inode); - -FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); - -void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred); - -bool Platform_getDiskIO(DiskIOData* data); - -bool Platform_getNetworkIO(NetworkIOData* data); - -void Platform_getBattery(double *percent, ACPresence *isOnAC); - -void Platform_getHostname(char* buffer, size_t size); - -void Platform_getRelease(char** string); - -enum { - PLATFORM_LONGOPT_HOST = 128, - PLATFORM_LONGOPT_TIMEZONE, - PLATFORM_LONGOPT_HOSTZONE, -}; - -#define PLATFORM_LONG_OPTIONS \ - {PMLONGOPT_HOST, optional_argument, 0, PLATFORM_LONGOPT_HOST}, \ - {PMLONGOPT_TIMEZONE, optional_argument, 0, PLATFORM_LONGOPT_TIMEZONE}, \ - {PMLONGOPT_HOSTZONE, optional_argument, 0, PLATFORM_LONGOPT_HOSTZONE}, \ - -void Platform_longOptionsUsage(const char* name); - -bool Platform_getLongOption(int opt, int argc, char** argv); - -extern pmOptions opts; - - -typedef enum Metric_ { - PCP_CONTROL_THREADS, /* proc.control.perclient.threads */ - - PCP_HINV_NCPU, /* hinv.ncpu */ - PCP_HINV_CPUCLOCK, /* hinv.cpu.clock */ - PCP_UNAME_SYSNAME, /* kernel.uname.sysname */ - PCP_UNAME_RELEASE, /* kernel.uname.release */ - PCP_UNAME_MACHINE, /* kernel.uname.machine */ - PCP_UNAME_DISTRO, /* kernel.uname.distro */ - PCP_LOAD_AVERAGE, /* kernel.all.load */ - PCP_PID_MAX, /* kernel.all.pid_max */ - PCP_UPTIME, /* kernel.all.uptime */ - PCP_BOOTTIME, /* kernel.all.boottime */ - PCP_CPU_USER, /* kernel.all.cpu.user */ - PCP_CPU_NICE, /* kernel.all.cpu.nice */ - PCP_CPU_SYSTEM, /* kernel.all.cpu.sys */ - PCP_CPU_IDLE, /* kernel.all.cpu.idle */ - PCP_CPU_IOWAIT, /* kernel.all.cpu.wait.total */ - PCP_CPU_IRQ, /* kernel.all.cpu.intr */ - PCP_CPU_SOFTIRQ, /* kernel.all.cpu.irq.soft */ - PCP_CPU_STEAL, /* kernel.all.cpu.steal */ - PCP_CPU_GUEST, /* kernel.all.cpu.guest */ - PCP_CPU_GUESTNICE, /* kernel.all.cpu.guest_nice */ - PCP_PERCPU_USER, /* kernel.percpu.cpu.user */ - PCP_PERCPU_NICE, /* kernel.percpu.cpu.nice */ - PCP_PERCPU_SYSTEM, /* kernel.percpu.cpu.sys */ - PCP_PERCPU_IDLE, /* kernel.percpu.cpu.idle */ - PCP_PERCPU_IOWAIT, /* kernel.percpu.cpu.wait.total */ - PCP_PERCPU_IRQ, /* kernel.percpu.cpu.intr */ - PCP_PERCPU_SOFTIRQ, /* kernel.percpu.cpu.irq.soft */ - PCP_PERCPU_STEAL, /* kernel.percpu.cpu.steal */ - PCP_PERCPU_GUEST, /* kernel.percpu.cpu.guest */ - PCP_PERCPU_GUESTNICE, /* kernel.percpu.cpu.guest_nice */ - PCP_MEM_TOTAL, /* mem.physmem */ - PCP_MEM_FREE, /* mem.util.free */ - PCP_MEM_BUFFERS, /* mem.util.bufmem */ - PCP_MEM_CACHED, /* mem.util.cached */ - PCP_MEM_SHARED, /* mem.util.shared */ - PCP_MEM_AVAILABLE, /* mem.util.available */ - PCP_MEM_SRECLAIM, /* mem.util.slabReclaimable */ - PCP_MEM_SWAPCACHED, /* mem.util.swapCached */ - PCP_MEM_SWAPTOTAL, /* mem.util.swapTotal */ - PCP_MEM_SWAPFREE, /* mem.util.swapFree */ - PCP_DISK_READB, /* disk.all.read_bytes */ - PCP_DISK_WRITEB, /* disk.all.write_bytes */ - PCP_DISK_ACTIVE, /* disk.all.avactive */ - PCP_NET_RECVB, /* network.all.in.bytes */ - PCP_NET_SENDB, /* network.all.out.bytes */ - PCP_NET_RECVP, /* network.all.in.packets */ - PCP_NET_SENDP, /* network.all.out.packets */ - PCP_PSI_CPUSOME, /* kernel.all.pressure.cpu.some.avg */ - PCP_PSI_IOSOME, /* kernel.all.pressure.io.some.avg */ - PCP_PSI_IOFULL, /* kernel.all.pressure.io.full.avg */ - PCP_PSI_MEMSOME, /* kernel.all.pressure.memory.some.avg */ - PCP_PSI_MEMFULL, /* kernel.all.pressure.memory.full.avg */ - PCP_ZFS_ARC_ANON_SIZE, /* zfs.arc.anon_size */ - PCP_ZFS_ARC_BONUS_SIZE, /* zfs.arc.bonus_size */ - PCP_ZFS_ARC_COMPRESSED_SIZE, /* zfs.arc.compressed_size */ - PCP_ZFS_ARC_UNCOMPRESSED_SIZE, /* zfs.arc.uncompressed_size */ - PCP_ZFS_ARC_C_MAX, /* zfs.arc.c_max */ - PCP_ZFS_ARC_DBUF_SIZE, /* zfs.arc.dbuf_size */ - PCP_ZFS_ARC_DNODE_SIZE, /* zfs.arc.dnode_size */ - PCP_ZFS_ARC_HDR_SIZE, /* zfs.arc.hdr_size */ - PCP_ZFS_ARC_MFU_SIZE, /* zfs.arc.mfu_size */ - PCP_ZFS_ARC_MRU_SIZE, /* zfs.arc.mru_size */ - PCP_ZFS_ARC_SIZE, /* zfs.arc.size */ - PCP_ZRAM_CAPACITY, /* zram.capacity */ - PCP_ZRAM_ORIGINAL, /* zram.mm_stat.data_size.original */ - PCP_ZRAM_COMPRESSED, /* zram.mm_stat.data_size.compressed */ - - PCP_PROC_PID, /* proc.psinfo.pid */ - PCP_PROC_PPID, /* proc.psinfo.ppid */ - PCP_PROC_TGID, /* proc.psinfo.tgid */ - PCP_PROC_PGRP, /* proc.psinfo.pgrp */ - PCP_PROC_SESSION, /* proc.psinfo.session */ - PCP_PROC_STATE, /* proc.psinfo.sname */ - PCP_PROC_TTY, /* proc.psinfo.tty */ - PCP_PROC_TTYPGRP, /* proc.psinfo.tty_pgrp */ - PCP_PROC_MINFLT, /* proc.psinfo.minflt */ - PCP_PROC_MAJFLT, /* proc.psinfo.maj_flt */ - PCP_PROC_CMINFLT, /* proc.psinfo.cmin_flt */ - PCP_PROC_CMAJFLT, /* proc.psinfo.cmaj_flt */ - PCP_PROC_UTIME, /* proc.psinfo.utime */ - PCP_PROC_STIME, /* proc.psinfo.stime */ - PCP_PROC_CUTIME, /* proc.psinfo.cutime */ - PCP_PROC_CSTIME, /* proc.psinfo.cstime */ - PCP_PROC_PRIORITY, /* proc.psinfo.priority */ - PCP_PROC_NICE, /* proc.psinfo.nice */ - PCP_PROC_THREADS, /* proc.psinfo.threads */ - PCP_PROC_STARTTIME, /* proc.psinfo.start_time */ - PCP_PROC_PROCESSOR, /* proc.psinfo.processor */ - PCP_PROC_CMD, /* proc.psinfo.cmd */ - PCP_PROC_PSARGS, /* proc.psinfo.psargs */ - PCP_PROC_CGROUPS, /* proc.psinfo.cgroups */ - PCP_PROC_OOMSCORE, /* proc.psinfo.oom_score */ - PCP_PROC_VCTXSW, /* proc.psinfo.vctxsw */ - PCP_PROC_NVCTXSW, /* proc.psinfo.nvctxsw */ - PCP_PROC_LABELS, /* proc.psinfo.labels */ - PCP_PROC_ENVIRON, /* proc.psinfo.environ */ - PCP_PROC_TTYNAME, /* proc.psinfo.ttyname */ - - PCP_PROC_ID_UID, /* proc.id.uid */ - PCP_PROC_ID_USER, /* proc.id.uid_nm */ - - PCP_PROC_IO_RCHAR, /* proc.io.rchar */ - PCP_PROC_IO_WCHAR, /* proc.io.wchar */ - PCP_PROC_IO_SYSCR, /* proc.io.syscr */ - PCP_PROC_IO_SYSCW, /* proc.io.syscw */ - PCP_PROC_IO_READB, /* proc.io.read_bytes */ - PCP_PROC_IO_WRITEB, /* proc.io.write_bytes */ - PCP_PROC_IO_CANCELLED, /* proc.io.cancelled_write_bytes */ - - PCP_PROC_MEM_SIZE, /* proc.memory.size */ - PCP_PROC_MEM_RSS, /* proc.memory.rss */ - PCP_PROC_MEM_SHARE, /* proc.memory.share */ - PCP_PROC_MEM_TEXTRS, /* proc.memory.textrss */ - PCP_PROC_MEM_LIBRS, /* proc.memory.librss */ - PCP_PROC_MEM_DATRS, /* proc.memory.datrss */ - PCP_PROC_MEM_DIRTY, /* proc.memory.dirty */ - - PCP_PROC_SMAPS_PSS, /* proc.smaps.pss */ - PCP_PROC_SMAPS_SWAP, /* proc.smaps.swap */ - PCP_PROC_SMAPS_SWAPPSS, /* proc.smaps.swappss */ - - PCP_METRIC_COUNT /* total metric count */ -} Metric; - -void Metric_enable(Metric metric, bool enable); - -bool Metric_enabled(Metric metric); - -void Metric_enableThreads(void); - -bool Metric_fetch(struct timeval *timestamp); - -bool Metric_iterate(Metric metric, int* instp, int* offsetp); - -pmAtomValue* Metric_values(Metric metric, pmAtomValue *atom, int count, int type); - -int Metric_instanceCount(Metric metric); - -int Metric_instanceOffset(Metric metric, int inst); - -pmAtomValue *Metric_instance(Metric metric, int inst, int offset, pmAtomValue *atom, int type); - -void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec); - -void Platform_gettime_monotonic(uint64_t* msec); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/pcp/ProcessField.h pcp-5.3.2/src/pcp/htop/pcp/ProcessField.h --- pcp-5.3.1/src/pcp/htop/pcp/ProcessField.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -#ifndef HEADER_PCPProcessField -#define HEADER_PCPProcessField -/* -htop - pcp/ProcessField.h -(C) 2014 Hisham H. Muhammad -(C) 2021 htop dev team -(C) 2020-2021 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - - -#define PLATFORM_PROCESS_FIELDS \ - CMINFLT = 11, \ - CMAJFLT = 13, \ - UTIME = 14, \ - STIME = 15, \ - CUTIME = 16, \ - CSTIME = 17, \ - M_SHARE = 41, \ - M_TRS = 42, \ - M_DRS = 43, \ - M_LRS = 44, \ - M_DT = 45, \ - CTID = 100, \ - RCHAR = 103, \ - WCHAR = 104, \ - SYSCR = 105, \ - SYSCW = 106, \ - RBYTES = 107, \ - WBYTES = 108, \ - CNCLWB = 109, \ - IO_READ_RATE = 110, \ - IO_WRITE_RATE = 111, \ - IO_RATE = 112, \ - CGROUP = 113, \ - OOM = 114, \ - PERCENT_CPU_DELAY = 116, \ - PERCENT_IO_DELAY = 117, \ - PERCENT_SWAP_DELAY = 118, \ - M_PSS = 119, \ - M_SWAP = 120, \ - M_PSSWP = 121, \ - CTXT = 122, \ - SECATTR = 123, \ - PROC_COMM = 124, \ - // End of list - - -#endif /* HEADER_PCPProcessField */ diff -Nru pcp-5.3.1/src/pcp/htop/pcp-htop.c pcp-5.3.2/src/pcp/htop/pcp-htop.c --- pcp-5.3.1/src/pcp/htop/pcp-htop.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/pcp-htop.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -/* -htop - pcp-htop.c -(C) 2004-2011 Hisham H. Muhammad -(C) 2020-2021 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include - -#include "CommandLine.h" -#include "Platform.h" - - -int main(int argc, char** argv) { - const char* name = "pcp-htop"; - pmSetProgname(name); - - /* extract environment variables */ - opts.flags |= PM_OPTFLAG_ENV_ONLY; - (void)pmGetOptions(argc, argv, &opts); - - return CommandLine_run(name, argc, argv); -} diff -Nru pcp-5.3.1/src/pcp/htop/Process.c pcp-5.3.2/src/pcp/htop/Process.c --- pcp-5.3.1/src/pcp/htop/Process.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Process.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,615 +0,0 @@ -/* -htop - Process.c -(C) 2004-2015 Hisham H. Muhammad -(C) 2020 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "Process.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Platform.h" -#include "ProcessList.h" -#include "RichString.h" -#include "Settings.h" -#include "XUtils.h" - -#if defined(MAJOR_IN_MKDEV) -#include -#elif defined(MAJOR_IN_SYSMACROS) -#include -#endif - - -static uid_t Process_getuid = (uid_t)-1; - -int Process_pidDigits = 7; - -void Process_setupColumnWidths() { - int maxPid = Platform_getMaxPid(); - if (maxPid == -1) - return; - - Process_pidDigits = ceil(log10(maxPid)); - assert(Process_pidDigits <= PROCESS_MAX_PID_DIGITS); -} - -void Process_humanNumber(RichString* str, unsigned long long number, bool coloring) { - char buffer[10]; - int len; - - int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; - int processMegabytesColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS]; - int processGigabytesColor = coloring ? CRT_colors[PROCESS_GIGABYTES] : CRT_colors[PROCESS]; - int shadowColor = coloring ? CRT_colors[PROCESS_SHADOW] : CRT_colors[PROCESS]; - int processColor = CRT_colors[PROCESS]; - - if (number == ULLONG_MAX) { - //Invalid number - RichString_appendAscii(str, shadowColor, " N/A "); - } else if (number < 1000) { - //Plain number, no markings - len = xSnprintf(buffer, sizeof(buffer), "%5llu ", number); - RichString_appendnAscii(str, processColor, buffer, len); - } else if (number < 100000) { - //2 digit MB, 3 digit KB - len = xSnprintf(buffer, sizeof(buffer), "%2llu", number/1000); - RichString_appendnAscii(str, processMegabytesColor, buffer, len); - number %= 1000; - len = xSnprintf(buffer, sizeof(buffer), "%03llu ", number); - RichString_appendnAscii(str, processColor, buffer, len); - } else if (number < 1000 * ONE_K) { - //3 digit MB - number /= ONE_K; - len = xSnprintf(buffer, sizeof(buffer), "%4lluM ", number); - RichString_appendnAscii(str, processMegabytesColor, buffer, len); - } else if (number < 10000 * ONE_K) { - //1 digit GB, 3 digit MB - number /= ONE_K; - len = xSnprintf(buffer, sizeof(buffer), "%1llu", number/1000); - RichString_appendnAscii(str, processGigabytesColor, buffer, len); - number %= 1000; - len = xSnprintf(buffer, sizeof(buffer), "%03lluM ", number); - RichString_appendnAscii(str, processMegabytesColor, buffer, len); - } else if (number < 100000 * ONE_K) { - //2 digit GB, 1 digit MB - number /= 100 * ONE_K; - len = xSnprintf(buffer, sizeof(buffer), "%2llu", number/10); - RichString_appendnAscii(str, processGigabytesColor, buffer, len); - number %= 10; - len = xSnprintf(buffer, sizeof(buffer), ".%1llu", number); - RichString_appendnAscii(str, processMegabytesColor, buffer, len); - RichString_appendAscii(str, processGigabytesColor, "G "); - } else if (number < 1000 * ONE_M) { - //3 digit GB - number /= ONE_M; - len = xSnprintf(buffer, sizeof(buffer), "%4lluG ", number); - RichString_appendnAscii(str, processGigabytesColor, buffer, len); - } else if (number < 10000ULL * ONE_M) { - //1 digit TB, 3 digit GB - number /= ONE_M; - len = xSnprintf(buffer, sizeof(buffer), "%1llu", number/1000); - RichString_appendnAscii(str, largeNumberColor, buffer, len); - number %= 1000; - len = xSnprintf(buffer, sizeof(buffer), "%03lluG ", number); - RichString_appendnAscii(str, processGigabytesColor, buffer, len); - } else { - //2 digit TB and above - len = xSnprintf(buffer, sizeof(buffer), "%4.1lfT ", (double)number/ONE_G); - RichString_appendnAscii(str, largeNumberColor, buffer, len); - } -} - -void Process_colorNumber(RichString* str, unsigned long long number, bool coloring) { - char buffer[13]; - - int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; - int processMegabytesColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS]; - int processColor = CRT_colors[PROCESS]; - int processShadowColor = coloring ? CRT_colors[PROCESS_SHADOW] : CRT_colors[PROCESS]; - - if (number == ULLONG_MAX) { - RichString_appendAscii(str, CRT_colors[PROCESS_SHADOW], " N/A "); - } else if (number >= 100000LL * ONE_DECIMAL_T) { - xSnprintf(buffer, sizeof(buffer), "%11llu ", number / ONE_DECIMAL_G); - RichString_appendnAscii(str, largeNumberColor, buffer, 12); - } else if (number >= 100LL * ONE_DECIMAL_T) { - xSnprintf(buffer, sizeof(buffer), "%11llu ", number / ONE_DECIMAL_M); - RichString_appendnAscii(str, largeNumberColor, buffer, 8); - RichString_appendnAscii(str, processMegabytesColor, buffer+8, 4); - } else if (number >= 10LL * ONE_DECIMAL_G) { - xSnprintf(buffer, sizeof(buffer), "%11llu ", number / ONE_DECIMAL_K); - RichString_appendnAscii(str, largeNumberColor, buffer, 5); - RichString_appendnAscii(str, processMegabytesColor, buffer+5, 3); - RichString_appendnAscii(str, processColor, buffer+8, 4); - } else { - xSnprintf(buffer, sizeof(buffer), "%11llu ", number); - RichString_appendnAscii(str, largeNumberColor, buffer, 2); - RichString_appendnAscii(str, processMegabytesColor, buffer+2, 3); - RichString_appendnAscii(str, processColor, buffer+5, 3); - RichString_appendnAscii(str, processShadowColor, buffer+8, 4); - } -} - -void Process_printTime(RichString* str, unsigned long long totalHundredths) { - unsigned long long totalSeconds = totalHundredths / 100; - - unsigned long long hours = totalSeconds / 3600; - int minutes = (totalSeconds / 60) % 60; - int seconds = totalSeconds % 60; - int hundredths = totalHundredths - (totalSeconds * 100); - char buffer[10]; - if (hours >= 100) { - xSnprintf(buffer, sizeof(buffer), "%7lluh ", hours); - RichString_appendAscii(str, CRT_colors[LARGE_NUMBER], buffer); - } else { - if (hours) { - xSnprintf(buffer, sizeof(buffer), "%2lluh", hours); - RichString_appendAscii(str, CRT_colors[LARGE_NUMBER], buffer); - xSnprintf(buffer, sizeof(buffer), "%02d:%02d ", minutes, seconds); - } else { - xSnprintf(buffer, sizeof(buffer), "%2d:%02d.%02d ", minutes, seconds, hundredths); - } - RichString_appendAscii(str, CRT_colors[DEFAULT_COLOR], buffer); - } -} - -void Process_fillStarttimeBuffer(Process* this) { - struct tm date; - (void) localtime_r(&this->starttime_ctime, &date); - strftime(this->starttime_show, sizeof(this->starttime_show) - 1, (this->starttime_ctime > (time(NULL) - 86400)) ? "%R " : "%b%d ", &date); -} - -static inline void Process_writeCommand(const Process* this, int attr, int baseattr, RichString* str) { - int start = RichString_size(str); - int len = 0; - const char* comm = this->comm; - - if (this->settings->highlightBaseName || !this->settings->showProgramPath) { - int basename = 0; - for (int i = 0; i < this->basenameOffset; i++) { - if (comm[i] == '/') { - basename = i + 1; - } else if (comm[i] == ':') { - len = i + 1; - break; - } - } - if (len == 0) { - if (this->settings->showProgramPath) { - start += basename; - } else { - comm += basename; - } - len = this->basenameOffset - basename; - } - } - - RichString_appendWide(str, attr, comm); - - if (this->settings->highlightBaseName) { - RichString_setAttrn(str, baseattr, start, len); - } -} - -void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring) { - int largeNumberColor = CRT_colors[LARGE_NUMBER]; - int processMegabytesColor = CRT_colors[PROCESS_MEGABYTES]; - int processColor = CRT_colors[PROCESS]; - - if (!coloring) { - largeNumberColor = CRT_colors[PROCESS]; - processMegabytesColor = CRT_colors[PROCESS]; - } - - if (isnan(rate)) { - RichString_appendAscii(str, CRT_colors[PROCESS_SHADOW], " N/A "); - } else if (rate < ONE_K) { - int len = snprintf(buffer, n, "%7.2f B/s ", rate); - RichString_appendnAscii(str, processColor, buffer, len); - } else if (rate < ONE_M) { - int len = snprintf(buffer, n, "%7.2f K/s ", rate / ONE_K); - RichString_appendnAscii(str, processColor, buffer, len); - } else if (rate < ONE_G) { - int len = snprintf(buffer, n, "%7.2f M/s ", rate / ONE_M); - RichString_appendnAscii(str, processMegabytesColor, buffer, len); - } else if (rate < ONE_T) { - int len = snprintf(buffer, n, "%7.2f G/s ", rate / ONE_G); - RichString_appendnAscii(str, largeNumberColor, buffer, len); - } else { - int len = snprintf(buffer, n, "%7.2f T/s ", rate / ONE_T); - RichString_appendnAscii(str, largeNumberColor, buffer, len); - } -} - -void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width) { - int columns = width; - RichString_appendnWideColumns(str, attr, content, strlen(content), &columns); - RichString_appendChr(str, attr, ' ', width + 1 - columns); -} - -void Process_writeField(const Process* this, RichString* str, ProcessField field) { - char buffer[256]; - size_t n = sizeof(buffer); - int attr = CRT_colors[DEFAULT_COLOR]; - bool coloring = this->settings->highlightMegabytes; - - switch (field) { - case COMM: { - int baseattr = CRT_colors[PROCESS_BASENAME]; - if (this->settings->highlightThreads && Process_isThread(this)) { - attr = CRT_colors[PROCESS_THREAD]; - baseattr = CRT_colors[PROCESS_THREAD_BASENAME]; - } - if (!this->settings->treeView || this->indent == 0) { - Process_writeCommand(this, attr, baseattr, str); - return; - } - - char* buf = buffer; - int maxIndent = 0; - bool lastItem = (this->indent < 0); - int indent = (this->indent < 0 ? -this->indent : this->indent); - - for (int i = 0; i < 32; i++) { - if (indent & (1U << i)) { - maxIndent = i+1; - } - } - - for (int i = 0; i < maxIndent - 1; i++) { - int written, ret; - if (indent & (1 << i)) { - ret = xSnprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]); - } else { - ret = xSnprintf(buf, n, " "); - } - if (ret < 0 || (size_t)ret >= n) { - written = n; - } else { - written = ret; - } - buf += written; - n -= written; - } - - const char* draw = CRT_treeStr[lastItem ? TREE_STR_BEND : TREE_STR_RTEE]; - xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] ); - RichString_appendWide(str, CRT_colors[PROCESS_TREE], buffer); - Process_writeCommand(this, attr, baseattr, str); - return; - } - case MAJFLT: Process_colorNumber(str, this->majflt, coloring); return; - case MINFLT: Process_colorNumber(str, this->minflt, coloring); return; - case M_RESIDENT: Process_humanNumber(str, this->m_resident, coloring); return; - case M_VIRT: Process_humanNumber(str, this->m_virt, coloring); return; - case NICE: - xSnprintf(buffer, n, "%3ld ", this->nice); - attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY] - : this->nice > 0 ? CRT_colors[PROCESS_LOW_PRIORITY] - : CRT_colors[PROCESS_SHADOW]; - break; - case NLWP: - if (this->nlwp == 1) - attr = CRT_colors[PROCESS_SHADOW]; - - xSnprintf(buffer, n, "%4ld ", this->nlwp); - break; - case PERCENT_CPU: - case PERCENT_NORM_CPU: { - float cpuPercentage = this->percent_cpu; - if (field == PERCENT_NORM_CPU) { - cpuPercentage /= this->processList->cpuCount; - } - if (cpuPercentage > 999.9F) { - xSnprintf(buffer, n, "%4u ", (unsigned int)cpuPercentage); - } else if (cpuPercentage > 99.9F) { - xSnprintf(buffer, n, "%3u. ", (unsigned int)cpuPercentage); - } else { - if (cpuPercentage < 0.05F) - attr = CRT_colors[PROCESS_SHADOW]; - - xSnprintf(buffer, n, "%4.1f ", cpuPercentage); - } - break; - } - case PERCENT_MEM: - if (this->percent_mem > 99.9F) { - xSnprintf(buffer, n, "100. "); - } else { - if (this->percent_mem < 0.05F) - attr = CRT_colors[PROCESS_SHADOW]; - - xSnprintf(buffer, n, "%4.1f ", this->percent_mem); - } - break; - case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break; - case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pid); break; - case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->ppid); break; - case PRIORITY: - if (this->priority <= -100) - xSnprintf(buffer, n, " RT "); - else - xSnprintf(buffer, n, "%3ld ", this->priority); - break; - case PROCESSOR: xSnprintf(buffer, n, "%3d ", Settings_cpuId(this->settings, this->processor)); break; - case SESSION: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->session); break; - case STARTTIME: xSnprintf(buffer, n, "%s", this->starttime_show); break; - case STATE: - xSnprintf(buffer, n, "%c ", this->state); - switch (this->state) { - case 'R': - attr = CRT_colors[PROCESS_R_STATE]; - break; - case 'D': - attr = CRT_colors[PROCESS_D_STATE]; - break; - case 'I': - case 'S': - attr = CRT_colors[PROCESS_SHADOW]; - break; - } - break; - case ST_UID: xSnprintf(buffer, n, "%5d ", this->st_uid); break; - case TIME: Process_printTime(str, this->time); return; - case TGID: - if (this->tgid == this->pid) - attr = CRT_colors[PROCESS_SHADOW]; - - xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tgid); - break; - case TPGID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tpgid); break; - case TTY_NR: { - unsigned int major = major(this->tty_nr); - unsigned int minor = minor(this->tty_nr); - if (major == 0 && minor == 0) { - attr = CRT_colors[PROCESS_SHADOW]; - xSnprintf(buffer, n, "(none) "); - } else { - xSnprintf(buffer, n, "%3u:%3u ", major, minor); - } - break; - } - case USER: - if (Process_getuid != this->st_uid) - attr = CRT_colors[PROCESS_SHADOW]; - - if (this->user) { - Process_printLeftAlignedField(str, attr, this->user, 9); - return; - } - - xSnprintf(buffer, n, "%-9d ", this->st_uid); - break; - default: - assert(0); /* should never be reached */ - xSnprintf(buffer, n, "- "); - } - RichString_appendWide(str, attr, buffer); -} - -void Process_display(const Object* cast, RichString* out) { - const Process* this = (const Process*) cast; - const ProcessField* fields = this->settings->fields; - for (int i = 0; fields[i]; i++) - As_Process(this)->writeField(this, out, fields[i]); - - if (this->settings->shadowOtherUsers && this->st_uid != Process_getuid) { - RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]); - } - - if (this->tag == true) { - RichString_setAttr(out, CRT_colors[PROCESS_TAG]); - } - - if (this->settings->highlightChanges) { - if (Process_isTomb(this)) { - out->highlightAttr = CRT_colors[PROCESS_TOMB]; - } else if (Process_isNew(this)) { - out->highlightAttr = CRT_colors[PROCESS_NEW]; - } - } - - assert(RichString_size(out) > 0); -} - -void Process_done(Process* this) { - assert (this != NULL); - free(this->comm); -} - -static const char* Process_getCommandStr(const Process* p) { - return p->comm ? p->comm : ""; -} - -const ProcessClass Process_class = { - .super = { - .extends = Class(Object), - .display = Process_display, - .delete = Process_delete, - .compare = Process_compare - }, - .writeField = Process_writeField, - .getCommandStr = Process_getCommandStr, -}; - -void Process_init(Process* this, const Settings* settings) { - this->settings = settings; - this->tag = false; - this->showChildren = true; - this->show = true; - this->updated = false; - this->basenameOffset = -1; - - if (Process_getuid == (uid_t)-1) { - Process_getuid = getuid(); - } -} - -void Process_toggleTag(Process* this) { - this->tag = !this->tag; -} - -bool Process_isNew(const Process* this) { - assert(this->processList); - if (this->processList->monotonicMs >= this->seenStampMs) { - return this->processList->monotonicMs - this->seenStampMs <= 1000 * (uint64_t)this->processList->settings->highlightDelaySecs; - } - return false; -} - -bool Process_isTomb(const Process* this) { - return this->tombStampMs > 0; -} - -bool Process_setPriority(Process* this, int priority) { - int old_prio = getpriority(PRIO_PROCESS, this->pid); - int err = setpriority(PRIO_PROCESS, this->pid, priority); - - if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) { - this->nice = priority; - } - return (err == 0); -} - -bool Process_changePriorityBy(Process* this, Arg delta) { - return Process_setPriority(this, this->nice + delta.i); -} - -bool Process_sendSignal(Process* this, Arg sgn) { - return kill(this->pid, sgn.i) == 0; -} - -int Process_pidCompare(const void* v1, const void* v2) { - const Process* p1 = (const Process*)v1; - const Process* p2 = (const Process*)v2; - - return SPACESHIP_NUMBER(p1->pid, p2->pid); -} - -int Process_compare(const void* v1, const void* v2) { - const Process *p1 = (const Process*)v1; - const Process *p2 = (const Process*)v2; - - const Settings *settings = p1->settings; - - ProcessField key = Settings_getActiveSortKey(settings); - - int result = Process_compareByKey(p1, p2, key); - - // Implement tie-breaker (needed to make tree mode more stable) - if (!result) - return SPACESHIP_NUMBER(p1->pid, p2->pid); - - return (Settings_getActiveDirection(settings) == 1) ? result : -result; -} - -static uint8_t stateCompareValue(char state) { - switch (state) { - - case 'S': - return 10; - - case 'I': - return 9; - - case 'X': - return 8; - - case 'Z': - return 7; - - case 't': - return 6; - - case 'T': - return 5; - - case 'L': - return 4; - - case 'D': - return 3; - - case 'R': - return 2; - - case '?': - return 1; - - default: - return 0; - } -} - -int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) { - int r; - - switch (key) { - case PERCENT_CPU: - case PERCENT_NORM_CPU: - return SPACESHIP_NUMBER(p1->percent_cpu, p2->percent_cpu); - case PERCENT_MEM: - return SPACESHIP_NUMBER(p1->m_resident, p2->m_resident); - case COMM: - return SPACESHIP_NULLSTR(Process_getCommand(p1), Process_getCommand(p2)); - case MAJFLT: - return SPACESHIP_NUMBER(p1->majflt, p2->majflt); - case MINFLT: - return SPACESHIP_NUMBER(p1->minflt, p2->minflt); - case M_RESIDENT: - return SPACESHIP_NUMBER(p1->m_resident, p2->m_resident); - case M_VIRT: - return SPACESHIP_NUMBER(p1->m_virt, p2->m_virt); - case NICE: - return SPACESHIP_NUMBER(p1->nice, p2->nice); - case NLWP: - return SPACESHIP_NUMBER(p1->nlwp, p2->nlwp); - case PGRP: - return SPACESHIP_NUMBER(p1->pgrp, p2->pgrp); - case PID: - return SPACESHIP_NUMBER(p1->pid, p2->pid); - case PPID: - return SPACESHIP_NUMBER(p1->ppid, p2->ppid); - case PRIORITY: - return SPACESHIP_NUMBER(p1->priority, p2->priority); - case PROCESSOR: - return SPACESHIP_NUMBER(p1->processor, p2->processor); - case SESSION: - return SPACESHIP_NUMBER(p1->session, p2->session); - case STARTTIME: - r = SPACESHIP_NUMBER(p1->starttime_ctime, p2->starttime_ctime); - return r != 0 ? r : SPACESHIP_NUMBER(p1->pid, p2->pid); - case STATE: - return SPACESHIP_NUMBER(stateCompareValue(p1->state), stateCompareValue(p2->state)); - case ST_UID: - return SPACESHIP_NUMBER(p1->st_uid, p2->st_uid); - case TIME: - return SPACESHIP_NUMBER(p1->time, p2->time); - case TGID: - return SPACESHIP_NUMBER(p1->tgid, p2->tgid); - case TPGID: - return SPACESHIP_NUMBER(p1->tpgid, p2->tpgid); - case TTY_NR: - return SPACESHIP_NUMBER(p1->tty_nr, p2->tty_nr); - case USER: - return SPACESHIP_NULLSTR(p1->user, p2->user); - default: - return SPACESHIP_NUMBER(p1->pid, p2->pid); - } -} diff -Nru pcp-5.3.1/src/pcp/htop/Process.h pcp-5.3.2/src/pcp/htop/Process.h --- pcp-5.3.1/src/pcp/htop/Process.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Process.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,296 +0,0 @@ -#ifndef HEADER_Process -#define HEADER_Process -/* -htop - Process.h -(C) 2004-2015 Hisham H. Muhammad -(C) 2020 Red Hat, Inc. All Rights Reserved. -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include -#include -#include - -#include "Object.h" -#include "ProcessField.h" -#include "RichString.h" - - -#define PROCESS_FLAG_IO 0x0001 -#define DEFAULT_HIGHLIGHT_SECS 5 - -typedef enum ProcessField_ { - NULL_PROCESSFIELD = 0, - PID = 1, - COMM = 2, - STATE = 3, - PPID = 4, - PGRP = 5, - SESSION = 6, - TTY_NR = 7, - TPGID = 8, - MINFLT = 10, - MAJFLT = 12, - PRIORITY = 18, - NICE = 19, - STARTTIME = 21, - PROCESSOR = 38, - M_VIRT = 39, - M_RESIDENT = 40, - ST_UID = 46, - PERCENT_CPU = 47, - PERCENT_MEM = 48, - USER = 49, - TIME = 50, - NLWP = 51, - TGID = 52, - PERCENT_NORM_CPU = 53, - - /* Platform specific fields, defined in ${platform}/ProcessField.h */ - PLATFORM_PROCESS_FIELDS - - LAST_PROCESSFIELD -} ProcessField; - -struct Settings_; - -typedef struct Process_ { - /* Super object for emulated OOP */ - Object super; - - /* Pointer to quasi-global data structures */ - const struct ProcessList_* processList; - const struct Settings_* settings; - - /* Process runtime (in hundredth of a second) */ - unsigned long long int time; - - /* Process identifier */ - pid_t pid; - - /* Parent process identifier */ - pid_t ppid; - - /* Thread group identifier */ - pid_t tgid; - - /* Process group identifier */ - int pgrp; - - /* Session identifier */ - int session; - - /* Foreground group identifier of the controlling terminal */ - int tpgid; - - /* - * Controlling terminal of the process. - * The minor device number is contained in the combination of bits 31 to 20 and 7 to 0; the major device number is in bits 15 to 8. - * */ - unsigned int tty_nr; - - /* User identifier */ - uid_t st_uid; - - /* User name */ - const char* user; - - /* - * Process name including arguments. - * Use Process_getCommand() for Command actually displayed. - */ - char* comm; - - /* Offset in comm of the process basename */ - int basenameOffset; - - /* CPU number last executed on */ - int processor; - - /* CPU usage during last cycle (in percent) */ - float percent_cpu; - - /* Memory usage during last cycle (in percent) */ - float percent_mem; - - /* Scheduling priority */ - long int priority; - - /* Nice value */ - long int nice; - - /* Number of threads in this process */ - long int nlwp; - - /* Process start time (in seconds elapsed since the Epoch) */ - time_t starttime_ctime; - - /* Process start time (cached formatted string) */ - char starttime_show[8]; - - /* Total program size (in kilobytes) */ - long m_virt; - - /* Resident set size (in kilobytes) */ - long m_resident; - - /* Number of minor faults the process has made which have not required loading a memory page from disk */ - unsigned long int minflt; - - /* Number of major faults the process has made which have required loading a memory page from disk */ - unsigned long int majflt; - - /* - * Process state (platform dependent): - * D - Waiting - * I - Idle - * L - Acquiring lock - * R - Running - * S - Sleeping - * T - Stopped (on a signal) - * X - Dead - * Z - Zombie - * t - Tracing stop - * ? - Unknown - */ - char state; - - /* Whether the process was updated during the current scan */ - bool updated; - - /* Whether the process was tagged by the user */ - bool tag; - - /* Whether to display this process */ - bool show; - - /* Whether this process was shown last cycle */ - bool wasShown; - - /* Whether to show children of this process in tree-mode */ - bool showChildren; - - /* - * Internal time counts for showing new and exited processes. - */ - uint64_t seenStampMs; - uint64_t tombStampMs; - - /* - * Internal state for tree-mode. - */ - int indent; - unsigned int tree_left; - unsigned int tree_right; - unsigned int tree_depth; - unsigned int tree_index; -} Process; - -typedef struct ProcessFieldData_ { - /* Name (displayed in setup menu) */ - const char* name; - - /* Title (display in main screen); must have same width as the printed values */ - const char* title; - - /* Description (displayed in setup menu) */ - const char* description; - - /* Scan flag to enable scan-method otherwise not run */ - uint32_t flags; - - /* Whether the values are process identifies; adjusts the width of title and values if true */ - bool pidColumn; - - /* Whether the column should be sorted in descending order by default */ - bool defaultSortDesc; -} ProcessFieldData; - -// Implemented in platform-specific code: -void Process_writeField(const Process* this, RichString* str, ProcessField field); -int Process_compare(const void* v1, const void* v2); -void Process_delete(Object* cast); -bool Process_isThread(const Process* this); -extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; -#define PROCESS_MAX_PID_DIGITS 19 -extern int Process_pidDigits; - -typedef Process*(*Process_New)(const struct Settings_*); -typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField); -typedef int (*Process_CompareByKey)(const Process*, const Process*, ProcessField); -typedef const char* (*Process_GetCommandStr)(const Process*); - -typedef struct ProcessClass_ { - const ObjectClass super; - const Process_WriteField writeField; - const Process_CompareByKey compareByKey; - const Process_GetCommandStr getCommandStr; -} ProcessClass; - -#define As_Process(this_) ((const ProcessClass*)((this_)->super.klass)) - -#define Process_getCommand(this_) (As_Process(this_)->getCommandStr ? As_Process(this_)->getCommandStr((const Process*)(this_)) : ((const Process*)(this_))->comm) -#define Process_compareByKey(p1_, p2_, key_) (As_Process(p1_)->compareByKey ? (As_Process(p1_)->compareByKey(p1_, p2_, key_)) : Process_compareByKey_Base(p1_, p2_, key_)) - -static inline pid_t Process_getParentPid(const Process* this) { - return this->tgid == this->pid ? this->ppid : this->tgid; -} - -static inline bool Process_isChildOf(const Process* this, pid_t pid) { - return pid == Process_getParentPid(this); -} - -#define ONE_K 1024UL -#define ONE_M (ONE_K * ONE_K) -#define ONE_G (ONE_M * ONE_K) -#define ONE_T (1ULL * ONE_G * ONE_K) - -#define ONE_DECIMAL_K 1000UL -#define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K) -#define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K) -#define ONE_DECIMAL_T (1ULL * ONE_DECIMAL_G * ONE_DECIMAL_K) - -void Process_setupColumnWidths(void); - -/* Takes number in kilo units (base 1024) */ -void Process_humanNumber(RichString* str, unsigned long long number, bool coloring); - -/* Takes number in bare units (base 1000) */ -void Process_colorNumber(RichString* str, unsigned long long number, bool coloring); - -/* Takes number in hundredths of a seconds */ -void Process_printTime(RichString* str, unsigned long long totalHundredths); - -void Process_fillStarttimeBuffer(Process* this); - -/* Takes number in bare units (base 1024) */ -void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring); - -void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width); - -void Process_display(const Object* cast, RichString* out); - -void Process_done(Process* this); - -extern const ProcessClass Process_class; - -void Process_init(Process* this, const struct Settings_* settings); - -void Process_toggleTag(Process* this); - -bool Process_isNew(const Process* this); - -bool Process_isTomb(const Process* this); - -bool Process_setPriority(Process* this, int priority); - -bool Process_changePriorityBy(Process* this, Arg delta); - -bool Process_sendSignal(Process* this, Arg sgn); - -int Process_pidCompare(const void* v1, const void* v2); - -int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ProcessList.c pcp-5.3.2/src/pcp/htop/ProcessList.c --- pcp-5.3.1/src/pcp/htop/ProcessList.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ProcessList.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,647 +0,0 @@ -/* -htop - ProcessList.c -(C) 2004,2005 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ProcessList.h" - -#include -#include -#include -#include - -#include "CRT.h" -#include "Hashtable.h" -#include "Macros.h" -#include "Platform.h" -#include "Vector.h" -#include "XUtils.h" - - -ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) { - this->processes = Vector_new(klass, true, DEFAULT_SIZE); - this->processes2 = Vector_new(klass, true, DEFAULT_SIZE); // tree-view auxiliary buffer - - this->processTable = Hashtable_new(200, false); - this->displayTreeSet = Hashtable_new(200, false); - this->draftingTreeSet = Hashtable_new(200, false); - - this->usersTable = usersTable; - this->pidMatchList = pidMatchList; - - this->userId = userId; - - // set later by platform-specific code - this->cpuCount = 0; - - this->monotonicMs = 0; - -#ifdef HAVE_LIBHWLOC - this->topologyOk = false; - if (hwloc_topology_init(&this->topology) == 0) { - this->topologyOk = - #if HWLOC_API_VERSION < 0x00020000 - /* try to ignore the top-level machine object type */ - 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_MACHINE) && - /* ignore caches, which don't add structure */ - 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CORE) && - 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CACHE) && - 0 == hwloc_topology_set_flags(this->topology, HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) && - #else - 0 == hwloc_topology_set_all_types_filter(this->topology, HWLOC_TYPE_FILTER_KEEP_STRUCTURE) && - #endif - 0 == hwloc_topology_load(this->topology); - } -#endif - - this->following = -1; - - return this; -} - -void ProcessList_done(ProcessList* this) { -#ifdef HAVE_LIBHWLOC - if (this->topologyOk) { - hwloc_topology_destroy(this->topology); - } -#endif - - Hashtable_delete(this->draftingTreeSet); - Hashtable_delete(this->displayTreeSet); - Hashtable_delete(this->processTable); - - Vector_delete(this->processes2); - Vector_delete(this->processes); -} - -void ProcessList_setPanel(ProcessList* this, Panel* panel) { - this->panel = panel; -} - -static const char* alignedProcessFieldTitle(ProcessField field) { - const char* title = Process_fields[field].title; - if (!title) - return "- "; - - if (!Process_fields[field].pidColumn) - return title; - - static char titleBuffer[PROCESS_MAX_PID_DIGITS + /* space */ 1 + /* null-terminator */ + 1]; - xSnprintf(titleBuffer, sizeof(titleBuffer), "%*s ", Process_pidDigits, title); - - return titleBuffer; -} - -void ProcessList_printHeader(const ProcessList* this, RichString* header) { - RichString_rewind(header, RichString_size(header)); - - const Settings* settings = this->settings; - const ProcessField* fields = settings->fields; - - ProcessField key = Settings_getActiveSortKey(settings); - - for (int i = 0; fields[i]; i++) { - int color; - if (settings->treeView && settings->treeViewAlwaysByPID) { - color = CRT_colors[PANEL_HEADER_FOCUS]; - } else if (key == fields[i]) { - color = CRT_colors[PANEL_SELECTION_FOCUS]; - } else { - color = CRT_colors[PANEL_HEADER_FOCUS]; - } - - RichString_appendWide(header, color, alignedProcessFieldTitle(fields[i])); - if (key == fields[i] && RichString_getCharVal(*header, RichString_size(header) - 1) == ' ') { - RichString_rewind(header, 1); // rewind to override space - RichString_appendnWide(header, - CRT_colors[PANEL_SELECTION_FOCUS], - CRT_treeStr[Settings_getActiveDirection(this->settings) == 1 ? TREE_STR_ASC : TREE_STR_DESC], - 1); - } - if (COMM == fields[i] && settings->showMergedCommand) { - RichString_appendAscii(header, color, "(merged)"); - } - } -} - -void ProcessList_add(ProcessList* this, Process* p) { - assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1); - assert(Hashtable_get(this->processTable, p->pid) == NULL); - p->processList = this; - - // highlighting processes found in first scan by first scan marked "far in the past" - p->seenStampMs = this->monotonicMs; - - Vector_add(this->processes, p); - Hashtable_put(this->processTable, p->pid, p); - - assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1); - assert(Hashtable_get(this->processTable, p->pid) != NULL); - assert(Hashtable_count(this->processTable) == Vector_count(this->processes)); -} - -void ProcessList_remove(ProcessList* this, const Process* p) { - assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1); - assert(Hashtable_get(this->processTable, p->pid) != NULL); - - const Process* pp = Hashtable_remove(this->processTable, p->pid); - assert(pp == p); (void)pp; - - pid_t pid = p->pid; - int idx = Vector_indexOf(this->processes, p, Process_pidCompare); - assert(idx != -1); - - if (idx >= 0) { - Vector_remove(this->processes, idx); - } - - if (this->following != -1 && this->following == pid) { - this->following = -1; - Panel_setSelectionColor(this->panel, PANEL_SELECTION_FOCUS); - } - - assert(Hashtable_get(this->processTable, pid) == NULL); - assert(Hashtable_count(this->processTable) == Vector_count(this->processes)); -} - -Process* ProcessList_get(ProcessList* this, int idx) { - return (Process*)Vector_get(this->processes, idx); -} - -int ProcessList_size(const ProcessList* this) { - return Vector_size(this->processes); -} - -// ProcessList_updateTreeSetLayer sorts this->displayTreeSet, -// relying only on itself. -// -// Algorithm -// -// The algorithm is based on `depth-first search`, -// even though `breadth-first search` approach may be more efficient on first glance, -// after comparison it may be not, as it's not safe to go deeper without first updating the tree structure. -// If it would be safe that approach would likely bring an advantage in performance. -// -// Each call of the function looks for a 'layer'. A 'layer' is a list of processes with the same depth. -// First it sorts a list. Then it runs the function recursively for each element of the sorted list. -// After that it updates the settings of processes. -// -// It relies on `leftBound` and `rightBound` as an optimization to cut the list size at the time it builds a 'layer'. -// -// It uses a temporary Hashtable `draftingTreeSet` because it's not safe to traverse a tree -// and at the same time make changes in it. -// -static void ProcessList_updateTreeSetLayer(ProcessList* this, unsigned int leftBound, unsigned int rightBound, unsigned int deep, unsigned int left, unsigned int right, unsigned int* index, unsigned int* treeIndex, int indent) { - - // It's guaranteed that layer_size is enough space - // but most likely it needs less. Specifically on first iteration. - int layerSize = (right - left) / 2; - - // check if we reach `children` of `leaves` - if (layerSize == 0) - return; - - Vector* layer = Vector_new(Vector_type(this->processes), false, layerSize); - - // Find all processes on the same layer (process with the same `deep` value - // and included in a range from `leftBound` to `rightBound`). - // - // This loop also keeps track of left_bound and right_bound of these processes - // in order not to lose this information once the list is sorted. - // - // The variables left_bound and right_bound are different from what the values lhs and rhs represent. - // While left_bound and right_bound define a range of processes to look at, the values given by lhs and rhs are indices into an array - // - // In the below example note how filtering a range of indices i is different from filtering for processes in the bounds left_bound < x < right_bound … - // - // The nested tree set is sorted by left value, which is guaranteed upon entry/exit of this function. - // - // i | l | r - // 1 | 1 | 9 - // 2 | 2 | 8 - // 3 | 4 | 5 - // 4 | 6 | 7 - for (unsigned int i = leftBound; i < rightBound; i++) { - Process* proc = (Process*)Hashtable_get(this->displayTreeSet, i); - assert(proc); - if (proc && proc->tree_depth == deep && proc->tree_left > left && proc->tree_right < right) { - if (Vector_size(layer) > 0) { - Process* previous_process = (Process*)Vector_get(layer, Vector_size(layer) - 1); - - // Make a 'right_bound' of previous_process in a layer the current process's index. - // - // Use 'tree_depth' as a temporal variable. - // It's safe to do as later 'tree_depth' will be renovated. - previous_process->tree_depth = proc->tree_index; - } - - Vector_add(layer, proc); - } - } - - // The loop above changes just up to process-1. - // So the last process of the layer isn't updated by the above code. - // - // Thus, if present, set the `rightBound` to the last process on the layer - if (Vector_size(layer) > 0) { - Process* previous_process = (Process*)Vector_get(layer, Vector_size(layer) - 1); - previous_process->tree_depth = rightBound; - } - - Vector_quickSort(layer); - - int size = Vector_size(layer); - for (int i = 0; i < size; i++) { - Process* proc = (Process*)Vector_get(layer, i); - - unsigned int idx = (*index)++; - int newLeft = (*treeIndex)++; - - int level = deep == 0 ? 0 : (int)deep - 1; - int currentIndent = indent == -1 ? 0 : indent | (1 << level); - int nextIndent = indent == -1 ? 0 : ((i < size - 1) ? currentIndent : indent); - - unsigned int newLeftBound = proc->tree_index; - unsigned int newRightBound = proc->tree_depth; - ProcessList_updateTreeSetLayer(this, newLeftBound, newRightBound, deep + 1, proc->tree_left, proc->tree_right, index, treeIndex, nextIndent); - - int newRight = (*treeIndex)++; - - proc->tree_left = newLeft; - proc->tree_right = newRight; - proc->tree_index = idx; - proc->tree_depth = deep; - - if (indent == -1) { - proc->indent = 0; - } else if (i == size - 1) { - proc->indent = -currentIndent; - } else { - proc->indent = currentIndent; - } - - Hashtable_put(this->draftingTreeSet, proc->tree_index, proc); - - // It's not strictly necessary to do this, but doing so anyways - // allows for checking the correctness of the inner workings. - Hashtable_remove(this->displayTreeSet, newLeftBound); - } - - Vector_delete(layer); -} - -static void ProcessList_updateTreeSet(ProcessList* this) { - unsigned int index = 0; - unsigned int tree_index = 1; - - const int vsize = Vector_size(this->processes); - - assert(Hashtable_count(this->draftingTreeSet) == 0); - assert((int)Hashtable_count(this->displayTreeSet) == vsize); - - ProcessList_updateTreeSetLayer(this, 0, vsize, 0, 0, vsize * 2 + 1, &index, &tree_index, -1); - - Hashtable* tmp = this->draftingTreeSet; - this->draftingTreeSet = this->displayTreeSet; - this->displayTreeSet = tmp; - - assert(Hashtable_count(this->draftingTreeSet) == 0); - assert((int)Hashtable_count(this->displayTreeSet) == vsize); -} - -static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level, int indent, int direction, bool show, int* node_counter, int* node_index) { - // On OpenBSD the kernel thread 'swapper' has pid 0. - // Do not treat it as root of any tree. - if (pid == 0) - return; - - Vector* children = Vector_new(Class(Process), false, DEFAULT_SIZE); - - for (int i = Vector_size(this->processes) - 1; i >= 0; i--) { - Process* process = (Process*)Vector_get(this->processes, i); - if (process->show && Process_isChildOf(process, pid)) { - process = (Process*)Vector_take(this->processes, i); - Vector_add(children, process); - } - } - - int size = Vector_size(children); - for (int i = 0; i < size; i++) { - int index = (*node_index)++; - Process* process = (Process*)Vector_get(children, i); - - int lft = (*node_counter)++; - - if (!show) { - process->show = false; - } - - int s = Vector_size(this->processes2); - if (direction == 1) { - Vector_add(this->processes2, process); - } else { - Vector_insert(this->processes2, 0, process); - } - - assert(Vector_size(this->processes2) == s + 1); (void)s; - - int nextIndent = indent | (1 << level); - ProcessList_buildTreeBranch(this, process->pid, level + 1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false, node_counter, node_index); - if (i == size - 1) { - process->indent = -nextIndent; - } else { - process->indent = nextIndent; - } - - int rht = (*node_counter)++; - - process->tree_left = lft; - process->tree_right = rht; - process->tree_depth = level + 1; - process->tree_index = index; - Hashtable_put(this->displayTreeSet, index, process); - } - Vector_delete(children); -} - -static int ProcessList_treeProcessCompare(const void* v1, const void* v2) { - const Process *p1 = (const Process*)v1; - const Process *p2 = (const Process*)v2; - - return SPACESHIP_NUMBER(p1->tree_left, p2->tree_left); -} - -static int ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) { - const Process *p1 = (const Process*)v1; - const Process *p2 = (const Process*)v2; - - return SPACESHIP_NUMBER(p1->pid, p2->pid); -} - -// Builds a sorted tree from scratch, without relying on previously gathered information -static void ProcessList_buildTree(ProcessList* this) { - int node_counter = 1; - int node_index = 0; - int direction = Settings_getActiveDirection(this->settings); - - // Sort by PID - Vector_quickSortCustomCompare(this->processes, ProcessList_treeProcessCompareByPID); - int vsize = Vector_size(this->processes); - - // Find all processes whose parent is not visible - int size; - while ((size = Vector_size(this->processes))) { - int i; - for (i = 0; i < size; i++) { - Process* process = (Process*)Vector_get(this->processes, i); - - // Immediately consume processes hidden from view - if (!process->show) { - process = (Process*)Vector_take(this->processes, i); - process->indent = 0; - process->tree_depth = 0; - process->tree_left = node_counter++; - process->tree_index = node_index++; - Vector_add(this->processes2, process); - ProcessList_buildTreeBranch(this, process->pid, 0, 0, direction, false, &node_counter, &node_index); - process->tree_right = node_counter++; - Hashtable_put(this->displayTreeSet, process->tree_index, process); - break; - } - - pid_t ppid = Process_getParentPid(process); - - // Bisect the process vector to find parent - int l = 0; - int r = size; - - // If PID corresponds with PPID (e.g. "kernel_task" (PID:0, PPID:0) - // on Mac OS X 10.11.6) cancel bisecting and regard this process as - // root. - if (process->pid == ppid) - r = 0; - - // On Linux both the init process (pid 1) and the root UMH kernel thread (pid 2) - // use a ppid of 0. As that PID can't exist, we can skip searching for it. - if (!ppid) - r = 0; - - while (l < r) { - int c = (l + r) / 2; - pid_t pid = ((Process*)Vector_get(this->processes, c))->pid; - if (ppid == pid) { - break; - } else if (ppid < pid) { - r = c; - } else { - l = c + 1; - } - } - - // If parent not found, then construct the tree with this node as root - if (l >= r) { - process = (Process*)Vector_take(this->processes, i); - process->indent = 0; - process->tree_depth = 0; - process->tree_left = node_counter++; - process->tree_index = node_index++; - Vector_add(this->processes2, process); - Hashtable_put(this->displayTreeSet, process->tree_index, process); - ProcessList_buildTreeBranch(this, process->pid, 0, 0, direction, process->showChildren, &node_counter, &node_index); - process->tree_right = node_counter++; - break; - } - } - - // There should be no loop in the process tree - assert(i < size); - } - - // Swap listings around - Vector* t = this->processes; - this->processes = this->processes2; - this->processes2 = t; - - // Check consistency of the built structures - assert(Vector_size(this->processes) == vsize); (void)vsize; - assert(Vector_size(this->processes2) == 0); -} - -void ProcessList_sort(ProcessList* this) { - if (this->settings->treeView) { - ProcessList_updateTreeSet(this); - Vector_quickSortCustomCompare(this->processes, ProcessList_treeProcessCompare); - } else { - Vector_insertionSort(this->processes); - } -} - -ProcessField ProcessList_keyAt(const ProcessList* this, int at) { - int x = 0; - const ProcessField* fields = this->settings->fields; - ProcessField field; - for (int i = 0; (field = fields[i]); i++) { - int len = strlen(alignedProcessFieldTitle(field)); - if (at >= x && at <= x + len) { - return field; - } - x += len; - } - return COMM; -} - -void ProcessList_expandTree(ProcessList* this) { - int size = Vector_size(this->processes); - for (int i = 0; i < size; i++) { - Process* process = (Process*) Vector_get(this->processes, i); - process->showChildren = true; - } -} - -void ProcessList_collapseAllBranches(ProcessList* this) { - int size = Vector_size(this->processes); - for (int i = 0; i < size; i++) { - Process* process = (Process*) Vector_get(this->processes, i); - // FreeBSD has pid 0 = kernel and pid 1 = init, so init has tree_depth = 1 - if (process->tree_depth > 0 && process->pid > 1) - process->showChildren = false; - } -} - -void ProcessList_rebuildPanel(ProcessList* this) { - const char* incFilter = this->incFilter; - - const int currPos = Panel_getSelectedIndex(this->panel); - const int currScrollV = this->panel->scrollV; - const int currSize = Panel_size(this->panel); - - Panel_prune(this->panel); - - /* Follow main process if followed a userland thread and threads are now hidden */ - const Settings* settings = this->settings; - if (this->following != -1 && settings->hideUserlandThreads) { - const Process* followedProcess = (const Process*) Hashtable_get(this->processTable, this->following); - if (followedProcess && Process_isThread(followedProcess) && Hashtable_get(this->processTable, followedProcess->tgid) != NULL) { - this->following = followedProcess->tgid; - } - } - - const int processCount = ProcessList_size(this); - int idx = 0; - bool foundFollowed = false; - - for (int i = 0; i < processCount; i++) { - Process* p = ProcessList_get(this, i); - - if ( (!p->show) - || (this->userId != (uid_t) -1 && (p->st_uid != this->userId)) - || (incFilter && !(String_contains_i(Process_getCommand(p), incFilter))) - || (this->pidMatchList && !Hashtable_get(this->pidMatchList, p->tgid)) ) - continue; - - Panel_set(this->panel, idx, (Object*)p); - - if (this->following != -1 && p->pid == this->following) { - foundFollowed = true; - Panel_setSelected(this->panel, idx); - this->panel->scrollV = currScrollV; - } - idx++; - } - - if (this->following != -1 && !foundFollowed) { - /* Reset if current followed pid not found */ - this->following = -1; - Panel_setSelectionColor(this->panel, PANEL_SELECTION_FOCUS); - } - - if (this->following == -1) { - /* If the last item was selected, keep the new last item selected */ - if (currPos > 0 && currPos == currSize - 1) - Panel_setSelected(this->panel, Panel_size(this->panel) - 1); - else - Panel_setSelected(this->panel, currPos); - - this->panel->scrollV = currScrollV; - } -} - -Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_New constructor) { - Process* proc = (Process*) Hashtable_get(this->processTable, pid); - *preExisting = proc; - if (proc) { - assert(Vector_indexOf(this->processes, proc, Process_pidCompare) != -1); - assert(proc->pid == pid); - } else { - proc = constructor(this->settings); - assert(proc->comm == NULL); - proc->pid = pid; - } - return proc; -} - -void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) { - // in pause mode only gather global data for meters (CPU/memory/...) - if (pauseProcessUpdate) { - ProcessList_goThroughEntries(this, true); - return; - } - - // mark all process as "dirty" - for (int i = 0; i < Vector_size(this->processes); i++) { - Process* p = (Process*) Vector_get(this->processes, i); - p->updated = false; - p->wasShown = p->show; - p->show = true; - } - - this->totalTasks = 0; - this->userlandThreads = 0; - this->kernelThreads = 0; - this->runningTasks = 0; - - - // set scan timestamp - static bool firstScanDone = false; - if (firstScanDone) { - Platform_gettime_monotonic(&this->monotonicMs); - } else { - this->monotonicMs = 0; - firstScanDone = true; - } - - ProcessList_goThroughEntries(this, false); - - for (int i = Vector_size(this->processes) - 1; i >= 0; i--) { - Process* p = (Process*) Vector_get(this->processes, i); - if (p->tombStampMs > 0) { - // remove tombed process - if (this->monotonicMs >= p->tombStampMs) { - ProcessList_remove(this, p); - } - } else if (p->updated == false) { - // process no longer exists - if (this->settings->highlightChanges && p->wasShown) { - // mark tombed - p->tombStampMs = this->monotonicMs + 1000 * this->settings->highlightDelaySecs; - } else { - // immediately remove - ProcessList_remove(this, p); - } - } else { - p->updated = false; - } - } - - if (this->settings->treeView) { - // Clear out the hashtable to avoid any left-over processes from previous build - // - // The sorting algorithm relies on the fact that - // len(this->displayTreeSet) == len(this->processes) - Hashtable_clear(this->displayTreeSet); - - ProcessList_buildTree(this); - } -} diff -Nru pcp-5.3.1/src/pcp/htop/ProcessList.h pcp-5.3.2/src/pcp/htop/ProcessList.h --- pcp-5.3.1/src/pcp/htop/ProcessList.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ProcessList.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,124 +0,0 @@ -#ifndef HEADER_ProcessList -#define HEADER_ProcessList -/* -htop - ProcessList.h -(C) 2004,2005 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include - -#include "Hashtable.h" -#include "Object.h" -#include "Panel.h" -#include "Process.h" -#include "RichString.h" -#include "Settings.h" -#include "UsersTable.h" -#include "Vector.h" - -#ifdef HAVE_LIBHWLOC -#include -#endif - - -#ifndef MAX_NAME -#define MAX_NAME 128 -#endif - -#ifndef MAX_READ -#define MAX_READ 2048 -#endif - -typedef unsigned long long int memory_t; -#define MEMORY_MAX ULLONG_MAX - -typedef struct ProcessList_ { - const Settings* settings; - - Vector* processes; - Vector* processes2; - Hashtable* processTable; - UsersTable* usersTable; - - Hashtable* displayTreeSet; - Hashtable* draftingTreeSet; - - struct timeval realtime; /* time of the current sample */ - uint64_t realtimeMs; /* current time in milliseconds */ - uint64_t monotonicMs; /* same, but from monotonic clock */ - - Panel* panel; - int following; - uid_t userId; - const char* incFilter; - Hashtable* pidMatchList; - - #ifdef HAVE_LIBHWLOC - hwloc_topology_t topology; - bool topologyOk; - #endif - - unsigned int totalTasks; - unsigned int runningTasks; - unsigned int userlandThreads; - unsigned int kernelThreads; - - memory_t totalMem; - memory_t usedMem; - memory_t buffersMem; - memory_t cachedMem; - memory_t sharedMem; - memory_t availableMem; - - memory_t totalSwap; - memory_t usedSwap; - memory_t cachedSwap; - - unsigned int cpuCount; -} ProcessList; - -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); -void ProcessList_delete(ProcessList* pl); -void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); - - -ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); - -void ProcessList_done(ProcessList* this); - -void ProcessList_setPanel(ProcessList* this, Panel* panel); - -void ProcessList_printHeader(const ProcessList* this, RichString* header); - -void ProcessList_add(ProcessList* this, Process* p); - -void ProcessList_remove(ProcessList* this, const Process* p); - -Process* ProcessList_get(ProcessList* this, int idx); - -int ProcessList_size(const ProcessList* this); - -void ProcessList_sort(ProcessList* this); - -ProcessField ProcessList_keyAt(const ProcessList* this, int at); - -void ProcessList_expandTree(ProcessList* this); - -void ProcessList_collapseAllBranches(ProcessList* this); - -void ProcessList_rebuildPanel(ProcessList* this); - -Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_New constructor); - -void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate); - -static inline Process* ProcessList_findProcess(ProcessList* this, pid_t pid) { - return (Process*) Hashtable_get(this->processTable, pid); -} - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ProcessLocksScreen.c pcp-5.3.2/src/pcp/htop/ProcessLocksScreen.c --- pcp-5.3.1/src/pcp/htop/ProcessLocksScreen.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ProcessLocksScreen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -/* -htop - ProcessLocksScreen.c -(C) 2020 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "ProcessLocksScreen.h" - -#include -#include -#include - -#include "Panel.h" -#include "Platform.h" -#include "ProvideCurses.h" -#include "Vector.h" -#include "XUtils.h" - - -ProcessLocksScreen* ProcessLocksScreen_new(const Process* process) { - ProcessLocksScreen* this = xMalloc(sizeof(ProcessLocksScreen)); - Object_setClass(this, Class(ProcessLocksScreen)); - if (Process_isThread(process)) - this->pid = process->tgid; - else - this->pid = process->pid; - return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME"); -} - -void ProcessLocksScreen_delete(Object* this) { - free(InfoScreen_done((InfoScreen*)this)); -} - -static void ProcessLocksScreen_draw(InfoScreen* this) { - InfoScreen_drawTitled(this, "Snapshot of file locks of process %d - %s", ((ProcessLocksScreen*)this)->pid, Process_getCommand(this->process)); -} - -static inline void FileLocks_Data_clear(FileLocks_Data* data) { - free(data->locktype); - free(data->exclusive); - free(data->readwrite); - free(data->filename); -} - -static void ProcessLocksScreen_scan(InfoScreen* this) { - Panel* panel = this->display; - int idx = Panel_getSelectedIndex(panel); - Panel_prune(panel); - FileLocks_ProcessData* pdata = Platform_getProcessLocks(((ProcessLocksScreen*)this)->pid); - if (!pdata) { - InfoScreen_addLine(this, "This feature is not supported on your platform."); - } else if (pdata->error) { - InfoScreen_addLine(this, "Could not determine file locks."); - } else { - FileLocks_LockData* ldata = pdata->locks; - if (!ldata) { - InfoScreen_addLine(this, "No locks have been found for the selected process."); - } - while (ldata) { - FileLocks_Data* data = &ldata->data; - - char entry[512]; - if (ULLONG_MAX == data->end) { - xSnprintf(entry, sizeof(entry), "%10d %-10s %-10s %-10s %02x:%02x:%020"PRIu64" %20"PRIu64" %20s %s", - data->id, - data->locktype, data->exclusive, data->readwrite, - data->dev[0], data->dev[1], data->inode, - data->start, "", - data->filename ? data->filename : "" - ); - } else { - xSnprintf(entry, sizeof(entry), "%10d %-10s %-10s %-10s %02x:%02x:%020"PRIu64" %20"PRIu64" %20"PRIu64" %s", - data->id, - data->locktype, data->exclusive, data->readwrite, - data->dev[0], data->dev[1], data->inode, - data->start, data->end, - data->filename ? data->filename : "" - ); - } - - InfoScreen_addLine(this, entry); - FileLocks_Data_clear(&ldata->data); - - FileLocks_LockData* old = ldata; - ldata = ldata->next; - free(old); - } - } - free(pdata); - Vector_insertionSort(this->lines); - Vector_insertionSort(panel->items); - Panel_setSelected(panel, idx); -} - -const InfoScreenClass ProcessLocksScreen_class = { - .super = { - .extends = Class(Object), - .delete = ProcessLocksScreen_delete - }, - .scan = ProcessLocksScreen_scan, - .draw = ProcessLocksScreen_draw -}; diff -Nru pcp-5.3.1/src/pcp/htop/ProcessLocksScreen.h pcp-5.3.2/src/pcp/htop/ProcessLocksScreen.h --- pcp-5.3.1/src/pcp/htop/ProcessLocksScreen.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ProcessLocksScreen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -#ifndef HEADER_ProcessLocksScreen -#define HEADER_ProcessLocksScreen -/* -htop - ProcessLocksScreen.h -(C) 2020 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include -#include -#include - -#include "InfoScreen.h" -#include "Object.h" -#include "Process.h" - - -typedef struct ProcessLocksScreen_ { - InfoScreen super; - pid_t pid; -} ProcessLocksScreen; - -typedef struct FileLocks_Data_ { - char* locktype; - char* exclusive; - char* readwrite; - char* filename; - int id; - unsigned int dev[2]; - uint64_t inode; - uint64_t start; - uint64_t end; -} FileLocks_Data; - -typedef struct FileLocks_LockData_ { - FileLocks_Data data; - struct FileLocks_LockData_* next; -} FileLocks_LockData; - -typedef struct FileLocks_ProcessData_ { - bool error; - struct FileLocks_LockData_* locks; -} FileLocks_ProcessData; - -extern const InfoScreenClass ProcessLocksScreen_class; - -ProcessLocksScreen* ProcessLocksScreen_new(const Process* process); - -void ProcessLocksScreen_delete(Object* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ProvideCurses.h pcp-5.3.2/src/pcp/htop/ProvideCurses.h --- pcp-5.3.1/src/pcp/htop/ProvideCurses.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ProvideCurses.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -#ifndef HEADER_ProvideCurses -#define HEADER_ProvideCurses -/* -htop - RichString.h -(C) 2004,2011 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - - -#include "config.h" - -// IWYU pragma: begin_exports - -#if defined(HAVE_NCURSESW_CURSES_H) -#include -#elif defined(HAVE_NCURSES_NCURSES_H) -#include -#elif defined(HAVE_NCURSES_CURSES_H) -#include -#elif defined(HAVE_NCURSES_H) -#include -#elif defined(HAVE_CURSES_H) -#include -#endif - -#ifdef HAVE_LIBNCURSESW -#include -#include -#endif - -// IWYU pragma: end_exports - -#endif // HEADER_ProvideCurses diff -Nru pcp-5.3.1/src/pcp/htop/RichString.c pcp-5.3.2/src/pcp/htop/RichString.c --- pcp-5.3.1/src/pcp/htop/RichString.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/RichString.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -/* -htop - RichString.c -(C) 2004,2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "RichString.h" - -#include -#include -#include - -#include "Macros.h" -#include "XUtils.h" - - -#define charBytes(n) (sizeof(CharType) * (n)) - -static void RichString_extendLen(RichString* this, int len) { - if (this->chlen <= RICHSTRING_MAXLEN) { - if (len > RICHSTRING_MAXLEN) { - this->chptr = xMalloc(charBytes(len + 1)); - memcpy(this->chptr, this->chstr, charBytes(this->chlen)); - } - } else { - if (len <= RICHSTRING_MAXLEN) { - memcpy(this->chstr, this->chptr, charBytes(len)); - free(this->chptr); - this->chptr = this->chstr; - } else { - this->chptr = xRealloc(this->chptr, charBytes(len + 1)); - } - } - - RichString_setChar(this, len, 0); - this->chlen = len; -} - -static void RichString_setLen(RichString* this, int len) { - if (len < RICHSTRING_MAXLEN && this->chlen < RICHSTRING_MAXLEN) { - RichString_setChar(this, len, 0); - this->chlen = len; - } else { - RichString_extendLen(this, len); - } -} - -void RichString_rewind(RichString* this, int count) { - RichString_setLen(this, this->chlen - count); -} - -#ifdef HAVE_LIBNCURSESW - -static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) { - wchar_t data[len + 1]; - len = mbstowcs(data, data_c, len); - if (len <= 0) - return 0; - - int newLen = from + len; - RichString_setLen(this, newLen); - for (int i = from, j = 0; i < newLen; i++, j++) { - this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (iswprint(data[j]) ? data[j] : '?') } }; - } - - return len; -} - -int RichString_appendnWideColumns(RichString* this, int attrs, const char* data_c, int len, int* columns) { - wchar_t data[len + 1]; - len = mbstowcs(data, data_c, len); - if (len <= 0) - return 0; - - int from = this->chlen; - int newLen = from + len; - RichString_setLen(this, newLen); - int columnsWritten = 0; - int pos = from; - for (int j = 0; j < len; j++) { - wchar_t c = iswprint(data[j]) ? data[j] : '?'; - int cwidth = wcwidth(c); - if (cwidth > *columns) - break; - - *columns -= cwidth; - columnsWritten += cwidth; - - this->chptr[pos] = (CharType) { .attr = attrs & 0xffffff, .chars = { c, '\0' } }; - pos++; - } - - RichString_setLen(this, pos); - *columns = columnsWritten; - - return pos - from; -} - -static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data, int from, int len) { - int newLen = from + len; - RichString_setLen(this, newLen); - for (int i = from, j = 0; i < newLen; i++, j++) { - this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (isprint(data[j]) ? data[j] : '?') } }; - } - - return len; -} - -inline void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) { - int end = CLAMP(start + charcount, 0, this->chlen); - for (int i = start; i < end; i++) { - this->chptr[i].attr = attrs; - } -} - -void RichString_appendChr(RichString* this, int attrs, char c, int count) { - int from = this->chlen; - int newLen = from + count; - RichString_setLen(this, newLen); - for (int i = from; i < newLen; i++) { - this->chptr[i] = (CharType) { .attr = attrs, .chars = { c, 0 } }; - } -} - -int RichString_findChar(const RichString* this, char c, int start) { - const wchar_t wc = btowc(c); - const cchar_t* ch = this->chptr + start; - for (int i = start; i < this->chlen; i++) { - if (ch->chars[0] == wc) - return i; - ch++; - } - return -1; -} - -#else /* HAVE_LIBNCURSESW */ - -static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) { - int newLen = from + len; - RichString_setLen(this, newLen); - for (int i = from, j = 0; i < newLen; i++, j++) { - this->chptr[i] = (((unsigned char)data_c[j]) >= 32 ? ((unsigned char)data_c[j]) : '?') | attrs; - } - this->chptr[newLen] = 0; - - return len; -} - -int RichString_appendnWideColumns(RichString* this, int attrs, const char* data_c, int len, int* columns) { - int written = RichString_writeFromWide(this, attrs, data_c, this->chlen, MINIMUM(len, *columns)); - *columns = written; - return written; -} - -static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data_c, int from, int len) { - return RichString_writeFromWide(this, attrs, data_c, from, len); -} - -void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) { - int end = CLAMP(start + charcount, 0, this->chlen); - for (int i = start; i < end; i++) { - this->chptr[i] = (this->chptr[i] & 0xff) | attrs; - } -} - -void RichString_appendChr(RichString* this, int attrs, char c, int count) { - int from = this->chlen; - int newLen = from + count; - RichString_setLen(this, newLen); - for (int i = from; i < newLen; i++) { - this->chptr[i] = c | attrs; - } -} - -int RichString_findChar(const RichString* this, char c, int start) { - const chtype* ch = this->chptr + start; - for (int i = start; i < this->chlen; i++) { - if ((*ch & 0xff) == (chtype) c) - return i; - ch++; - } - return -1; -} - -#endif /* HAVE_LIBNCURSESW */ - -void RichString_delete(RichString* this) { - if (this->chlen > RICHSTRING_MAXLEN) { - free(this->chptr); - this->chptr = this->chstr; - } -} - -void RichString_setAttr(RichString* this, int attrs) { - RichString_setAttrn(this, attrs, 0, this->chlen); -} - -int RichString_appendWide(RichString* this, int attrs, const char* data) { - return RichString_writeFromWide(this, attrs, data, this->chlen, strlen(data)); -} - -int RichString_appendnWide(RichString* this, int attrs, const char* data, int len) { - return RichString_writeFromWide(this, attrs, data, this->chlen, len); -} - -int RichString_writeWide(RichString* this, int attrs, const char* data) { - return RichString_writeFromWide(this, attrs, data, 0, strlen(data)); -} - -int RichString_appendAscii(RichString* this, int attrs, const char* data) { - return RichString_writeFromAscii(this, attrs, data, this->chlen, strlen(data)); -} - -int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len) { - return RichString_writeFromAscii(this, attrs, data, this->chlen, len); -} - -int RichString_writeAscii(RichString* this, int attrs, const char* data) { - return RichString_writeFromAscii(this, attrs, data, 0, strlen(data)); -} diff -Nru pcp-5.3.1/src/pcp/htop/RichString.h pcp-5.3.2/src/pcp/htop/RichString.h --- pcp-5.3.1/src/pcp/htop/RichString.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/RichString.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -#ifndef HEADER_RichString -#define HEADER_RichString -/* -htop - RichString.h -(C) 2004,2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" - -#include "ProvideCurses.h" - - -#define RichString_size(this) ((this)->chlen) -#define RichString_sizeVal(this) ((this).chlen) - -#define RichString_begin(this) RichString (this); RichString_beginAllocated(this) -#define RichString_beginAllocated(this) \ - do { \ - (this).chlen = 0, \ - (this).chptr = (this).chstr; \ - RichString_setChar(&this, 0, 0); \ - (this).highlightAttr = 0; \ - } while(0) - -#ifdef HAVE_LIBNCURSESW -#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr) -#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + (off), n) -#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0]) -#define RichString_setChar(this, at, ch) do { (this)->chptr[(at)] = (CharType) { .chars = { ch, 0 } }; } while (0) -#define CharType cchar_t -#else -#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr) -#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + (off), n) -#define RichString_getCharVal(this, i) ((this).chptr[i] & 0xff) -#define RichString_setChar(this, at, ch) do { (this)->chptr[(at)] = ch; } while (0) -#define CharType chtype -#endif - -#define RICHSTRING_MAXLEN 350 - -typedef struct RichString_ { - int chlen; - CharType* chptr; - CharType chstr[RICHSTRING_MAXLEN + 1]; - int highlightAttr; -} RichString; - -void RichString_delete(RichString* this); - -void RichString_rewind(RichString* this, int count); - -void RichString_setAttrn(RichString* this, int attrs, int start, int charcount); - -int RichString_findChar(const RichString* this, char c, int start); - -void RichString_setAttr(RichString* this, int attrs); - -void RichString_appendChr(RichString* this, int attrs, char c, int count); - -/* All appending and writing functions return the number of written characters (not columns). */ - -int RichString_appendWide(RichString* this, int attrs, const char* data); - -int RichString_appendnWide(RichString* this, int attrs, const char* data, int len); - -/* columns takes the maximum number of columns to write and contains on return the number of columns written. */ -int RichString_appendnWideColumns(RichString* this, int attrs, const char* data, int len, int* columns); - -int RichString_writeWide(RichString* this, int attrs, const char* data); - -int RichString_appendAscii(RichString* this, int attrs, const char* data); - -int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len); - -int RichString_writeAscii(RichString* this, int attrs, const char* data); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/ScreenManager.c pcp-5.3.2/src/pcp/htop/ScreenManager.c --- pcp-5.3.1/src/pcp/htop/ScreenManager.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ScreenManager.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,323 +0,0 @@ -/* -htop - ScreenManager.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ScreenManager.h" - -#include -#include -#include -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "Object.h" -#include "Platform.h" -#include "ProcessList.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -ScreenManager* ScreenManager_new(Header* header, const Settings* settings, const State* state, bool owner) { - ScreenManager* this; - this = xMalloc(sizeof(ScreenManager)); - this->x1 = 0; - this->y1 = header->height; - this->x2 = 0; - this->y2 = -1; - this->panels = Vector_new(Class(Panel), owner, DEFAULT_SIZE); - this->panelCount = 0; - this->header = header; - this->settings = settings; - this->state = state; - this->owner = owner; - this->allowFocusChange = true; - return this; -} - -void ScreenManager_delete(ScreenManager* this) { - Vector_delete(this->panels); - free(this); -} - -inline int ScreenManager_size(const ScreenManager* this) { - return this->panelCount; -} - -void ScreenManager_add(ScreenManager* this, Panel* item, int size) { - int lastX = 0; - if (this->panelCount > 0) { - const Panel* last = (const Panel*) Vector_get(this->panels, this->panelCount - 1); - lastX = last->x + last->w + 1; - } - int height = LINES - this->y1 + this->y2; - if (size > 0) { - Panel_resize(item, size, height); - } else { - Panel_resize(item, COLS - this->x1 + this->x2 - lastX, height); - } - Panel_move(item, lastX, this->y1); - Vector_add(this->panels, item); - item->needsRedraw = true; - this->panelCount++; -} - -Panel* ScreenManager_remove(ScreenManager* this, int idx) { - assert(this->panelCount > idx); - Panel* panel = (Panel*) Vector_remove(this->panels, idx); - this->panelCount--; - return panel; -} - -void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) { - this->x1 = x1; - this->y1 = y1; - this->x2 = x2; - this->y2 = y2; - int panels = this->panelCount; - int lastX = 0; - for (int i = 0; i < panels - 1; i++) { - Panel* panel = (Panel*) Vector_get(this->panels, i); - Panel_resize(panel, panel->w, LINES - y1 + y2); - Panel_move(panel, lastX, y1); - lastX = panel->x + panel->w + 1; - } - Panel* panel = (Panel*) Vector_get(this->panels, panels - 1); - Panel_resize(panel, COLS - x1 + x2 - lastX, LINES - y1 + y2); - Panel_move(panel, lastX, y1); -} - -static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool* rescan, bool* timedOut) { - ProcessList* pl = this->header->pl; - - Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs); - double newTime = ((double)pl->realtime.tv_sec * 10) + ((double)pl->realtime.tv_usec / 100000); - - *timedOut = (newTime - *oldTime > this->settings->delay); - *rescan |= *timedOut; - - if (newTime < *oldTime) { - *rescan = true; // clock was adjusted? - } - - if (*rescan) { - *oldTime = newTime; - // scan processes first - some header values are calculated there - ProcessList_scan(pl, this->state->pauseProcessUpdate); - // always update header, especially to avoid gaps in graph meters - Header_updateData(this->header); - if (!this->state->pauseProcessUpdate && (*sortTimeout == 0 || this->settings->treeView)) { - ProcessList_sort(pl); - *sortTimeout = 1; - } - *redraw = true; - } - if (*redraw) { - ProcessList_rebuildPanel(pl); - Header_draw(this->header); - } - *rescan = false; -} - -static void ScreenManager_drawPanels(ScreenManager* this, int focus, bool force_redraw) { - const int nPanels = this->panelCount; - for (int i = 0; i < nPanels; i++) { - Panel* panel = (Panel*) Vector_get(this->panels, i); - Panel_draw(panel, - force_redraw, - i == focus, - panel != (Panel*)this->state->mainPanel || !this->state->hideProcessSelection, - State_hideFunctionBar(this->state)); - mvvline(panel->y, panel->x + panel->w, ' ', panel->h + (State_hideFunctionBar(this->state) ? 1 : 0)); - } -} - -void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) { - bool quit = false; - int focus = 0; - - Panel* panelFocus = (Panel*) Vector_get(this->panels, focus); - - double oldTime = 0.0; - - int ch = ERR; - int closeTimeout = 0; - - bool timedOut = true; - bool redraw = true; - bool force_redraw = true; - bool rescan = false; - int sortTimeout = 0; - int resetSortTimeout = 5; - - while (!quit) { - if (this->header) { - checkRecalculation(this, &oldTime, &sortTimeout, &redraw, &rescan, &timedOut); - } - - if (redraw || force_redraw) { - ScreenManager_drawPanels(this, focus, force_redraw); - force_redraw = false; - } - - int prevCh = ch; - set_escdelay(25); - ch = getch(); - - HandlerResult result = IGNORED; - if (ch == KEY_MOUSE && this->settings->enableMouse) { - ch = ERR; - MEVENT mevent; - int ok = getmouse(&mevent); - if (ok == OK) { - if (mevent.bstate & BUTTON1_RELEASED) { - if (mevent.y == LINES - 1) { - ch = FunctionBar_synthesizeEvent(panelFocus->currentBar, mevent.x); - } else { - for (int i = 0; i < this->panelCount; i++) { - Panel* panel = (Panel*) Vector_get(this->panels, i); - if (mevent.x >= panel->x && mevent.x <= panel->x + panel->w) { - if (mevent.y == panel->y) { - ch = EVENT_HEADER_CLICK(mevent.x - panel->x); - break; - } else if (mevent.y > panel->y && mevent.y <= panel->y + panel->h) { - ch = KEY_MOUSE; - if (panel == panelFocus || this->allowFocusChange) { - focus = i; - panelFocus = panel; - const Object* oldSelection = Panel_getSelected(panel); - Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1); - if (Panel_getSelected(panel) == oldSelection) { - ch = KEY_RECLICK; - } - } - break; - } - } - } - } - #if NCURSES_MOUSE_VERSION > 1 - } else if (mevent.bstate & BUTTON4_PRESSED) { - ch = KEY_WHEELUP; - } else if (mevent.bstate & BUTTON5_PRESSED) { - ch = KEY_WHEELDOWN; - #endif - } - } - } - if (ch == ERR) { - if (sortTimeout > 0) - sortTimeout--; - if (prevCh == ch && !timedOut) { - closeTimeout++; - if (closeTimeout == 100) { - break; - } - } else { - closeTimeout = 0; - } - redraw = false; - continue; - } - switch (ch) { - case KEY_ALT('H'): ch = KEY_LEFT; break; - case KEY_ALT('J'): ch = KEY_DOWN; break; - case KEY_ALT('K'): ch = KEY_UP; break; - case KEY_ALT('L'): ch = KEY_RIGHT; break; - } - redraw = true; - if (Panel_eventHandlerFn(panelFocus)) { - result = Panel_eventHandler(panelFocus, ch); - } - if (result & SYNTH_KEY) { - ch = result >> 16; - } - if (result & REFRESH) { - sortTimeout = 0; - } - if (result & REDRAW) { - force_redraw = true; - } - if (result & RESCAN) { - rescan = true; - sortTimeout = 0; - } - if (result & HANDLED) { - continue; - } else if (result & BREAK_LOOP) { - quit = true; - continue; - } - - switch (ch) { - case KEY_RESIZE: - { - ScreenManager_resize(this, this->x1, this->y1, this->x2, this->y2); - continue; - } - case KEY_LEFT: - case KEY_CTRL('B'): - if (this->panelCount < 2) { - goto defaultHandler; - } - - if (!this->allowFocusChange) { - break; - } - -tryLeft: - if (focus > 0) { - focus--; - } - - panelFocus = (Panel*) Vector_get(this->panels, focus); - if (Panel_size(panelFocus) == 0 && focus > 0) { - goto tryLeft; - } - - break; - case KEY_RIGHT: - case KEY_CTRL('F'): - case 9: - if (this->panelCount < 2) { - goto defaultHandler; - } - if (!this->allowFocusChange) { - break; - } - -tryRight: - if (focus < this->panelCount - 1) { - focus++; - } - - panelFocus = (Panel*) Vector_get(this->panels, focus); - if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1) { - goto tryRight; - } - - break; - case 27: - case 'q': - case KEY_F(10): - quit = true; - continue; - default: -defaultHandler: - sortTimeout = resetSortTimeout; - Panel_onKey(panelFocus, ch); - break; - } - } - - if (lastFocus) { - *lastFocus = panelFocus; - } - - if (lastKey) { - *lastKey = ch; - } -} diff -Nru pcp-5.3.1/src/pcp/htop/ScreenManager.h pcp-5.3.2/src/pcp/htop/ScreenManager.h --- pcp-5.3.1/src/pcp/htop/ScreenManager.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/ScreenManager.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -#ifndef HEADER_ScreenManager -#define HEADER_ScreenManager -/* -htop - ScreenManager.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include - -#include "Action.h" -#include "Header.h" -#include "Panel.h" -#include "Settings.h" -#include "Vector.h" - - -typedef struct ScreenManager_ { - int x1; - int y1; - int x2; - int y2; - Vector* panels; - int panelCount; - Header* header; - const Settings* settings; - const State* state; - bool owner; - bool allowFocusChange; -} ScreenManager; - -ScreenManager* ScreenManager_new(Header* header, const Settings* settings, const State* state, bool owner); - -void ScreenManager_delete(ScreenManager* this); - -int ScreenManager_size(const ScreenManager* this); - -void ScreenManager_add(ScreenManager* this, Panel* item, int size); - -Panel* ScreenManager_remove(ScreenManager* this, int idx); - -void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2); - -void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Settings.c pcp-5.3.2/src/pcp/htop/Settings.c --- pcp-5.3.1/src/pcp/htop/Settings.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Settings.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,474 +0,0 @@ -/* -htop - Settings.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Settings.h" - -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "Macros.h" -#include "Meter.h" -#include "Platform.h" -#include "XUtils.h" - - -void Settings_delete(Settings* this) { - free(this->filename); - free(this->fields); - for (unsigned int i = 0; i < ARRAYSIZE(this->columns); i++) { - String_freeArray(this->columns[i].names); - free(this->columns[i].modes); - } - free(this); -} - -static void Settings_readMeters(Settings* this, const char* line, int column) { - char* trim = String_trim(line); - char** ids = String_split(trim, ' ', NULL); - free(trim); - this->columns[column].names = ids; -} - -static void Settings_readMeterModes(Settings* this, const char* line, int column) { - char* trim = String_trim(line); - char** ids = String_split(trim, ' ', NULL); - free(trim); - int len = 0; - for (int i = 0; ids[i]; i++) { - len++; - } - this->columns[column].len = len; - int* modes = len ? xCalloc(len, sizeof(int)) : NULL; - for (int i = 0; i < len; i++) { - modes[i] = atoi(ids[i]); - } - String_freeArray(ids); - this->columns[column].modes = modes; -} - -static void Settings_defaultMeters(Settings* this, unsigned int initialCpuCount) { - int sizes[] = { 3, 3 }; - if (initialCpuCount > 4 && initialCpuCount <= 128) { - sizes[1]++; - } - for (int i = 0; i < 2; i++) { - this->columns[i].names = xCalloc(sizes[i] + 1, sizeof(char*)); - this->columns[i].modes = xCalloc(sizes[i], sizeof(int)); - this->columns[i].len = sizes[i]; - } - int r = 0; - - if (initialCpuCount > 128) { - // Just show the average, ricers need to config for impressive screenshots - this->columns[0].names[0] = xStrdup("CPU"); - this->columns[0].modes[0] = BAR_METERMODE; - } else if (initialCpuCount > 32) { - this->columns[0].names[0] = xStrdup("LeftCPUs8"); - this->columns[0].modes[0] = BAR_METERMODE; - this->columns[1].names[r] = xStrdup("RightCPUs8"); - this->columns[1].modes[r++] = BAR_METERMODE; - } else if (initialCpuCount > 16) { - this->columns[0].names[0] = xStrdup("LeftCPUs4"); - this->columns[0].modes[0] = BAR_METERMODE; - this->columns[1].names[r] = xStrdup("RightCPUs4"); - this->columns[1].modes[r++] = BAR_METERMODE; - } else if (initialCpuCount > 8) { - this->columns[0].names[0] = xStrdup("LeftCPUs2"); - this->columns[0].modes[0] = BAR_METERMODE; - this->columns[1].names[r] = xStrdup("RightCPUs2"); - this->columns[1].modes[r++] = BAR_METERMODE; - } else if (initialCpuCount > 4) { - this->columns[0].names[0] = xStrdup("LeftCPUs"); - this->columns[0].modes[0] = BAR_METERMODE; - this->columns[1].names[r] = xStrdup("RightCPUs"); - this->columns[1].modes[r++] = BAR_METERMODE; - } else { - this->columns[0].names[0] = xStrdup("AllCPUs"); - this->columns[0].modes[0] = BAR_METERMODE; - } - this->columns[0].names[1] = xStrdup("Memory"); - this->columns[0].modes[1] = BAR_METERMODE; - this->columns[0].names[2] = xStrdup("Swap"); - this->columns[0].modes[2] = BAR_METERMODE; - this->columns[1].names[r] = xStrdup("Tasks"); - this->columns[1].modes[r++] = TEXT_METERMODE; - this->columns[1].names[r] = xStrdup("LoadAverage"); - this->columns[1].modes[r++] = TEXT_METERMODE; - this->columns[1].names[r] = xStrdup("Uptime"); - this->columns[1].modes[r++] = TEXT_METERMODE; -} - -static void readFields(ProcessField* fields, uint32_t* flags, const char* line) { - char* trim = String_trim(line); - char** ids = String_split(trim, ' ', NULL); - free(trim); - int i, j; - *flags = 0; - for (j = 0, i = 0; i < LAST_PROCESSFIELD && ids[i]; i++) { - // This "+1" is for compatibility with the older enum format. - int id = atoi(ids[i]) + 1; - if (id > 0 && id < LAST_PROCESSFIELD && Process_fields[id].name) { - fields[j] = id; - *flags |= Process_fields[id].flags; - j++; - } - } - fields[j] = NULL_PROCESSFIELD; - String_freeArray(ids); -} - -static bool Settings_read(Settings* this, const char* fileName, unsigned int initialCpuCount) { - FILE* fd = fopen(fileName, "r"); - if (!fd) - return false; - - bool didReadMeters = false; - bool didReadFields = false; - for (;;) { - char* line = String_readLine(fd); - if (!line) { - break; - } - size_t nOptions; - char** option = String_split(line, '=', &nOptions); - free (line); - if (nOptions < 2) { - String_freeArray(option); - continue; - } - if (String_eq(option[0], "fields")) { - readFields(this->fields, &(this->flags), option[1]); - didReadFields = true; - } else if (String_eq(option[0], "sort_key")) { - // This "+1" is for compatibility with the older enum format. - this->sortKey = atoi(option[1]) + 1; - } else if (String_eq(option[0], "tree_sort_key")) { - // This "+1" is for compatibility with the older enum format. - this->treeSortKey = atoi(option[1]) + 1; - } else if (String_eq(option[0], "sort_direction")) { - this->direction = atoi(option[1]); - } else if (String_eq(option[0], "tree_sort_direction")) { - this->treeDirection = atoi(option[1]); - } else if (String_eq(option[0], "tree_view")) { - this->treeView = atoi(option[1]); - } else if (String_eq(option[0], "tree_view_always_by_pid")) { - this->treeViewAlwaysByPID = atoi(option[1]); - } else if (String_eq(option[0], "all_branches_collapsed")) { - this->allBranchesCollapsed = atoi(option[1]); - } else if (String_eq(option[0], "hide_kernel_threads")) { - this->hideKernelThreads = atoi(option[1]); - } else if (String_eq(option[0], "hide_userland_threads")) { - this->hideUserlandThreads = atoi(option[1]); - } else if (String_eq(option[0], "shadow_other_users")) { - this->shadowOtherUsers = atoi(option[1]); - } else if (String_eq(option[0], "show_thread_names")) { - this->showThreadNames = atoi(option[1]); - } else if (String_eq(option[0], "show_program_path")) { - this->showProgramPath = atoi(option[1]); - } else if (String_eq(option[0], "highlight_base_name")) { - this->highlightBaseName = atoi(option[1]); - } else if (String_eq(option[0], "highlight_megabytes")) { - this->highlightMegabytes = atoi(option[1]); - } else if (String_eq(option[0], "highlight_threads")) { - this->highlightThreads = atoi(option[1]); - } else if (String_eq(option[0], "highlight_changes")) { - this->highlightChanges = atoi(option[1]); - } else if (String_eq(option[0], "highlight_changes_delay_secs")) { - this->highlightDelaySecs = CLAMP(atoi(option[1]), 1, 24*60*60); - } else if (String_eq(option[0], "find_comm_in_cmdline")) { - this->findCommInCmdline = atoi(option[1]); - } else if (String_eq(option[0], "strip_exe_from_cmdline")) { - this->stripExeFromCmdline = atoi(option[1]); - } else if (String_eq(option[0], "show_merged_command")) { - this->showMergedCommand = atoi(option[1]); - } else if (String_eq(option[0], "header_margin")) { - this->headerMargin = atoi(option[1]); - } else if (String_eq(option[0], "expand_system_time")) { - // Compatibility option. - this->detailedCPUTime = atoi(option[1]); - } else if (String_eq(option[0], "detailed_cpu_time")) { - this->detailedCPUTime = atoi(option[1]); - } else if (String_eq(option[0], "cpu_count_from_one")) { - this->countCPUsFromOne = atoi(option[1]); - } else if (String_eq(option[0], "cpu_count_from_zero")) { - // old (inverted) naming also supported for backwards compatibility - this->countCPUsFromOne = !atoi(option[1]); - } else if (String_eq(option[0], "show_cpu_usage")) { - this->showCPUUsage = atoi(option[1]); - } else if (String_eq(option[0], "show_cpu_frequency")) { - this->showCPUFrequency = atoi(option[1]); - #ifdef BUILD_WITH_CPU_TEMP - } else if (String_eq(option[0], "show_cpu_temperature")) { - this->showCPUTemperature = atoi(option[1]); - } else if (String_eq(option[0], "degree_fahrenheit")) { - this->degreeFahrenheit = atoi(option[1]); - #endif - } else if (String_eq(option[0], "update_process_names")) { - this->updateProcessNames = atoi(option[1]); - } else if (String_eq(option[0], "account_guest_in_cpu_meter")) { - this->accountGuestInCPUMeter = atoi(option[1]); - } else if (String_eq(option[0], "delay")) { - this->delay = CLAMP(atoi(option[1]), 1, 255); - } else if (String_eq(option[0], "color_scheme")) { - this->colorScheme = atoi(option[1]); - if (this->colorScheme < 0 || this->colorScheme >= LAST_COLORSCHEME) { - this->colorScheme = 0; - } - } else if (String_eq(option[0], "enable_mouse")) { - this->enableMouse = atoi(option[1]); - } else if (String_eq(option[0], "left_meters")) { - Settings_readMeters(this, option[1], 0); - didReadMeters = true; - } else if (String_eq(option[0], "right_meters")) { - Settings_readMeters(this, option[1], 1); - didReadMeters = true; - } else if (String_eq(option[0], "left_meter_modes")) { - Settings_readMeterModes(this, option[1], 0); - didReadMeters = true; - } else if (String_eq(option[0], "right_meter_modes")) { - Settings_readMeterModes(this, option[1], 1); - didReadMeters = true; - } else if (String_eq(option[0], "hide_function_bar")) { - this->hideFunctionBar = atoi(option[1]); - #ifdef HAVE_LIBHWLOC - } else if (String_eq(option[0], "topology_affinity")) { - this->topologyAffinity = !!atoi(option[1]); - #endif - } - String_freeArray(option); - } - fclose(fd); - if (!didReadMeters) { - Settings_defaultMeters(this, initialCpuCount); - } - return didReadFields; -} - -static void writeFields(FILE* fd, const ProcessField* fields, const char* name) { - fprintf(fd, "%s=", name); - const char* sep = ""; - for (int i = 0; fields[i]; i++) { - // This "-1" is for compatibility with the older enum format. - fprintf(fd, "%s%d", sep, (int) fields[i] - 1); - sep = " "; - } - fprintf(fd, "\n"); -} - -static void writeMeters(const Settings* this, FILE* fd, int column) { - const char* sep = ""; - for (int i = 0; i < this->columns[column].len; i++) { - fprintf(fd, "%s%s", sep, this->columns[column].names[i]); - sep = " "; - } - fprintf(fd, "\n"); -} - -static void writeMeterModes(const Settings* this, FILE* fd, int column) { - const char* sep = ""; - for (int i = 0; i < this->columns[column].len; i++) { - fprintf(fd, "%s%d", sep, this->columns[column].modes[i]); - sep = " "; - } - fprintf(fd, "\n"); -} - -int Settings_write(const Settings* this) { - FILE* fd = fopen(this->filename, "w"); - if (fd == NULL) - return -errno; - - fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n"); - fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n"); - writeFields(fd, this->fields, "fields"); - // This "-1" is for compatibility with the older enum format. - fprintf(fd, "sort_key=%d\n", (int) this->sortKey - 1); - fprintf(fd, "sort_direction=%d\n", (int) this->direction); - fprintf(fd, "tree_sort_key=%d\n", (int) this->treeSortKey - 1); - fprintf(fd, "tree_sort_direction=%d\n", (int) this->treeDirection); - fprintf(fd, "hide_kernel_threads=%d\n", (int) this->hideKernelThreads); - fprintf(fd, "hide_userland_threads=%d\n", (int) this->hideUserlandThreads); - fprintf(fd, "shadow_other_users=%d\n", (int) this->shadowOtherUsers); - fprintf(fd, "show_thread_names=%d\n", (int) this->showThreadNames); - fprintf(fd, "show_program_path=%d\n", (int) this->showProgramPath); - fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName); - fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes); - fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads); - fprintf(fd, "highlight_changes=%d\n", (int) this->highlightChanges); - fprintf(fd, "highlight_changes_delay_secs=%d\n", (int) this->highlightDelaySecs); - fprintf(fd, "find_comm_in_cmdline=%d\n", (int) this->findCommInCmdline); - fprintf(fd, "strip_exe_from_cmdline=%d\n", (int) this->stripExeFromCmdline); - fprintf(fd, "show_merged_command=%d\n", (int) this->showMergedCommand); - fprintf(fd, "tree_view=%d\n", (int) this->treeView); - fprintf(fd, "tree_view_always_by_pid=%d\n", (int) this->treeViewAlwaysByPID); - fprintf(fd, "all_branches_collapsed=%d\n", (int) this->allBranchesCollapsed); - fprintf(fd, "header_margin=%d\n", (int) this->headerMargin); - fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime); - fprintf(fd, "cpu_count_from_one=%d\n", (int) this->countCPUsFromOne); - fprintf(fd, "show_cpu_usage=%d\n", (int) this->showCPUUsage); - fprintf(fd, "show_cpu_frequency=%d\n", (int) this->showCPUFrequency); - #ifdef BUILD_WITH_CPU_TEMP - fprintf(fd, "show_cpu_temperature=%d\n", (int) this->showCPUTemperature); - fprintf(fd, "degree_fahrenheit=%d\n", (int) this->degreeFahrenheit); - #endif - fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames); - fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter); - fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme); - fprintf(fd, "enable_mouse=%d\n", (int) this->enableMouse); - fprintf(fd, "delay=%d\n", (int) this->delay); - fprintf(fd, "left_meters="); writeMeters(this, fd, 0); - fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0); - fprintf(fd, "right_meters="); writeMeters(this, fd, 1); - fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1); - fprintf(fd, "hide_function_bar=%d\n", (int) this->hideFunctionBar); - #ifdef HAVE_LIBHWLOC - fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity); - #endif - - int r = 0; - - if (ferror(fd) != 0) - r = (errno != 0) ? -errno : -EBADF; - - if (fclose(fd) != 0) - r = r ? r : -errno; - - return r; -} - -Settings* Settings_new(unsigned int initialCpuCount) { - Settings* this = xCalloc(1, sizeof(Settings)); - - this->sortKey = PERCENT_CPU; - this->treeSortKey = PID; - this->direction = -1; - this->treeDirection = 1; - this->shadowOtherUsers = false; - this->showThreadNames = false; - this->hideKernelThreads = false; - this->hideUserlandThreads = false; - this->treeView = false; - this->allBranchesCollapsed = false; - this->highlightBaseName = false; - this->highlightMegabytes = false; - this->detailedCPUTime = false; - this->countCPUsFromOne = false; - this->showCPUUsage = true; - this->showCPUFrequency = false; - #ifdef BUILD_WITH_CPU_TEMP - this->showCPUTemperature = false; - this->degreeFahrenheit = false; - #endif - this->updateProcessNames = false; - this->showProgramPath = true; - this->highlightThreads = true; - this->highlightChanges = false; - this->highlightDelaySecs = DEFAULT_HIGHLIGHT_SECS; - this->findCommInCmdline = true; - this->stripExeFromCmdline = true; - this->showMergedCommand = false; - this->hideFunctionBar = 0; - #ifdef HAVE_LIBHWLOC - this->topologyAffinity = false; - #endif - this->fields = xCalloc(LAST_PROCESSFIELD + 1, sizeof(ProcessField)); - // TODO: turn 'fields' into a Vector, - // (and ProcessFields into proper objects). - this->flags = 0; - const ProcessField* defaults = Platform_defaultFields; - for (int i = 0; defaults[i]; i++) { - this->fields[i] = defaults[i]; - this->flags |= Process_fields[defaults[i]].flags; - } - - char* legacyDotfile = NULL; - const char* rcfile = getenv("HTOPRC"); - if (rcfile) { - this->filename = xStrdup(rcfile); - } else { - const char* home = getenv("HOME"); - if (!home) - home = ""; - - const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); - char* configDir = NULL; - char* htopDir = NULL; - if (xdgConfigHome) { - this->filename = String_cat(xdgConfigHome, "/htop/htoprc"); - configDir = xStrdup(xdgConfigHome); - htopDir = String_cat(xdgConfigHome, "/htop"); - } else { - this->filename = String_cat(home, "/.config/htop/htoprc"); - configDir = String_cat(home, "/.config"); - htopDir = String_cat(home, "/.config/htop"); - } - legacyDotfile = String_cat(home, "/.htoprc"); - (void) mkdir(configDir, 0700); - (void) mkdir(htopDir, 0700); - free(htopDir); - free(configDir); - struct stat st; - int err = lstat(legacyDotfile, &st); - if (err || S_ISLNK(st.st_mode)) { - free(legacyDotfile); - legacyDotfile = NULL; - } - } - this->colorScheme = 0; - this->enableMouse = true; - this->changed = false; - this->delay = DEFAULT_DELAY; - bool ok = false; - if (legacyDotfile) { - ok = Settings_read(this, legacyDotfile, initialCpuCount); - if (ok) { - // Transition to new location and delete old configuration file - if (Settings_write(this) == 0) { - unlink(legacyDotfile); - } - } - free(legacyDotfile); - } - if (!ok) { - ok = Settings_read(this, this->filename, initialCpuCount); - } - if (!ok) { - this->changed = true; - ok = Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount); - } - if (!ok) { - Settings_defaultMeters(this, initialCpuCount); - this->hideKernelThreads = true; - this->highlightMegabytes = true; - this->highlightThreads = true; - this->findCommInCmdline = true; - this->stripExeFromCmdline = true; - this->showMergedCommand = false; - this->headerMargin = true; - } - return this; -} - -void Settings_invertSortOrder(Settings* this) { - int* attr = (this->treeView) ? &(this->treeDirection) : &(this->direction); - *attr = (*attr == 1) ? -1 : 1; -} - -void Settings_setSortKey(Settings* this, ProcessField sortKey) { - if (this->treeViewAlwaysByPID || !this->treeView) { - this->sortKey = sortKey; - this->direction = (Process_fields[sortKey].defaultSortDesc) ? -1 : 1; - this->treeView = false; - } else { - this->treeSortKey = sortKey; - this->treeDirection = (Process_fields[sortKey].defaultSortDesc) ? -1 : 1; - } -} diff -Nru pcp-5.3.1/src/pcp/htop/Settings.h pcp-5.3.2/src/pcp/htop/Settings.h --- pcp-5.3.1/src/pcp/htop/Settings.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Settings.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -#ifndef HEADER_Settings -#define HEADER_Settings -/* -htop - Settings.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include - -#include "Process.h" - - -#define DEFAULT_DELAY 15 - -typedef struct { - int len; - char** names; - int* modes; -} MeterColumnSettings; - -typedef struct Settings_ { - char* filename; - MeterColumnSettings columns[2]; - - ProcessField* fields; - uint32_t flags; - int colorScheme; - int delay; - - int direction; - int treeDirection; - ProcessField sortKey; - ProcessField treeSortKey; - - bool countCPUsFromOne; - bool detailedCPUTime; - bool showCPUUsage; - bool showCPUFrequency; - #ifdef BUILD_WITH_CPU_TEMP - bool showCPUTemperature; - bool degreeFahrenheit; - #endif - bool treeView; - bool treeViewAlwaysByPID; - bool allBranchesCollapsed; - bool showProgramPath; - bool shadowOtherUsers; - bool showThreadNames; - bool hideKernelThreads; - bool hideUserlandThreads; - bool highlightBaseName; - bool highlightMegabytes; - bool highlightThreads; - bool highlightChanges; - int highlightDelaySecs; - bool findCommInCmdline; - bool stripExeFromCmdline; - bool showMergedCommand; - bool updateProcessNames; - bool accountGuestInCPUMeter; - bool headerMargin; - bool enableMouse; - int hideFunctionBar; // 0 - off, 1 - on ESC until next input, 2 - permanently - #ifdef HAVE_LIBHWLOC - bool topologyAffinity; - #endif - - bool changed; -} Settings; - -#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromOne ? (cpu)+1 : (cpu)) - -static inline ProcessField Settings_getActiveSortKey(const Settings* this) { - return (this->treeView) - ? (this->treeViewAlwaysByPID ? PID : this->treeSortKey) - : this->sortKey; -} - -static inline int Settings_getActiveDirection(const Settings* this) { - return this->treeView ? this->treeDirection : this->direction; -} - -void Settings_delete(Settings* this); - -int Settings_write(const Settings* this); - -Settings* Settings_new(unsigned int initialCpuCount); - -void Settings_invertSortOrder(Settings* this); - -void Settings_setSortKey(Settings* this, ProcessField sortKey); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/SignalsPanel.c pcp-5.3.2/src/pcp/htop/SignalsPanel.c --- pcp-5.3.1/src/pcp/htop/SignalsPanel.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/SignalsPanel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* -htop - SignalsPanel.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "SignalsPanel.h" - -#include -#include - -#include "FunctionBar.h" -#include "ListItem.h" -#include "Object.h" -#include "Panel.h" -#include "Platform.h" -#include "XUtils.h" - - -Panel* SignalsPanel_new() { - Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Send ", "Cancel ")); - const int defaultSignal = SIGTERM; - int defaultPosition = 15; - unsigned int i; - for (i = 0; i < Platform_numberOfSignals; i++) { - Panel_set(this, i, (Object*) ListItem_new(Platform_signals[i].name, Platform_signals[i].number)); - // signal 15 is not always the 15th signal in the table - if (Platform_signals[i].number == defaultSignal) { - defaultPosition = i; - } - } - #if (defined(SIGRTMIN) && defined(SIGRTMAX)) - if (SIGRTMAX - SIGRTMIN <= 100) { - static char buf[16]; - for (int sig = SIGRTMIN; sig <= SIGRTMAX; i++, sig++) { - int n = sig - SIGRTMIN; - xSnprintf(buf, sizeof(buf), "%2d SIGRTMIN%-+3d", sig, n); - if (n == 0) { - buf[11] = '\0'; - } - Panel_set(this, i, (Object*) ListItem_new(buf, sig)); - } - } - #endif - Panel_setHeader(this, "Send signal:"); - Panel_setSelected(this, defaultPosition); - return this; -} diff -Nru pcp-5.3.1/src/pcp/htop/SignalsPanel.h pcp-5.3.2/src/pcp/htop/SignalsPanel.h --- pcp-5.3.1/src/pcp/htop/SignalsPanel.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/SignalsPanel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -#ifndef HEADER_SignalsPanel -#define HEADER_SignalsPanel -/* -htop - SignalsPanel.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Panel.h" - -typedef struct SignalItem_ { - const char* name; - int number; -} SignalItem; - -Panel* SignalsPanel_new(void); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/SwapMeter.c pcp-5.3.2/src/pcp/htop/SwapMeter.c --- pcp-5.3.1/src/pcp/htop/SwapMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/SwapMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -/* -htop - SwapMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "SwapMeter.h" - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" - - -static const int SwapMeter_attributes[] = { - SWAP, - SWAP_CACHE -}; - -static void SwapMeter_updateValues(Meter* this) { - char* buffer = this->txtBuffer; - size_t size = sizeof(this->txtBuffer); - int written; - Platform_setSwapValues(this); - - written = Meter_humanUnit(buffer, this->values[0], size); - METER_BUFFER_CHECK(buffer, size, written); - - METER_BUFFER_APPEND_CHR(buffer, size, '/'); - - Meter_humanUnit(buffer, this->total, size); -} - -static void SwapMeter_display(const Object* cast, RichString* out) { - char buffer[50]; - const Meter* this = (const Meter*)cast; - RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); - Meter_humanUnit(buffer, this->total, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - -#ifdef HTOP_LINUX - Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:"); - RichString_appendAscii(out, CRT_colors[SWAP_CACHE], buffer); -#endif -} - -const MeterClass SwapMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = SwapMeter_display, - }, - .updateValues = SwapMeter_updateValues, - .defaultMode = BAR_METERMODE, - .maxItems = 2, - .total = 100.0, - .attributes = SwapMeter_attributes, - .name = "Swap", - .uiName = "Swap", - .caption = "Swp" -}; diff -Nru pcp-5.3.1/src/pcp/htop/SwapMeter.h pcp-5.3.2/src/pcp/htop/SwapMeter.h --- pcp-5.3.1/src/pcp/htop/SwapMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/SwapMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_SwapMeter -#define HEADER_SwapMeter -/* -htop - SwapMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass SwapMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/SysArchMeter.c pcp-5.3.2/src/pcp/htop/SysArchMeter.c --- pcp-5.3.1/src/pcp/htop/SysArchMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/SysArchMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* -htop - SysArchMeter.c -(C) 2021 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ -#include "config.h" // IWYU pragma: keep - -#include "Platform.h" -#include "SysArchMeter.h" - -#include "XUtils.h" - - -static const int SysArchMeter_attributes[] = {HOSTNAME}; - -static void SysArchMeter_updateValues(Meter* this) { - static char* string; - - if (string == NULL) - Platform_getRelease(&string); - - String_safeStrncpy(this->txtBuffer, string, sizeof(this->txtBuffer)); -} - -const MeterClass SysArchMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = SysArchMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 0, - .total = 100.0, - .attributes = SysArchMeter_attributes, - .name = "System", - .uiName = "System", - .caption = "System: ", -}; diff -Nru pcp-5.3.1/src/pcp/htop/SysArchMeter.h pcp-5.3.2/src/pcp/htop/SysArchMeter.h --- pcp-5.3.1/src/pcp/htop/SysArchMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/SysArchMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_SysArchMeter -#define HEADER_SysArchMeter -/* -htop - SysArchMeter.h -(C) 2021 htop dev team -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ -#include "Meter.h" - - -extern const MeterClass SysArchMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/TasksMeter.c pcp-5.3.2/src/pcp/htop/TasksMeter.c --- pcp-5.3.1/src/pcp/htop/TasksMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/TasksMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* -htop - TasksMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "TasksMeter.h" - -#include "CRT.h" -#include "Macros.h" -#include "Object.h" -#include "ProcessList.h" -#include "RichString.h" -#include "Settings.h" -#include "XUtils.h" - - -static const int TasksMeter_attributes[] = { - CPU_SYSTEM, - PROCESS_THREAD, - PROCESS, - TASKS_RUNNING -}; - -static void TasksMeter_updateValues(Meter* this) { - const ProcessList* pl = this->pl; - this->values[0] = pl->kernelThreads; - this->values[1] = pl->userlandThreads; - this->values[2] = pl->totalTasks - pl->kernelThreads - pl->userlandThreads; - this->values[3] = MINIMUM(pl->runningTasks, pl->cpuCount); - this->total = pl->totalTasks; - - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%d/%d", (int) this->values[3], (int) this->total); -} - -static void TasksMeter_display(const Object* cast, RichString* out) { - const Meter* this = (const Meter*)cast; - const Settings* settings = this->pl->settings; - char buffer[20]; - - xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[2]); - RichString_writeAscii(out, CRT_colors[METER_VALUE], buffer); - - RichString_appendAscii(out, settings->hideUserlandThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], ", "); - xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[1]); - RichString_appendAscii(out, settings->hideUserlandThreads ? CRT_colors[METER_SHADOW] : CRT_colors[TASKS_RUNNING], buffer); - RichString_appendAscii(out, settings->hideUserlandThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], " thr"); - - RichString_appendAscii(out, settings->hideKernelThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], ", "); - xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[0]); - RichString_appendAscii(out, settings->hideKernelThreads ? CRT_colors[METER_SHADOW] : CRT_colors[TASKS_RUNNING], buffer); - RichString_appendAscii(out, settings->hideKernelThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], " kthr"); - - RichString_appendAscii(out, CRT_colors[METER_TEXT], "; "); - xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[3]); - RichString_appendAscii(out, CRT_colors[TASKS_RUNNING], buffer); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " running"); -} - -const MeterClass TasksMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = TasksMeter_display, - }, - .updateValues = TasksMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 4, - .total = 100.0, - .attributes = TasksMeter_attributes, - .name = "Tasks", - .uiName = "Task counter", - .caption = "Tasks: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/TasksMeter.h pcp-5.3.2/src/pcp/htop/TasksMeter.h --- pcp-5.3.1/src/pcp/htop/TasksMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/TasksMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_TasksMeter -#define HEADER_TasksMeter -/* -htop - TasksMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass TasksMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/TraceScreen.c pcp-5.3.2/src/pcp/htop/TraceScreen.c --- pcp-5.3.1/src/pcp/htop/TraceScreen.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/TraceScreen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,190 +0,0 @@ -/* -htop - TraceScreen.c -(C) 2005-2006 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "TraceScreen.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CRT.h" -#include "FunctionBar.h" -#include "IncSet.h" -#include "Panel.h" -#include "ProvideCurses.h" -#include "XUtils.h" - - -static const char* const TraceScreenFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing ", "Done ", NULL}; - -static const char* const TraceScreenKeys[] = {"F3", "F4", "F8", "F9", "Esc"}; - -static const int TraceScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27}; - -TraceScreen* TraceScreen_new(const Process* process) { - // This initializes all TraceScreen variables to "false" so only default = true ones need to be set below - TraceScreen* this = xCalloc(1, sizeof(TraceScreen)); - Object_setClass(this, Class(TraceScreen)); - this->tracing = true; - FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents); - CRT_disableDelay(); - return (TraceScreen*) InfoScreen_init(&this->super, process, fuBar, LINES - 2, " "); -} - -void TraceScreen_delete(Object* cast) { - TraceScreen* this = (TraceScreen*) cast; - if (this->child > 0) { - kill(this->child, SIGTERM); - waitpid(this->child, NULL, 0); - } - - if (this->strace) { - fclose(this->strace); - } - - CRT_enableDelay(); - free(InfoScreen_done((InfoScreen*)this)); -} - -static void TraceScreen_draw(InfoScreen* this) { - InfoScreen_drawTitled(this, "Trace of process %d - %s", this->process->pid, Process_getCommand(this->process)); -} - -bool TraceScreen_forkTracer(TraceScreen* this) { - int fdpair[2] = {0, 0}; - - if (pipe(fdpair) == -1) - return false; - - if (fcntl(fdpair[0], F_SETFL, O_NONBLOCK) < 0) - goto err; - - if (fcntl(fdpair[1], F_SETFL, O_NONBLOCK) < 0) - goto err; - - pid_t child = fork(); - if (child == -1) - goto err; - - if (child == 0) { - close(fdpair[0]); - - dup2(fdpair[1], STDOUT_FILENO); - dup2(fdpair[1], STDERR_FILENO); - close(fdpair[1]); - - char buffer[32] = {0}; - xSnprintf(buffer, sizeof(buffer), "%d", this->super.process->pid); - execlp("strace", "strace", "-T", "-tt", "-s", "512", "-p", buffer, NULL); - - // Should never reach here, unless execlp fails ... - const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; - (void)! write(STDERR_FILENO, message, strlen(message)); - - exit(127); - } - - FILE* fd = fdopen(fdpair[0], "r"); - if (!fd) - goto err; - - close(fdpair[1]); - - this->child = child; - this->strace = fd; - return true; - -err: - close(fdpair[1]); - close(fdpair[0]); - return false; -} - -static void TraceScreen_updateTrace(InfoScreen* super) { - TraceScreen* this = (TraceScreen*) super; - char buffer[1025]; - - int fd_strace = fileno(this->strace); - assert(fd_strace != -1); - - fd_set fds; - FD_ZERO(&fds); -// FD_SET(STDIN_FILENO, &fds); - FD_SET(fd_strace, &fds); - - struct timeval tv = { .tv_sec = 0, .tv_usec = 500 }; - int ready = select(fd_strace + 1, &fds, NULL, NULL, &tv); - - size_t nread = 0; - if (ready > 0 && FD_ISSET(fd_strace, &fds)) - nread = fread(buffer, 1, sizeof(buffer) - 1, this->strace); - - if (nread && this->tracing) { - const char* line = buffer; - buffer[nread] = '\0'; - for (size_t i = 0; i < nread; i++) { - if (buffer[i] == '\n') { - buffer[i] = '\0'; - if (this->contLine) { - InfoScreen_appendLine(&this->super, line); - this->contLine = false; - } else { - InfoScreen_addLine(&this->super, line); - } - line = buffer + i + 1; - } - } - if (line < buffer + nread) { - InfoScreen_addLine(&this->super, line); - buffer[nread] = '\0'; - this->contLine = true; - } - if (this->follow) { - Panel_setSelected(this->super.display, Panel_size(this->super.display) - 1); - } - } -} - -static bool TraceScreen_onKey(InfoScreen* super, int ch) { - TraceScreen* this = (TraceScreen*) super; - switch(ch) { - case 'f': - case KEY_F(8): - this->follow = !(this->follow); - if (this->follow) - Panel_setSelected(super->display, Panel_size(super->display)-1); - return true; - case 't': - case KEY_F(9): - this->tracing = !this->tracing; - FunctionBar_setLabel(super->display->defaultBar, KEY_F(9), this->tracing?"Stop Tracing ":"Resume Tracing "); - InfoScreen_draw(this); - return true; - } - this->follow = false; - return false; -} - -const InfoScreenClass TraceScreen_class = { - .super = { - .extends = Class(Object), - .delete = TraceScreen_delete - }, - .draw = TraceScreen_draw, - .onErr = TraceScreen_updateTrace, - .onKey = TraceScreen_onKey, -}; diff -Nru pcp-5.3.1/src/pcp/htop/TraceScreen.h pcp-5.3.2/src/pcp/htop/TraceScreen.h --- pcp-5.3.1/src/pcp/htop/TraceScreen.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/TraceScreen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -#ifndef HEADER_TraceScreen -#define HEADER_TraceScreen -/* -htop - TraceScreen.h -(C) 2005-2006 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include -#include -#include - -#include "InfoScreen.h" -#include "Object.h" -#include "Process.h" - - -typedef struct TraceScreen_ { - InfoScreen super; - bool tracing; - pid_t child; - FILE* strace; - bool contLine; - bool follow; -} TraceScreen; - - -extern const InfoScreenClass TraceScreen_class; - -TraceScreen* TraceScreen_new(const Process* process); - -void TraceScreen_delete(Object* cast); - -bool TraceScreen_forkTracer(TraceScreen* this); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/UptimeMeter.c pcp-5.3.2/src/pcp/htop/UptimeMeter.c --- pcp-5.3.1/src/pcp/htop/UptimeMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/UptimeMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* -htop - UptimeMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "UptimeMeter.h" - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "XUtils.h" - - -static const int UptimeMeter_attributes[] = { - UPTIME -}; - -static void UptimeMeter_updateValues(Meter* this) { - int totalseconds = Platform_getUptime(); - if (totalseconds == -1) { - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "(unknown)"); - return; - } - int seconds = totalseconds % 60; - int minutes = (totalseconds / 60) % 60; - int hours = (totalseconds / 3600) % 24; - int days = (totalseconds / 86400); - this->values[0] = days; - if (days > this->total) { - this->total = days; - } - char daysbuf[32]; - if (days > 100) { - xSnprintf(daysbuf, sizeof(daysbuf), "%d days(!), ", days); - } else if (days > 1) { - xSnprintf(daysbuf, sizeof(daysbuf), "%d days, ", days); - } else if (days == 1) { - xSnprintf(daysbuf, sizeof(daysbuf), "1 day, "); - } else { - daysbuf[0] = '\0'; - } - xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds); -} - -const MeterClass UptimeMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete - }, - .updateValues = UptimeMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 100.0, - .attributes = UptimeMeter_attributes, - .name = "Uptime", - .uiName = "Uptime", - .caption = "Uptime: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/UptimeMeter.h pcp-5.3.2/src/pcp/htop/UptimeMeter.h --- pcp-5.3.1/src/pcp/htop/UptimeMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/UptimeMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -#ifndef HEADER_UptimeMeter -#define HEADER_UptimeMeter -/* -htop - UptimeMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Meter.h" - -extern const MeterClass UptimeMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/UsersTable.c pcp-5.3.2/src/pcp/htop/UsersTable.c --- pcp-5.3.1/src/pcp/htop/UsersTable.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/UsersTable.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* -htop - UsersTable.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "UsersTable.h" - -#include -#include -#include -#include - -#include "XUtils.h" - - -UsersTable* UsersTable_new() { - UsersTable* this; - this = xMalloc(sizeof(UsersTable)); - this->users = Hashtable_new(10, true); - return this; -} - -void UsersTable_delete(UsersTable* this) { - Hashtable_delete(this->users); - free(this); -} - -char* UsersTable_getRef(UsersTable* this, unsigned int uid) { - char* name = Hashtable_get(this->users, uid); - if (name == NULL) { - const struct passwd* userData = getpwuid(uid); - if (userData != NULL) { - name = xStrdup(userData->pw_name); - Hashtable_put(this->users, uid, name); - } - } - return name; -} - -inline void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData) { - Hashtable_foreach(this->users, f, userData); -} diff -Nru pcp-5.3.1/src/pcp/htop/UsersTable.h pcp-5.3.2/src/pcp/htop/UsersTable.h --- pcp-5.3.1/src/pcp/htop/UsersTable.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/UsersTable.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#ifndef HEADER_UsersTable -#define HEADER_UsersTable -/* -htop - UsersTable.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Hashtable.h" - -typedef struct UsersTable_ { - Hashtable* users; -} UsersTable; - -UsersTable* UsersTable_new(void); - -void UsersTable_delete(UsersTable* this); - -char* UsersTable_getRef(UsersTable* this, unsigned int uid); - -void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/Vector.c pcp-5.3.2/src/pcp/htop/Vector.c --- pcp-5.3.1/src/pcp/htop/Vector.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Vector.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,340 +0,0 @@ -/* -htop - Vector.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Vector.h" - -#include -#include -#include - -#include "XUtils.h" - - -Vector* Vector_new(const ObjectClass* type, bool owner, int size) { - Vector* this; - - if (size == DEFAULT_SIZE) { - size = 10; - } - - assert(size > 0); - this = xMalloc(sizeof(Vector)); - this->growthRate = size; - this->array = (Object**) xCalloc(size, sizeof(Object*)); - this->arraySize = size; - this->items = 0; - this->type = type; - this->owner = owner; - return this; -} - -void Vector_delete(Vector* this) { - if (this->owner) { - for (int i = 0; i < this->items; i++) { - if (this->array[i]) { - Object_delete(this->array[i]); - } - } - } - free(this->array); - free(this); -} - -#ifndef NDEBUG - -static bool Vector_isConsistent(const Vector* this) { - assert(this->items <= this->arraySize); - - if (this->owner) { - for (int i = 0; i < this->items; i++) { - if (!this->array[i]) { - return false; - } - } - } - - return true; -} - -unsigned int Vector_count(const Vector* this) { - unsigned int items = 0; - for (int i = 0; i < this->items; i++) { - if (this->array[i]) { - items++; - } - } - assert(items == (unsigned int)this->items); - return items; -} - -Object* Vector_get(const Vector* this, int idx) { - assert(idx >= 0 && idx < this->items); - assert(this->array[idx]); - assert(Object_isA(this->array[idx], this->type)); - return this->array[idx]; -} - -int Vector_size(const Vector* this) { - assert(Vector_isConsistent(this)); - return this->items; -} - -#endif /* NDEBUG */ - -void Vector_prune(Vector* this) { - assert(Vector_isConsistent(this)); - if (this->owner) { - for (int i = 0; i < this->items; i++) - if (this->array[i]) { - Object_delete(this->array[i]); - //this->array[i] = NULL; - } - } - this->items = 0; -} - -//static int comparisons = 0; - -static void swap(Object** array, int indexA, int indexB) { - assert(indexA >= 0); - assert(indexB >= 0); - Object* tmp = array[indexA]; - array[indexA] = array[indexB]; - array[indexB] = tmp; -} - -static int partition(Object** array, int left, int right, int pivotIndex, Object_Compare compare) { - const Object* pivotValue = array[pivotIndex]; - swap(array, pivotIndex, right); - int storeIndex = left; - for (int i = left; i < right; i++) { - //comparisons++; - if (compare(array[i], pivotValue) <= 0) { - swap(array, i, storeIndex); - storeIndex++; - } - } - swap(array, storeIndex, right); - return storeIndex; -} - -static void quickSort(Object** array, int left, int right, Object_Compare compare) { - if (left >= right) - return; - - int pivotIndex = (left + right) / 2; - int pivotNewIndex = partition(array, left, right, pivotIndex, compare); - quickSort(array, left, pivotNewIndex - 1, compare); - quickSort(array, pivotNewIndex + 1, right, compare); -} - -// If I were to use only one sorting algorithm for both cases, it would probably be this one: -/* - -static void combSort(Object** array, int left, int right, Object_Compare compare) { - int gap = right - left; - bool swapped = true; - while ((gap > 1) || swapped) { - if (gap > 1) { - gap = (int)((double)gap / 1.247330950103979); - } - swapped = false; - for (int i = left; gap + i <= right; i++) { - comparisons++; - if (compare(array[i], array[i+gap]) > 0) { - swap(array, i, i+gap); - swapped = true; - } - } - } -} - -*/ - -static void insertionSort(Object** array, int left, int right, Object_Compare compare) { - for (int i = left + 1; i <= right; i++) { - Object* t = array[i]; - int j = i - 1; - while (j >= left) { - //comparisons++; - if (compare(array[j], t) <= 0) - break; - - array[j + 1] = array[j]; - j--; - } - array[j + 1] = t; - } -} - -void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare) { - assert(compare); - assert(Vector_isConsistent(this)); - quickSort(this->array, 0, this->items - 1, compare); - assert(Vector_isConsistent(this)); -} - -void Vector_insertionSort(Vector* this) { - assert(this->type->compare); - assert(Vector_isConsistent(this)); - insertionSort(this->array, 0, this->items - 1, this->type->compare); - assert(Vector_isConsistent(this)); -} - -static void Vector_checkArraySize(Vector* this) { - assert(Vector_isConsistent(this)); - if (this->items >= this->arraySize) { - //int i; - //i = this->arraySize; - this->arraySize = this->items + this->growthRate; - this->array = (Object**) xRealloc(this->array, sizeof(Object*) * this->arraySize); - //for (; i < this->arraySize; i++) - // this->array[i] = NULL; - } - assert(Vector_isConsistent(this)); -} - -void Vector_insert(Vector* this, int idx, void* data_) { - Object* data = data_; - assert(idx >= 0); - assert(Object_isA(data, this->type)); - assert(Vector_isConsistent(this)); - - if (idx > this->items) { - idx = this->items; - } - - Vector_checkArraySize(this); - //assert(this->array[this->items] == NULL); - if (idx < this->items) { - memmove(&this->array[idx + 1], &this->array[idx], (this->items - idx) * sizeof(this->array[0])); - } - this->array[idx] = data; - this->items++; - assert(Vector_isConsistent(this)); -} - -Object* Vector_take(Vector* this, int idx) { - assert(idx >= 0 && idx < this->items); - assert(Vector_isConsistent(this)); - Object* removed = this->array[idx]; - assert(removed); - this->items--; - if (idx < this->items) { - memmove(&this->array[idx], &this->array[idx + 1], (this->items - idx) * sizeof(this->array[0])); - } - //this->array[this->items] = NULL; - assert(Vector_isConsistent(this)); - return removed; -} - -Object* Vector_remove(Vector* this, int idx) { - Object* removed = Vector_take(this, idx); - if (this->owner) { - Object_delete(removed); - return NULL; - } else { - return removed; - } -} - -void Vector_moveUp(Vector* this, int idx) { - assert(idx >= 0 && idx < this->items); - assert(Vector_isConsistent(this)); - - if (idx == 0) - return; - - Object* temp = this->array[idx]; - this->array[idx] = this->array[idx - 1]; - this->array[idx - 1] = temp; -} - -void Vector_moveDown(Vector* this, int idx) { - assert(idx >= 0 && idx < this->items); - assert(Vector_isConsistent(this)); - - if (idx == this->items - 1) - return; - - Object* temp = this->array[idx]; - this->array[idx] = this->array[idx + 1]; - this->array[idx + 1] = temp; -} - -void Vector_set(Vector* this, int idx, void* data_) { - Object* data = data_; - assert(idx >= 0); - assert(Object_isA(data, this->type)); - assert(Vector_isConsistent(this)); - - Vector_checkArraySize(this); - if (idx >= this->items) { - this->items = idx + 1; - } else { - if (this->owner) { - Object* removed = this->array[idx]; - assert (removed != NULL); - Object_delete(removed); - } - } - this->array[idx] = data; - assert(Vector_isConsistent(this)); -} - -/* - -static void Vector_merge(Vector* this, Vector* v2) { - int i; - assert(Vector_isConsistent(this)); - - for (i = 0; i < v2->items; i++) - Vector_add(this, v2->array[i]); - v2->items = 0; - Vector_delete(v2); - assert(Vector_isConsistent(this)); -} - -*/ - -void Vector_add(Vector* this, void* data_) { - Object* data = data_; - assert(Object_isA(data, this->type)); - assert(Vector_isConsistent(this)); - int i = this->items; - Vector_set(this, this->items, data); - assert(this->items == i + 1); (void)(i); - assert(Vector_isConsistent(this)); -} - -int Vector_indexOf(const Vector* this, const void* search_, Object_Compare compare) { - const Object* search = search_; - assert(Object_isA(search, this->type)); - assert(compare); - assert(Vector_isConsistent(this)); - for (int i = 0; i < this->items; i++) { - const Object* o = this->array[i]; - assert(o); - if (compare(search, o) == 0) { - return i; - } - } - return -1; -} - -void Vector_splice(Vector* this, Vector* from) { - assert(Vector_isConsistent(this)); - assert(Vector_isConsistent(from)); - assert(!(this->owner && from->owner)); - - int olditems = this->items; - this->items += from->items; - Vector_checkArraySize(this); - for (int j = 0; j < from->items; j++) { - this->array[olditems + j] = from->array[j]; - } -} diff -Nru pcp-5.3.1/src/pcp/htop/Vector.h pcp-5.3.2/src/pcp/htop/Vector.h --- pcp-5.3.1/src/pcp/htop/Vector.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/Vector.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -#ifndef HEADER_Vector -#define HEADER_Vector -/* -htop - Vector.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "Object.h" - -#include - - -#ifndef DEFAULT_SIZE -#define DEFAULT_SIZE (-1) -#endif - -typedef struct Vector_ { - Object** array; - const ObjectClass* type; - int arraySize; - int growthRate; - int items; - bool owner; -} Vector; - -Vector* Vector_new(const ObjectClass* type, bool owner, int size); - -void Vector_delete(Vector* this); - -void Vector_prune(Vector* this); - -void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare); -static inline void Vector_quickSort(Vector* this) { - Vector_quickSortCustomCompare(this, this->type->compare); -} - -void Vector_insertionSort(Vector* this); - -void Vector_insert(Vector* this, int idx, void* data_); - -Object* Vector_take(Vector* this, int idx); - -Object* Vector_remove(Vector* this, int idx); - -void Vector_moveUp(Vector* this, int idx); - -void Vector_moveDown(Vector* this, int idx); - -void Vector_set(Vector* this, int idx, void* data_); - -#ifndef NDEBUG - -Object* Vector_get(const Vector* this, int idx); -int Vector_size(const Vector* this); -unsigned int Vector_count(const Vector* this); - -#else /* NDEBUG */ - -static inline Object* Vector_get(const Vector* this, int idx) { - return this->array[idx]; -} - -static inline int Vector_size(const Vector* this) { - return this->items; -} - -#endif /* NDEBUG */ - -static inline const ObjectClass* Vector_type(const Vector* this) { - return this->type; -} - -void Vector_add(Vector* this, void* data_); - -int Vector_indexOf(const Vector* this, const void* search_, Object_Compare compare); - -void Vector_splice(Vector* this, Vector* from); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/XUtils.c pcp-5.3.2/src/pcp/htop/XUtils.c --- pcp-5.3.1/src/pcp/htop/XUtils.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/XUtils.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,305 +0,0 @@ -/* -htop - StringUtils.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include "XUtils.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CRT.h" - - -void fail() { - CRT_done(); - abort(); - - _exit(1); // Should never reach here -} - -void* xMalloc(size_t size) { - assert(size > 0); - void* data = malloc(size); - if (!data) { - fail(); - } - return data; -} - -void* xMallocArray(size_t nmemb, size_t size) { - assert(nmemb > 0); - assert(size > 0); - if (SIZE_MAX / nmemb < size) { - fail(); - } - return xMalloc(nmemb * size); -} - -void* xCalloc(size_t nmemb, size_t size) { - assert(nmemb > 0); - assert(size > 0); - if (SIZE_MAX / nmemb < size) { - fail(); - } - void* data = calloc(nmemb, size); - if (!data) { - fail(); - } - return data; -} - -void* xRealloc(void* ptr, size_t size) { - assert(size > 0); - void* data = realloc(ptr, size); // deepcode ignore MemoryLeakOnRealloc: this goes to fail() - if (!data) { - free(ptr); - fail(); - } - return data; -} - -void* xReallocArray(void* ptr, size_t nmemb, size_t size) { - assert(nmemb > 0); - assert(size > 0); - if (SIZE_MAX / nmemb < size) { - fail(); - } - return xRealloc(ptr, nmemb * size); -} - -char* String_cat(const char* s1, const char* s2) { - const size_t l1 = strlen(s1); - const size_t l2 = strlen(s2); - char* out = xMalloc(l1 + l2 + 1); - memcpy(out, s1, l1); - memcpy(out + l1, s2, l2); - out[l1 + l2] = '\0'; - return out; -} - -char* String_trim(const char* in) { - while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') { - in++; - } - - size_t len = strlen(in); - while (len > 0 && (in[len - 1] == ' ' || in[len - 1] == '\t' || in[len - 1] == '\n')) { - len--; - } - - return xStrndup(in, len); -} - -char** String_split(const char* s, char sep, size_t* n) { - const unsigned int rate = 10; - char** out = xCalloc(rate, sizeof(char*)); - size_t ctr = 0; - unsigned int blocks = rate; - const char* where; - while ((where = strchr(s, sep)) != NULL) { - size_t size = (size_t)(where - s); - out[ctr] = xStrndup(s, size); - ctr++; - if (ctr == blocks) { - blocks += rate; - out = (char**) xRealloc(out, sizeof(char*) * blocks); - } - s += size + 1; - } - if (s[0] != '\0') { - out[ctr] = xStrdup(s); - ctr++; - } - out = xRealloc(out, sizeof(char*) * (ctr + 1)); - out[ctr] = NULL; - - if (n) - *n = ctr; - - return out; -} - -void String_freeArray(char** s) { - if (!s) { - return; - } - for (size_t i = 0; s[i] != NULL; i++) { - free(s[i]); - } - free(s); -} - -char* String_getToken(const char* line, const unsigned short int numMatch) { - const size_t len = strlen(line); - char inWord = 0; - unsigned short int count = 0; - char match[50]; - - size_t foundCount = 0; - - for (size_t i = 0; i < len; i++) { - char lastState = inWord; - inWord = line[i] == ' ' ? 0 : 1; - - if (lastState == 0 && inWord == 1) - count++; - - if (inWord == 1) { - if (count == numMatch && line[i] != ' ' && line[i] != '\0' && line[i] != '\n' && line[i] != (char)EOF) { - match[foundCount] = line[i]; - foundCount++; - } - } - } - - match[foundCount] = '\0'; - return xStrdup(match); -} - -char* String_readLine(FILE* fd) { - const unsigned int step = 1024; - unsigned int bufSize = step; - char* buffer = xMalloc(step + 1); - char* at = buffer; - for (;;) { - const char* ok = fgets(at, step + 1, fd); - if (!ok) { - free(buffer); - return NULL; - } - char* newLine = strrchr(at, '\n'); - if (newLine) { - *newLine = '\0'; - return buffer; - } else { - if (feof(fd)) { - return buffer; - } - } - bufSize += step; - buffer = xRealloc(buffer, bufSize + 1); - at = buffer + bufSize - step; - } -} - -size_t String_safeStrncpy(char *restrict dest, const char *restrict src, size_t size) { - assert(size > 0); - - size_t i = 0; - for (; i < size - 1 && src[i]; i++) - dest[i] = src[i]; - - dest[i] = '\0'; - - return i; -} - -int xAsprintf(char** strp, const char* fmt, ...) { - va_list vl; - va_start(vl, fmt); - int r = vasprintf(strp, fmt, vl); - va_end(vl); - - if (r < 0 || !*strp) { - fail(); - } - - return r; -} - -int xSnprintf(char* buf, size_t len, const char* fmt, ...) { - va_list vl; - va_start(vl, fmt); - int n = vsnprintf(buf, len, fmt, vl); - va_end(vl); - - if (n < 0 || (size_t)n >= len) { - fail(); - } - - return n; -} - -char* xStrdup(const char* str) { - char* data = strdup(str); - if (!data) { - fail(); - } - return data; -} - -void free_and_xStrdup(char** ptr, const char* str) { - if (*ptr && String_eq(*ptr, str)) - return; - - free(*ptr); - *ptr = xStrdup(str); -} - -char* xStrndup(const char* str, size_t len) { - char* data = strndup(str, len); - if (!data) { - fail(); - } - return data; -} - -static ssize_t readfd_internal(int fd, void* buffer, size_t count) { - if (!count) { - close(fd); - return -EINVAL; - } - - ssize_t alreadyRead = 0; - count--; // reserve one for null-terminator - - for (;;) { - ssize_t res = read(fd, buffer, count); - if (res == -1) { - if (errno == EINTR) - continue; - - close(fd); - return -errno; - } - - if (res > 0) { - buffer = ((char*)buffer) + res; - count -= (size_t)res; - alreadyRead += res; - } - - if (count == 0 || res == 0) { - close(fd); - *((char*)buffer) = '\0'; - return alreadyRead; - } - } -} - -ssize_t xReadfile(const char* pathname, void* buffer, size_t count) { - int fd = open(pathname, O_RDONLY); - if (fd < 0) - return -errno; - - return readfd_internal(fd, buffer, count); -} - -ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count) { - int fd = Compat_openat(dirfd, pathname, O_RDONLY); - if (fd < 0) - return -errno; - - return readfd_internal(fd, buffer, count); -} diff -Nru pcp-5.3.1/src/pcp/htop/XUtils.h pcp-5.3.2/src/pcp/htop/XUtils.h --- pcp-5.3.1/src/pcp/htop/XUtils.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/XUtils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -#ifndef HEADER_XUtils -#define HEADER_XUtils -/* -htop - StringUtils.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" // IWYU pragma: keep - -#include -#include -#include // IWYU pragma: keep -#include // IWYU pragma: keep -#include - -#include "Compat.h" -#include "Macros.h" - - -void fail(void) ATTR_NORETURN; - -void* xMalloc(size_t size) ATTR_ALLOC_SIZE1(1) ATTR_MALLOC; - -void* xMallocArray(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC; - -void* xCalloc(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC; - -void* xRealloc(void* ptr, size_t size) ATTR_ALLOC_SIZE1(2); - -void* xReallocArray(void* ptr, size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(2, 3); - -/* - * String_startsWith gives better performance if strlen(match) can be computed - * at compile time (e.g. when they are immutable string literals). :) - */ -static inline bool String_startsWith(const char* s, const char* match) { - return strncmp(s, match, strlen(match)) == 0; -} - -static inline bool String_contains_i(const char* s1, const char* s2) { - return strcasestr(s1, s2) != NULL; -} - -static inline bool String_eq(const char* s1, const char* s2) { - return strcmp(s1, s2) == 0; -} - -char* String_cat(const char* s1, const char* s2) ATTR_MALLOC; - -char* String_trim(const char* in) ATTR_MALLOC; - -char** String_split(const char* s, char sep, size_t* n); - -void String_freeArray(char** s); - -char* String_getToken(const char* line, unsigned short int numMatch) ATTR_MALLOC; - -char* String_readLine(FILE* fd) ATTR_MALLOC; - -/* Always null-terminates dest. Caller must pass a strictly positive size. */ -size_t String_safeStrncpy(char *restrict dest, const char *restrict src, size_t size); - -ATTR_FORMAT(printf, 2, 3) -int xAsprintf(char** strp, const char* fmt, ...); - -ATTR_FORMAT(printf, 3, 4) -int xSnprintf(char* buf, size_t len, const char* fmt, ...); - -char* xStrdup(const char* str) ATTR_NONNULL ATTR_MALLOC; -void free_and_xStrdup(char** ptr, const char* str); - -char* xStrndup(const char* str, size_t len) ATTR_NONNULL ATTR_MALLOC; - -ssize_t xReadfile(const char* pathname, void* buffer, size_t count); -ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count); - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/zfs/ZfsArcMeter.c pcp-5.3.2/src/pcp/htop/zfs/ZfsArcMeter.c --- pcp-5.3.1/src/pcp/htop/zfs/ZfsArcMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/zfs/ZfsArcMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* -htop - ZfsArcMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ZfsArcMeter.h" -#include "ZfsArcStats.h" - -#include "CRT.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" - - -static const int ZfsArcMeter_attributes[] = { - ZFS_MFU, ZFS_MRU, ZFS_ANON, ZFS_HEADER, ZFS_OTHER -}; - -void ZfsArcMeter_readStats(Meter* this, const ZfsArcStats* stats) { - this->total = stats->max; - this->values[0] = stats->MFU; - this->values[1] = stats->MRU; - this->values[2] = stats->anon; - this->values[3] = stats->header; - this->values[4] = stats->other; - - // "Hide" the last value so it can - // only be accessed by index and is not - // displayed by the Bar or Graph style - this->curItems = 5; - this->values[5] = stats->size; -} - -static void ZfsArcMeter_updateValues(Meter* this) { - char* buffer = this->txtBuffer; - size_t size = sizeof(this->txtBuffer); - int written; - Platform_setZfsArcValues(this); - - written = Meter_humanUnit(buffer, this->values[5], size); - METER_BUFFER_CHECK(buffer, size, written); - - METER_BUFFER_APPEND_CHR(buffer, size, '/'); - - Meter_humanUnit(buffer, this->total, size); -} - -static void ZfsArcMeter_display(const Object* cast, RichString* out) { - const Meter* this = (const Meter*)cast; - - if (this->values[5] > 0) { - char buffer[50]; - Meter_humanUnit(buffer, this->total, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - Meter_humanUnit(buffer, this->values[5], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Used:"); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " MFU:"); - RichString_appendAscii(out, CRT_colors[ZFS_MFU], buffer); - Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " MRU:"); - RichString_appendAscii(out, CRT_colors[ZFS_MRU], buffer); - Meter_humanUnit(buffer, this->values[2], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Anon:"); - RichString_appendAscii(out, CRT_colors[ZFS_ANON], buffer); - Meter_humanUnit(buffer, this->values[3], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Hdr:"); - RichString_appendAscii(out, CRT_colors[ZFS_HEADER], buffer); - Meter_humanUnit(buffer, this->values[4], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Oth:"); - RichString_appendAscii(out, CRT_colors[ZFS_OTHER], buffer); - } else { - RichString_writeAscii(out, CRT_colors[METER_TEXT], " "); - RichString_appendAscii(out, CRT_colors[FAILED_READ], "Unavailable"); - } -} - -const MeterClass ZfsArcMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = ZfsArcMeter_display, - }, - .updateValues = ZfsArcMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 6, - .total = 100.0, - .attributes = ZfsArcMeter_attributes, - .name = "ZFSARC", - .uiName = "ZFS ARC", - .caption = "ARC: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/zfs/ZfsArcMeter.h pcp-5.3.2/src/pcp/htop/zfs/ZfsArcMeter.h --- pcp-5.3.1/src/pcp/htop/zfs/ZfsArcMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/zfs/ZfsArcMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#ifndef HEADER_ZfsArcMeter -#define HEADER_ZfsArcMeter -/* -htop - ZfsArcMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ZfsArcStats.h" - -#include "Meter.h" - -void ZfsArcMeter_readStats(Meter* this, const ZfsArcStats* stats); - -extern const MeterClass ZfsArcMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/zfs/ZfsArcStats.h pcp-5.3.2/src/pcp/htop/zfs/ZfsArcStats.h --- pcp-5.3.1/src/pcp/htop/zfs/ZfsArcStats.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/zfs/ZfsArcStats.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#ifndef HEADER_ZfsArcStats -#define HEADER_ZfsArcStats -/* -htop - ZfsArcStats.h -(C) 2014 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -typedef struct ZfsArcStats_ { - int enabled; - int isCompressed; - unsigned long long int max; - unsigned long long int size; - unsigned long long int MFU; - unsigned long long int MRU; - unsigned long long int anon; - unsigned long long int header; - unsigned long long int other; - unsigned long long int compressed; - unsigned long long int uncompressed; -} ZfsArcStats; - -#endif diff -Nru pcp-5.3.1/src/pcp/htop/zfs/ZfsCompressedArcMeter.c pcp-5.3.2/src/pcp/htop/zfs/ZfsCompressedArcMeter.c --- pcp-5.3.1/src/pcp/htop/zfs/ZfsCompressedArcMeter.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/zfs/ZfsCompressedArcMeter.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* -htop - ZfsCompressedArcMeter.c -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ZfsCompressedArcMeter.h" - -#include "CRT.h" -#include "Meter.h" -#include "Object.h" -#include "Platform.h" -#include "RichString.h" -#include "XUtils.h" - -#include "zfs/ZfsArcStats.h" - - -static const int ZfsCompressedArcMeter_attributes[] = { - ZFS_COMPRESSED -}; - -void ZfsCompressedArcMeter_readStats(Meter* this, const ZfsArcStats* stats) { - if ( stats->isCompressed ) { - this->total = stats->uncompressed; - this->values[0] = stats->compressed; - } else { - // For uncompressed ARC, report 1:1 ratio - this->total = stats->size; - this->values[0] = stats->size; - } -} - -static void ZfsCompressedArcMeter_printRatioString(const Meter* this, char* buffer, size_t size) { - xSnprintf(buffer, size, "%.2f:1", this->total / this->values[0]); -} - -static void ZfsCompressedArcMeter_updateValues(Meter* this) { - Platform_setZfsCompressedArcValues(this); - - ZfsCompressedArcMeter_printRatioString(this, this->txtBuffer, sizeof(this->txtBuffer)); -} - -static void ZfsCompressedArcMeter_display(const Object* cast, RichString* out) { - const Meter* this = (const Meter*)cast; - - if (this->values[0] > 0) { - char buffer[50]; - Meter_humanUnit(buffer, this->total, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Uncompressed, "); - Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Compressed, "); - ZfsCompressedArcMeter_printRatioString(this, buffer, sizeof(buffer)); - RichString_appendAscii(out, CRT_colors[ZFS_RATIO], buffer); - RichString_appendAscii(out, CRT_colors[METER_TEXT], " Ratio"); - } else { - RichString_writeAscii(out, CRT_colors[METER_TEXT], " "); - RichString_appendAscii(out, CRT_colors[FAILED_READ], "Compression Unavailable"); - } -} - -const MeterClass ZfsCompressedArcMeter_class = { - .super = { - .extends = Class(Meter), - .delete = Meter_delete, - .display = ZfsCompressedArcMeter_display, - }, - .updateValues = ZfsCompressedArcMeter_updateValues, - .defaultMode = TEXT_METERMODE, - .maxItems = 1, - .total = 100.0, - .attributes = ZfsCompressedArcMeter_attributes, - .name = "ZFSCARC", - .uiName = "ZFS CARC", - .description = "ZFS CARC: Compressed ARC statistics", - .caption = "ARC: " -}; diff -Nru pcp-5.3.1/src/pcp/htop/zfs/ZfsCompressedArcMeter.h pcp-5.3.2/src/pcp/htop/zfs/ZfsCompressedArcMeter.h --- pcp-5.3.1/src/pcp/htop/zfs/ZfsCompressedArcMeter.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pcp/htop/zfs/ZfsCompressedArcMeter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#ifndef HEADER_ZfsCompressedArcMeter -#define HEADER_ZfsCompressedArcMeter -/* -htop - ZfsCompressedArcMeter.h -(C) 2004-2011 Hisham H. Muhammad -Released under the GNU GPLv2, see the COPYING file -in the source distribution for its full text. -*/ - -#include "ZfsArcStats.h" - -#include "Meter.h" - -void ZfsCompressedArcMeter_readStats(Meter* this, const ZfsArcStats* stats); - -extern const MeterClass ZfsCompressedArcMeter_class; - -#endif diff -Nru pcp-5.3.1/src/pcp/iostat/pcp-iostat.1 pcp-5.3.2/src/pcp/iostat/pcp-iostat.1 --- pcp-5.3.1/src/pcp/iostat/pcp-iostat.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/pcp/iostat/pcp-iostat.1 2021-07-30 04:05:06.000000000 +0000 @@ -31,23 +31,36 @@ When invoked via the .BR pcp (1) command, the +.I "pcp options" +.hy 0 +.BR \-A /\c +.BR \-\-align , .BR \-a /\c .BR \-\-archive , .BR \-h /\c .BR \-\-host , .BR \-O /\c .BR \-\-origin , +.BR \-S /\c +.BR \-\-start , .BR \-s /\c .BR \-\-samples , +.BR \-T /\c +.BR \-\-finish , .BR \-t /\c .BR \-\-interval , +.BR \-v /\c +.BR \-\-version , .BR \-Z /\c -.BR \-\-timezone -and several other -.I pcp options +.B \-\-timezone +and +.BR \-z /\c +.B \-\-hostzone become indirectly available; refer to .BR PCPIntro (1) for a complete description of these options. +.br +.hy .PP The additional command line options available for .B pcp-iostat @@ -170,6 +183,9 @@ .B \-a must also be specified. .TP +\fB\-V\fR, \fB\-\-version\fR +Display version number and exit. +.TP \f3\-x\f1 \f2comma-separated-options\f1 Specifies a comma-separated list of one or more extended reporting options as follows: diff -Nru pcp-5.3.1/src/pcp/ss/.gitignore pcp-5.3.2/src/pcp/ss/.gitignore --- pcp-5.3.1/src/pcp/ss/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pcp/ss/.gitignore 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1 @@ +pcp-ss.1.gz diff -Nru pcp-5.3.1/src/pcp/ss/GNUmakefile pcp-5.3.2/src/pcp/ss/GNUmakefile --- pcp-5.3.1/src/pcp/ss/GNUmakefile 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pcp/ss/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,40 @@ +# +# Copyright (c) 2021 Red Hat, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs + +TARGET = pcp-ss +SCRIPT = $(TARGET).py +MAN_PAGES = $(TARGET).1 + +default: $(SCRIPT) + +include $(BUILDRULES) + +install: default +ifeq "$(HAVE_PYTHON)" "true" + $(INSTALL) -m 755 $(SCRIPT) $(PCP_BINADM_DIR)/$(TARGET) + @$(INSTALL_MAN) +endif + +default_pcp: default + +install_pcp: install + +check :: $(SCRIPT) + $(PYLINT) $^ + +check :: $(MAN_PAGES) + $(MANLINT) $^ diff -Nru pcp-5.3.1/src/pcp/ss/pcp-ss.1 pcp-5.3.2/src/pcp/ss/pcp-ss.1 --- pcp-5.3.1/src/pcp/ss/pcp-ss.1 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pcp/ss/pcp-ss.1 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,284 @@ +'\"macro stdmacro +.\" +.\" Copyright (c) 2021 Red Hat. +.\" +.\" This program is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License as published by the +.\" Free Software Foundation; either version 2 of the License, or (at your +.\" option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +.\" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +.\" for more details. +.\" +.\" +.TH PCP-SS 1 "PCP" "Performance Co-Pilot" +.SH NAME +\f3pcp-ss\f1 \- report socket statistics +.SH SYNOPSIS +\f3pcp\f1 [\f2pcp\ options\f1] \f3ss\f1 [\f2ss\ options\f1] +.SH DESCRIPTION +.B pcp-ss +reports socket statistics collected by the +.BR pmdasockets (1) +PMDA agent. +The command is intended to be closely compatible with many of the +.BR ss (8) +command line options and reporting formats, but also offer +the advantages of local or remote monitoring (in live mode) and +also historical replay from a previously recorded PCP archive. +.PP +Live mode uses the +.B pcp +\fB-h\fP \fIhost\fP option and requires the +.BR pmdasockets (1) +PMDA to be installed and enabled on the target \fIhost\fP (local or remote), see +.BR pmdasockets (1) +for details on how to enable the \fBsockets\fP PMDA on a particular host. +The default source is live metrics collected on +.BR localhost , +if neither of the +.B \-h +or +.B \-a +options are given. +.PP +Historical/archive replay uses the +.B pcp +\fB-a\fP \fIarchive\fP option, where \fIarchive\fP is the +basename of a previously recorded PCP archive. +The archive replay feature is particularly useful because +socket statistics can be reported for a designated time using the +.B pcp +.B \-\-origin +option (which defaults to the start time of the archive). +.SH EXAMPLES +.TP 5 +\fBpcp ss\fP +Display default basic socket information for the local host. +This includes \fBNetid\fP (\fBtcp\fP, \fBudp\fP, etc), \fBState\fP (\fBESTAB\fP, +\fBTIME_WAIT\fP, etc), \fBRecv-Q\fP and \fBSend-Q\fP queue lengths +and the local and peer address and port for each socket. +.TP 5 +\fBpcp \-h \fIsomehost\fP ss \-noemitauO\fP +Display the same basic socket information as above for the host \fIsomehost\fP, +which may be the default \fBlocalhost\fP. +The additional command line arguments (\fB\-noemitauO\fP) display +one line per socket (\fB\-O\fP), numeric (\fB\-n\fP) service names (default), +timer information (\fB\-o\fP), extended socket details (\fB\-e\fP), +socket memory usage (\fB\-m\fP), internal TCP information (\fB\-i\fP), +both udp (\fB\-u\fP) and tcp sockets (\fB\-t\fP) and both listening and +non-listening sockets (\fB\-a\fP). +.TP 5 +\fBpcp \-a \fIsomearchive\fP \fB-S'@Wed 16 Jun 2021 12:57:21'\fP ss \-noemitauO\fP +Display the same information as the above example, but for the archive +\fIsomearchive\fP starting at the given time \fBWed 16 Jun 2021 12:57:21\fP. +Note the literal \fB@\fP prefix is required for an absolute time, see +.BR PCPIntro (1) +for details. +The archive must of course contain data for the requested time. You can use +\fBpmdumplog \-l\fP \fIsomearchive\fP to examine the time bounds of \fIsomearchive\fP. +.TP 5 +\fBpcp \-a \fIsomearchive\fP \fB\-O\-0\fP ss \-noemitauO\fP +As above, but with an offset of zero seconds (\fB\-O\-0\fP) before the current end of +\fIsomearchive\fP, i.e. the most recently logged data. Note that \fIsomearchive\fP +may be curently growing (i.e. being logged with +.BR pmlogger (1)). +.SH OPTIONS +Due to the large number of options supported by +.BR pcp-ss , +the +.BR pcp (1) +command should always be used to invoke +.B pcp-ss +in order to specify options such as the metrics source (host or archive) +and also (in archive mode), the requested start time or offset, and timezone +using the following options: +.TP 5 +\fB\-h\fP, \fB\-\-host\fP +The remote hostname to connect to in live mode +.TP 5 +\fB\-a\fP, \fB\-\-archive\fP +The archive file to use for historical sampling +.TP 5 +\fB\-O\fP, \fB\-\-origin\fP +The time offset to use within an archive (implies +.BR \-a ) +.TP 5 +\fB\-S\fP, \fB\-\-start\fP +The start time (e.g. in +.BR ctime (3) +format) to use when replaying an archive. +.TP 5 +\fB\-Z\fP, \fB\-\-timezone\fP +Use a specific timezone. +Since +.B pcp-ss +doesn't report timestamps, this only affects the interpretation +of an absolute starting time (\fB\-S\fP) or offset (\fB\-O\fP). +.TP 5 +\fB\-z\fP, \fB\-\-hostzone\fP +In archive mode, use the timezone of the archive rather than the +timezone on the local machine running +.BR pcp-ss . +The timezone, start and finish times of the archive may be examined using +.BR pmdumplog (1) +with the \fB\-L\fP option. +.PP +The above +.B pcp +options become indirectly available to the +.B pcp-ss +command via environment variables - refer to +.BR PCPIntro (1) +for a complete description of these options. +.PP +The additional command line options available for +.B pcp-ss +itself are: +.TP 5 +\fB\-h\fP, \fB\-\-help\fP +show help message and exit +.TP 5 +\fB\-V\fP, \fB\-\-version\fP +output version information +.TP 5 +\fB\-n\fP, \fB\-\-numeric\fP +don't resolve service names +.TP 5 +\fB\-r\fP, \fB\-\-resolve\fP +resolve host names +.TP 5 +\fB\-a\fP, \fB\-\-all\fP +display all sockets +.TP 5 +\fB\-l\fP, \fB\-\-listening\fP +display listening sockets +.TP 5 +\fB\-o\fP, \fB\-\-options\fP +show timer information +.TP 5 +\fB\-e\fP, \fB\-\-extended\fP +show detailed socket information +.TP 5 +\fB\-m\fP, \fB\-\-memory\fP +show socket memory usage +.TP 5 +\fB\-p\fP, \fB\-\-processes\fP +show process using socket +.TP 5 +\fB\-i\fP, \fB\-\-info\fP +show internal TCP information +.TP 5 +\fB\-s\fP, \fB\-\-summary\fP +show socket usage summary +.TP 5 +\fB\-b\fP, \fB\-\-bpf\fP +show bpf filter socket information +.TP 5 +\fB\-E\fP, \fB\-\-events\fP +continually display sockets as they are destroyed +.TP 5 +\fB\-Z\fP, \fB\-\-context\fP +display process SELinux security contexts +.TP 5 +\fB\-z\fP, \fB\-\-contexts\fP +display process and socket SELinux security contexts +.TP 5 +\fB\-N\fP, \fB\-\-net\fP +switch to the specified network namespace name +.TP 5 +\fB\-4\fP, \fB\-\-ipv4\fP +display only IP version 4 sockets +.TP 5 +\fB\-6\fP, \fB\-\-ipv6\fP +display only IP version 6 sockets +.TP 5 +\fB\-0\fP, \fB\-\-packet\fP +display PACKET sockets +.TP 5 +\fB\-t\fP, \fB\-\-tcp\fP +display only TCP sockets +.TP 5 +\fB\-M\fP, \fB\-\-mptcp\fP +display only MPTCP sockets +.TP 5 +\fB\-S\fP, \fB\-\-sctp\fP +display only SCTP sockets +.TP 5 +\fB\-u\fP, \fB\-\-udp\fP +display only UDP sockets +.TP 5 +\fB\-d\fP, \fB\-\-dccp\fP +display only DCCP sockets +.TP 5 +\fB\-w\fP, \fB\-\-raw\fP +display only RAW sockets +.TP 5 +\fB\-x\fP, \fB\-\-unix\fP +display only Unix domain sockets +.TP 5 +\fB\-H\fP, \fB\-\-noheader\fP +Suppress header line +.TP 5 +\fB\-O\fP, \fB\-\-oneline\fP +socket's data printed on a single line +.SH REPORT +The columns in the +.B pcp-ss +report vary according to the command line options and have the +same interpretation as described in +.BR ss (8). +.PP +One difference with +.B pcp-ss +is that the first line in the report begins with '\fB# Timestamp\fP' +followed by the timestamp (in the requested timezone, see \fB\-z\fP and \fB\-Z\fP above) +of the sample data from the host or archive source. +Following the timestamp is the currently active filter string for the metrics source. +In archive mode, the active filter can be changed dynamically, even whilst the archive is +being recorded. +This is different to +.BR ss (8) +where the filter is optionally specified on the command line of the tool and is +always 'live', i.e. +.BR ss (8) +does not support retrospective replay. +With +.BR pcp-ss , +the filter is stored in the back-end PMDA, see +.BR pmdasockets (1), +in the metric +.BR network.persocket.filter. +The default filter is \fBstate connected\fP, which can be changed by +storing a new string value in the +.B network.persocket.filter +metric using +.BR pmstore (1), +e.g. +\fBpmstore network.persocket.filter "state established"\fP. +This will override the persistent default filter, which is stored +in a PMDA configuration file and loaded each time the sockets PMDA is started. +See +.BR pmdasockets (1) +for further details and see +.BR ss (8) +for details of the filter syntax and examples. +.SH PCP ENVIRONMENT +Environment variables with the prefix \fBPCP_\fP are used to parameterize +the file and directory names used by PCP. +On each installation, the +file \fI/etc/pcp.conf\fP contains the local values for these variables. +The \fB$PCP_CONF\fP variable may be used to specify an alternative +configuration file, as described in \fBpcp.conf\fP(5). +.PP +For environment variables affecting PCP tools, see \fBpmGetOptions\fP(3). +.SH SEE ALSO +.BR PCPIntro (1), +.BR pcp (1), +.BR pmdasockets (1), +.BR pmlogger (1), +.BR pcp.conf (5) +and +.BR ss (8). diff -Nru pcp-5.3.1/src/pcp/ss/pcp-ss.py pcp-5.3.2/src/pcp/ss/pcp-ss.py --- pcp-5.3.1/src/pcp/ss/pcp-ss.py 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pcp/ss/pcp-ss.py 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,373 @@ +#!/usr/bin/env pmpython +# +# Copyright (C) 2021 Red Hat. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# pylint: disable=line-too-long,bad-continuation,broad-except,bare-except +# pylint: disable=missing-docstring,multiple-imports,unused-import +# pylint: disable=too-many-boolean-expressions + +""" Display socket statistics """ + +import os, sys, argparse, errno + +# PCP Python PMAPI +from pcp import pmapi +from cpmapi import PM_CONTEXT_ARCHIVE, PM_CONTEXT_HOST, PM_CONTEXT_LOCAL +from cpmapi import PM_ERR_EOL, PM_MODE_FORW, PM_MODE_INTERP + +if sys.version >= '3': + long = int + +# pmns prefix for pmdasockets(1) metrics +pmns = "network.persocket" + +def remove_prefix(text, prefix): + """ remove prefix from text (for python < 3.9) """ + return text[text.startswith(prefix) and len(prefix):] + +class SS(object): + """ PCP client implementation of the ss(1) tool, using pmdasockets(1) """ + + def __init__(self): + """ Construct object - prepare for command line handling """ + self.args = self.options() + self.source = "local:" + self.speclocal = None + self.metrics = [] + self.instD = {} # { instid: instname } + self.metricsD = {} # { name: fetchgroup } + self.descsD = {} # { name: pmDesc } + self.valuesD = {} # { name: {instid: value} } + self.context = None + self.pmfg = None + + def options(self): + """ define command line arguments """ + p = argparse.ArgumentParser() + p.add_argument('-V', '--version', action='store_true', help='output version information') + p.add_argument('-n', '--numeric', action='store_true', help='don\'t resolve service names (currently always set)') + p.add_argument('-r', '--resolve', action='store_true', help='resolve host names (currently always set)') + p.add_argument('-a', '--all', action='store_true', help='display all sockets') + p.add_argument('-l', '--listening', action='store_true', help='display listening sockets') + p.add_argument('-o', '--options', action='store_true', help='show timer information') + p.add_argument('-e', '--extended', action='store_true', help='show detailed socket information') + p.add_argument('-m', '--memory', action='store_true', help='show socket memory usage') + p.add_argument('-p', '--processes', action='store_true', help='show process using socket (not yet implemented)') + p.add_argument('-i', '--info', action='store_true', help='show internal TCP information') + p.add_argument('-s', '--summary', action='store_true', help='show socket usage summary (not yet implemented)') + p.add_argument('-b', '--bpf', action='store_true', help='show bpf filter socket information (not yet implemented)') + p.add_argument('-E', '--events', action='store_true', help='continually display sockets as they are destroyed (not implemented)') + p.add_argument('-Z', '--context', action='store_true', help='display process SELinux security contexts (not implemented)') + p.add_argument('-z', '--contexts', action='store_true', help='display process and socket SELinux security contexts (not implemented)') + p.add_argument('-N', '--net', action='store_true', help='switch to the specified network namespace name (not implemented)') + p.add_argument('-4', '--ipv4', action='store_true', help='display only IP version 4 sockets') + p.add_argument('-6', '--ipv6', action='store_true', help='display only IP version 6 sockets') + p.add_argument('-0', '--packet', action='store_true', help='display PACKET sockets (not implemented)') + p.add_argument('-t', '--tcp', action='store_true', help='display only TCP sockets') + p.add_argument('-M', '--mptcp', action='store_true', help='display only MPTCP sockets (not implemented)') + p.add_argument('-S', '--sctp', action='store_true', help='display only SCTP sockets (not implemented)') + p.add_argument('-u', '--udp', action='store_true', help='display only UDP sockets') + p.add_argument('-d', '--dccp', action='store_true', help='display only DCCP sockets (not implemented)') + p.add_argument('-w', '--raw', action='store_true', help='display only RAW sockets (not implemented)') + p.add_argument('-x', '--unix', action='store_true', help='display only Unix domain sockets (not implemented)') + p.add_argument('-H', '--noheader', action='store_true', help='Suppress header line') + p.add_argument('-O', '--oneline', action='store_true', help='print each socket\'s data on a single line') + args = p.parse_args() + + # special cases + if not (args.tcp or args.udp or args.mptcp or args.sctp or args.packet or args.dccp or args.raw or args.unix): + args.tcp = args.udp = args.mptcp = args.sctp = args.packet = args.dccp = args.raw = args.unix = True + + if not (args.ipv4 or args.ipv6): + args.ipv4 = args.ipv6 = True + + if args.all: + args.listening = True + + if args.events or args.context or args.contexts or args.net or args.summary or args.processes: + print("Warning: --events, --context --net, --summary and --processes options are not implemented") + + return args + + def connect(self): + """ Establish a fetchgroup PMAPI context to archive, host or local, + via environment passed in by pcp(1). The ss(1) command has many + clashes with standard PCP arguments so this is the only supported + invocation. Debug options (if any) are set for us by pcp(1). + Return True or False if we fail to connect. + """ + # source + pcp_host = os.getenv("PCP_HOST") + pcp_archive = os.getenv("PCP_ARCHIVE") + + # time window + pcp_origin = os.getenv("PCP_ORIGIN_TIME") + pcp_start_time = os.getenv("PCP_START_TIME") + pcp_align_time = os.getenv("PCP_ALIGN_TIME") + pcp_timezone = os.getenv("PCP_TIMEZONE") + pcp_hostzone = os.getenv("PCP_HOSTZONE") + pcp_debug = os.getenv("PCP_DEBUG") + + if pcp_archive is not None: + self.context_type = PM_CONTEXT_ARCHIVE + if pcp_origin is None and pcp_start_time is None: + pcp_origin = "-0" # end of archive + self.source = pcp_archive + else: + self.context_type = PM_CONTEXT_HOST + if pcp_host is not None: + self.source = pcp_host + else: + self.source = "localhost" + + try: + self.pmfg = pmapi.fetchgroup(self.context_type, self.source) + self.context = self.pmfg.get_context() + if pcp_archive: + options = pmapi.pmOptions("a:A:O:S:D:zZ:") + optargv = ["pcp-ss", pcp_archive] + if pcp_debug: + optargv.append("-D%s" % pcp_debug) + if pcp_align_time: + optargv.append("-A%s" % pcp_align_time) + if pcp_timezone: + optargv.append("-Z%s" % pcp_timezone) + if pcp_hostzone: + optargv.append("-z") + if pcp_origin: + optargv.append("-O%s" % pcp_origin) + pmapi.pmContext.fromOptions(options, optargv) + origin = options.pmGetOptionOrigin() + self.context.pmSetMode(PM_MODE_INTERP, origin, 0) + elif pcp_start_time: + optargv.append("-S%s" % pcp_start_time) + pmapi.pmContext.fromOptions(options, optargv) + start = options.pmGetOptionStart() + self.context.pmSetMode(PM_MODE_INTERP, start, 0) + + except pmapi.pmErr as error: + sys.stderr.write("%s: %s '%s'\n" % (error.progname(), error.message(), self.source)) + return False + + # check network.persocket metrics are available + try: + self.context.pmLookupName((pmns + ".filter")) + except Exception: + if self.context_type == PM_CONTEXT_HOST: + msg = "on host %s.\nIs the 'sockets' PMDA installed and enabled? See pmdasockets(1)." % self.source + else: + msg = "in archive %s" % self.source + print("Error: metrics for '%s' not found %s" % (pmns, msg)) + return False + + return True + + def traverseCB(self, name): + if not name.endswith(".filter"): + self.metrics.append(name) + + def fetch(self): + """ fetch metrics and report as per given options """ + + # filter and timestamp + self.filter = self.pmfg.extend_item(pmns + ".filter") + self.timestamp = self.pmfg.extend_timestamp() + + self.context.pmTraversePMNS(pmns, self.traverseCB) + self.pmids = self.context.pmLookupName(self.metrics) + descs = self.context.pmLookupDescs(self.pmids) + + # Create metrics dict keyed by metric name (without pmns prefix). + nmetrics = len(self.metrics) + for i in range (0, nmetrics): + pmnsname = self.metrics[i] + name = remove_prefix(pmnsname, pmns + ".") + try: + # do not want rate conversion, so use "instant" scale and only one fetch + self.descsD[name] = descs[i] + self.metricsD[name] = self.pmfg.extend_indom(pmnsname, + descs[i].contents.type, scale="instant", maxnum=10000) + except Exception as e: + print("Warning: Failed to add %s to fetch group: %s" % (name, e)) + + # fetch the lot + try: + self.pmfg.fetch() + except Exception as e: + print("Error: fetch failed: %s" % e) + sys.exit(1) + + # extract instances and values + for name in self.metricsD: + try: + instvalsD = {} + # walk the instances in the fetch group for this metric + for inst, iname, value in self.metricsD[name](): + self.instD[inst] = iname + try: + instvalsD[inst] = value() + except Exception as e: + print("Error: value() failed for metric %s, inst %d, iname %s: %s" % (name, inst, iname, e)) + self.valuesD[name] = instvalsD + except Exception as e: + pass # instance went away, socket probably closed + + def strfield(self, fmt, metric, inst, default=""): + """ return formatted field, if metric and inst are available else default string """ + try: + s = self.valuesD[metric][inst] + if s is not None: + return fmt % s + except: + pass + return fmt % default + + def intfield(self, fmt, metric, inst, default=0): + """ return formatted field, if metric and inst are available else default """ + try: + s = self.valuesD[metric][inst] + if s is not None: + return fmt % s + except: + pass + return fmt % default + + def boolfield(self, field, metric, inst, default=""): + """ return field if metric and inst are available and non-zero """ + try: + s = self.valuesD[metric][inst] + if s is not None and s != 0: + return field + except: + pass + return default + + def filter_netid(self, inst): + """ filter on netid and -t, -u and -x cmdline options """ + ret = False + netid = self.valuesD["netid"][inst] + if self.args.tcp and netid == "tcp": + ret = True + elif self.args.udp and netid == "udp": + ret = True + elif self.args.unix and netid == "unix": + ret = True + elif self.args.raw and netid == "raw": + ret = True + return ret + + def filter_listening(self, inst): + """ filter on tcp state """ + if self.args.all: + return True + netid = self.valuesD["netid"][inst] + state = self.valuesD["state"][inst] + if self.args.listening: + if state != "LISTEN" and netid in ("tcp", "tcp6"): + return False + return True + + def report(self): + """ output report based on cmdline options """ + if not self.args.noheader: # -H flag + print("# Time: %s Filter: %s" % (self.timestamp(), self.filter())) + print("Netid State Recv-Q Send-Q %25s %-25s Process" % ("Local Address:Port", "Peer Address:Port")) + for inst in self.instD: + if not self.filter_netid(inst) or not self.filter_listening(inst): + continue + out = "" + out += self.strfield("%-6s", "netid", inst) + out += self.strfield("%-9s", "state", inst, "-") + out += self.strfield("%6u", "recvq", inst, 0) + out += self.strfield("%6u", "sendq", inst, 0) + out += self.strfield("%26s ", "src", inst) + out += self.strfield("%-26s", "dst", inst) + + if self.args.options: # -o --options flag + m = self.valuesD["timer.str"][inst] + if m is not None and len(m) > 0: + out += " timer(%s)" % m + + if self.args.extended: # -e --extended flag + out += self.strfield(" uid:%d", "uid", inst, 0) + out += self.strfield(" inode:%lu", "inode", inst, 0) + out += self.strfield(" sk:%x", "sk", inst, 0) + out += self.strfield(" cgroup:%s", "cgroup", inst) + if self.valuesD["v6only"][inst] != 0: + out += " v6only:%d" % self.valuesD["v6only"][inst] + out += " <->" + + if not self.args.oneline and (self.args.memory or self.args.info): + out += "\n" + + if self.args.memory: # -m --memory flag + m = self.valuesD["skmem.str"][inst] + if m is not None and len(m) > 0: + out += " skmem(%s)" % m + + if self.args.info: # -i --info flag + out += self.boolfield(" ts", "ts", inst) + out += self.boolfield(" sack", "sack", inst) + # TODO ecn, ecnseen, fastopen + out += self.boolfield(" cubic", "cubic", inst) + out += self.strfield(" wscale:%s", "wscale.str", inst) + # TODO rto, backoff + out += self.strfield(" rtt:%s", "round_trip.str", inst) + out += self.strfield(" ato:%.0lf", "ato", inst, 0.0) + out += self.strfield(" mss:%d", "mss", inst, 0) + out += self.strfield(" cwnd:%d", "cwnd", inst, 0) + out += self.strfield(" pmtu:%d", "pmtu", inst, 0) + out += self.strfield(" ssthresh:%d", "ssthresh", inst, 0) + out += self.strfield(" bytes_sent:%lu", "bytes_sent", inst, 0) + out += self.strfield(" bytes_acked:%lu", "bytes_acked", inst, 0) + out += self.strfield(" bytes_received:%lu", "bytes_received", inst, 0) + out += self.strfield(" segs_out:%lu", "segs_out", inst, 0) + out += self.strfield(" segs_in:%lu", "segs_in", inst, 0) + out += self.strfield(" send %.0lfbps", "send", inst, 0) + out += self.strfield(" lastsnd:%.0lf", "lastsnd", inst, 0.0) + out += self.strfield(" lastrcv:%.0lf", "lastrcv", inst, 0.0) + out += self.strfield(" lastack:%.0lf", "lastack", inst, 0.0) + out += self.strfield(" pacing_rate %.0lfbps", "pacing_rate", inst, 0.0) + out += self.strfield(" delivery_rate %.0lfbps", "delivery_rate", inst, 0.0) + # TODO max_pacing_rate + out += self.strfield(" rcv_space:%lu", "rcv_space", inst, 0) + # TODO tcp-ulp-mptcp + # TODO token: + # TODO seq: + # TODO sfseq: + # TODO ssnoff + + print(out) + +if __name__ == '__main__': + try: + ss = SS() + if not ss.connect(): + # failed to connect or metrics not found - error already reported. + sys.exit(1) + ss.fetch() + ss.report() + except pmapi.pmErr as error: + if error.args[0] == PM_ERR_EOL: + sys.exit(0) + sys.stderr.write('%s: %s\n' % (error.progname(), error.message())) + sys.exit(1) + except pmapi.pmUsageErr as usage: + usage.message() + sys.exit(1) + except IOError as error: + if error.errno != errno.EPIPE: + sys.stderr.write("Error: %s\n" % str(error)) + sys.exit(1) + except KeyboardInterrupt: + sys.stdout.write("\n") diff -Nru pcp-5.3.1/src/pcp/tapestat/pcp-tapestat.1 pcp-5.3.2/src/pcp/tapestat/pcp-tapestat.1 --- pcp-5.3.1/src/pcp/tapestat/pcp-tapestat.1 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/pcp/tapestat/pcp-tapestat.1 2021-07-30 04:05:06.000000000 +0000 @@ -30,23 +30,36 @@ When invoked via the .BR pcp (1) command, the +.I "pcp options" +.hy 0 +.BR \-A /\c +.BR \-\-align , .BR \-a /\c .BR \-\-archive , .BR \-h /\c .BR \-\-host , .BR \-O /\c .BR \-\-origin , +.BR \-S /\c +.BR \-\-start , .BR \-s /\c .BR \-\-samples , .BR \-t /\c .BR \-\-interval , +.BR \-T /\c +.BR \-\-finish , +.BR \-V /\c +.BR \-\-version , .BR \-Z /\c .BR \-\-timezone -and several other -.I pcp options +and +.BR \-z /\c +.BR \-\-hostzone become indirectly available; refer to .BR PCPIntro (1) for a complete description of these options. +.br +.hy 0 .PP The additional command line options available for .B pcp-tapestat @@ -166,6 +179,9 @@ .B \-a must also be specified. .TP +\fB\-V\fR, \fB\-\-version\fR +Display version number and exit. +.TP \f3\-x\f1 \f2comma-separated-options\f1 Specifies a comma-separated list of one or more extended reporting options as follows: diff -Nru pcp-5.3.1/src/pmcd_wait/pmcd_wait.c pcp-5.3.2/src/pmcd_wait/pmcd_wait.c --- pcp-5.3.1/src/pmcd_wait/pmcd_wait.c 2018-11-16 06:44:22.000000000 +0000 +++ pcp-5.3.2/src/pmcd_wait/pmcd_wait.c 2021-07-30 04:05:06.000000000 +0000 @@ -34,6 +34,7 @@ { "host", 1, 'h', "HOST", "wait for PMCD on host" }, { "interval", 1, 't', "TIME", "maximum interval to wait for PMCD [default 60 seconds]" }, { "verbose", 0, 'v', 0, "turn on output messages" }, + PMOPT_HELP, PMAPI_OPTIONS_END }; diff -Nru pcp-5.3.1/src/pmclient/pmclient.c pcp-5.3.2/src/pmclient/pmclient.c --- pcp-5.3.1/src/pmclient/pmclient.c 2019-10-11 02:20:53.000000000 +0000 +++ pcp-5.3.2/src/pmclient/pmclient.c 2021-07-30 04:05:06.000000000 +0000 @@ -20,7 +20,21 @@ #include "pmnsmap.h" pmLongOptions longopts[] = { - PMAPI_GENERAL_OPTIONS, + PMAPI_OPTIONS_HEADER("General options"), + PMOPT_ALIGN, + PMOPT_ARCHIVE, + PMOPT_DEBUG, + PMOPT_HOST, + PMOPT_NAMESPACE, + PMOPT_ORIGIN, + PMOPT_START, + PMOPT_SAMPLES, + PMOPT_FINISH, + PMOPT_INTERVAL, + PMOPT_TIMEZONE, + PMOPT_HOSTZONE, + PMOPT_VERSION, + PMOPT_HELP, PMAPI_OPTIONS_HEADER("Reporting options"), { "pause", 0, 'P', 0, "pause between updates for archive replay" }, PMAPI_OPTIONS_END diff -Nru pcp-5.3.1/src/pmdas/bcc/bcc.conf pcp-5.3.2/src/pmdas/bcc/bcc.conf --- pcp-5.3.1/src/pmdas/bcc/bcc.conf 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/bcc/bcc.conf 2021-06-15 01:03:49.000000000 +0000 @@ -427,19 +427,3 @@ cluster = 110 # Mandatory for now - https://github.com/iovisor/bcc/issues/1774 process = java - -# This module counts the allocated bytes per Java class -# java(1) must be started with -XX:+ExtendedDTraceProbes -# for this module to work. NB. This might introduce non-negligible overhead. -# -# Configuration options: -# Name - type - default -# -# frequency - int - unset : sample every Nth allocation, power of two -# jvm_path - string - /etc/alternatives/jre/lib/server/libjvm.so : path to libjvm.so (if no process) -# process - string - unset : list of names/pids or regex of processes to monitor -[usdt_jvm_alloc] -module = usdt_jvm_alloc -cluster = 120 -# Mandatory for now - https://github.com/iovisor/bcc/issues/1774 -process = java diff -Nru pcp-5.3.1/src/pmdas/bcc/modules/usdt_jvm_alloc.bpf pcp-5.3.2/src/pmdas/bcc/modules/usdt_jvm_alloc.bpf --- pcp-5.3.1/src/pmdas/bcc/modules/usdt_jvm_alloc.bpf 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/bcc/modules/usdt_jvm_alloc.bpf 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -// Copyright (C) 2018 Marko Myllynen -// Licensed under the Apache License, Version 2.0 (the "License") - -#include - -#define JVM_WORDSIZE N - -struct key_t { - char name[128]; -}; - -BPF_HASH(classes, struct key_t, u64, 16384); -BPF_HASH(samples, u64, u64, 1); - -int trace_jvm_object_alloc(struct pt_regs *ctx, long tid, char *name, int nlen, int size) { - u64 zero = 0, *val; - - //FILTER_INIT - //FILTER_SAMPLE - - struct key_t key = {}; - bpf_probe_read(&key.name, sizeof(key.name), (void *)PT_REGS_PARM3(ctx)); - long alloc = size * JVM_WORDSIZE; - - val = classes.lookup_or_init(&key, &zero); - if (val) { - (*val) += alloc; - } - - return 0; -} diff -Nru pcp-5.3.1/src/pmdas/bcc/modules/usdt_jvm_alloc.python pcp-5.3.2/src/pmdas/bcc/modules/usdt_jvm_alloc.python --- pcp-5.3.1/src/pmdas/bcc/modules/usdt_jvm_alloc.python 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/bcc/modules/usdt_jvm_alloc.python 1970-01-01 00:00:00.000000000 +0000 @@ -1,155 +0,0 @@ -# -# Copyright (C) 2018 Marko Myllynen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -""" PCP BCC PMDA USDT JVM allocation profile module """ - -# pylint: disable=invalid-name, too-many-instance-attributes - -from platform import architecture -from ctypes import c_int -from os import path - -from bcc import BPF, USDT - -from pcp.pmapi import pmUnits -from cpmapi import PM_TYPE_U64, PM_SEM_COUNTER, PM_SPACE_BYTE -from cpmda import PMDA_FETCH_NOVALUES - -from modules.pcpbcc import PCPBCCBase - -# -# BPF program -# -bpf_src = "modules/usdt_jvm_alloc.bpf" - -# -# PCP BCC PMDA constants -# -MODULE = 'usdt_jvm_alloc' -METRIC = 'usdt.jvm.alloc' -units_bytes = pmUnits(1, 0, 0, PM_SPACE_BYTE, 0, 0) - -# -# PCP BCC Module -# -class PCPBCCModule(PCPBCCBase): - """ PCP BCC USDT JVM allocations module """ - def __init__(self, config, log, err, proc_refresh): - """ Constructor """ - PCPBCCBase.__init__(self, MODULE, config, log, err) - - self.pid = None - self.proc_filter = None - self.proc_refresh = proc_refresh - - self.cache = None - self.freq = 0 - self.jvm_path = "/etc/alternatives/jre/lib/server/libjvm.so" - self.usdt_contexts = [] - - for opt in self.config.options(MODULE): - if opt == 'frequency': - self.freq = int(self.config.get(MODULE, opt)) - if self.freq and self.freq & (self.freq - 1): - raise RuntimeError("Frequency is not power of two.") - if opt == 'jvm_path': - self.jvm_path = self.config.get(MODULE, opt) - if opt == 'process': - self.proc_filter = self.config.get(MODULE, opt) - self.update_pids(self.get_proc_info(self.proc_filter)) - - if not self.proc_filter: - # https://github.com/iovisor/bcc/issues/1774 - raise RuntimeError("Process filter is mandatory.") - - self.log("Initialized.") - - def metrics(self): - """ Get metric definitions """ - name = METRIC - self.items.append( - # Name - reserved - type - semantics - units - help - (name, None, PM_TYPE_U64, PM_SEM_COUNTER, units_bytes, 'alloc'), - ) - return True, self.items - - def reset_cache(self): - """ Reset internal cache """ - self.cache = {} - - def undef_cache(self): - """ Undefine internal cache """ - self.cache = None - - def compile(self): - """ Compile BPF """ - try: - if not self.pid and self.proc_filter and not self.proc_refresh: - # https://github.com/iovisor/bcc/issues/1774 - raise RuntimeError("No process to attach found.") - - if not self.bpf_text: - with open(path.dirname(__file__) + '/../' + bpf_src) as src: - self.bpf_text = src.read() - - if self.freq: - init_filter = "u64 *count = samples.lookup_or_init(&zero, &zero);" - sample_filter = "if (++(*count) & %d) return 0;" % (self.freq - 1) - self.bpf_text = self.bpf_text.replace("//FILTER_INIT", init_filter) - self.bpf_text = self.bpf_text.replace("//FILTER_SAMPLE", sample_filter) - if architecture()[0] == "64bit": - self.bpf_text = self.bpf_text.replace("JVM_WORDSIZE N", "JVM_WORDSIZE 8") - else: - self.bpf_text = self.bpf_text.replace("JVM_WORDSIZE N", "JVM_WORDSIZE 4") - - if not self.pid and self.proc_filter and self.proc_refresh: - self.log("No process to attach found, activation postponed.") - return - - self.usdt_contexts = [] - usdt = USDT(pid=self.pid) - usdt.enable_probe("object__alloc", "trace_jvm_object_alloc") - self.usdt_contexts.append(usdt) - - if self.debug: - self.log("BPF to be compiled:\n" + self.bpf_text.strip()) - - self.reset_cache() - self.bpf = BPF(text=self.bpf_text, usdt_contexts=self.usdt_contexts) - self.log("Compiled.") - except Exception as error: # pylint: disable=broad-except - self.bpf = None - self.undef_cache() - self.err(str(error)) - self.err("Module NOT active!") - raise - - def refresh(self): - """ Refresh BPF data """ - if self.bpf is None: - return None - - for k, v in self.bpf["classes"].items(): - key = self.parse_inst_name(k.name.decode("ASCII", "replace")) - self.cache[key] = v.value - self.insts[key] = c_int(1) - - return self.insts - - def bpfdata(self, item, inst): - """ Return BPF data as PCP metric value """ - try: - key = self.pmdaIndom.inst_name_lookup(inst) - return [self.cache[key], 1] - except Exception: # pylint: disable=broad-except - return [PMDA_FETCH_NOVALUES, 0] diff -Nru pcp-5.3.1/src/pmdas/denki/denki.c pcp-5.3.2/src/pmdas/denki/denki.c --- pcp-5.3.1/src/pmdas/denki/denki.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/denki.c 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,639 @@ +/* + * Denki (電気, Japanese for 'electricity'), PMDA for electricity related + * metrics + * + * Copyright (c) 2012-2014,2017,2021 Red Hat. + * Copyright (c) 1995,2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * - adaptions to pmda denki: Christian Horn + * - rapl readcode from rapl-plot, Vince Weaver -- vincent.weaver @ maine.edu + * ( https://github.com/deater/uarch-configure / GPL-2.0 License ) + */ + +#include +#include +#include "domain.h" +#include +#include + +#define NUM_RAPL_DOMAINS 10 +#define MAX_PACKAGES 16 +#define MAX_CPUS 2147483648 + +static int has_rapl, has_bat; /* Has the system rapl or battery? */ + +static int total_cores, total_packages; /* detected cpu cores and rapl packages */ +static int package_map[MAX_PACKAGES]; +char event_names[MAX_PACKAGES][NUM_RAPL_DOMAINS][256]; /* rapl domain names */ +long long raplvars[MAX_PACKAGES][NUM_RAPL_DOMAINS]; /* rapl domain readings */ +static int valid[MAX_PACKAGES][NUM_RAPL_DOMAINS]; /* Is this rapl domain valid? */ +static char filenames[MAX_PACKAGES][NUM_RAPL_DOMAINS][256]; /* pathes to the rapl domains */ + +static int detect_rapl_packages(void); /* detect RAPL packages, cpu cores */ +static int detect_rapl_domains(void); /* detect RAPL domains */ +static int read_rapl(void); /* read RAPL values */ +static int read_battery(void); /* read battery values */ +static int compute_energy_rate(void); /* compute discharge rate from BAT0 values */ +long long lookup_rapl_dom(int); /* map instance to 2-dimensional domain matrix */ + +static char rootpath[512] = "/"; /* path to rootpath, gets changed for regression tests */ + +/* detect RAPL packages and cpu cores */ +static int detect_rapl_packages(void) { + + char filename[MAXPATHLEN]; + FILE *fff; + int package,i; + + for(i=0;i= MAX_PACKAGES) { + pmNotifyErr(LOG_ERR, "package number %d invalid, range 0-%u", package, MAX_PACKAGES); + continue; + } + + if (package_map[package]==-1) { + total_packages++; + package_map[package]=i; + } + } + + total_cores=i; + + printf("\tDetected %d cores in %d packages\n\n", + total_cores,total_packages); + + return 0; +} + +static int detect_rapl_domains(void) { + char basename[MAX_PACKAGES][256]; + char tempfile[256]; + int i,pkg; + FILE *fff; + + for(pkg=0;pkg= battery_comp_rate ) { + + // computing how many Wh were used up in battery_comp_rate + energy_diff_d = (energy_now_old - energy_now)/1000000.0; + + // computing how many W would be used in 1h + energy_rate_d = energy_diff_d * 3600 / battery_comp_rate; + // pmNotifyErr(LOG_DEBUG, "DENKI: new computation, currently %f W/h are consumed",energy_rate_d); + + secondsold = secondsnow; + energy_now_old = energy_now; + } + + return 0; +} + +/* + * Denki PMDA metrics + * + * denki.rapl.rate - usage rates from RAPL + * denki.rapl.raw - plain raw values from RAPL + * denki.bat.energy_now_raw - BAT0/energy_now raw reading, + * current battery charge in Wh + * denki.bat.energy_now_rate - BAT0, current rate of discharging if postive value, + * or current charging rate if negative value + * denki.bat.power_now - BAT0/power_now raw reading + */ + +/* + * instance domains + * These use the more recent pmdaCache methods, but also appear in + * indomtab[] so that the initialization of the pmInDom and the pmDescs + * in metrictab[] is completed by pmdaInit + */ + +static pmdaIndom indomtab[] = { +#define RAPLRATE_INDOM 0 /* serial number for "rapl.rate" instance domain */ + { RAPLRATE_INDOM, 0, NULL }, +#define RAPLRAW_INDOM 1 /* serial number for "rapl.raw" instance domain */ + { RAPLRAW_INDOM, 0, NULL } +}; + +/* this is merely a convenience */ +static pmInDom *rate_indom = &indomtab[RAPLRATE_INDOM].it_indom; +static pmInDom *raw_indom = &indomtab[RAPLRAW_INDOM].it_indom; + +/* + * All metrics supported in this PMDA - one table entry for each. + */ + +static pmdaMetric metrictab[] = { +/* rapl.rate */ + { NULL, + { PMDA_PMID(0,0), PM_TYPE_U32, RAPLRATE_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,0,0,0,0) }, }, +/* rapl.raw */ + { NULL, + { PMDA_PMID(0,1), PM_TYPE_U32, RAPLRAW_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, }, +/* energy_now_raw */ + { NULL, + { PMDA_PMID(1,0), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, }, +/* energy_now_rate */ + { NULL, + { PMDA_PMID(1,1), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, }, +/* power_now */ + { NULL, + { PMDA_PMID(1,2), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) }, } +}; + +static int isDSO = 1; /* =0 I am a daemon */ +static char *username; + +/* data and function prototypes for dynamic instance domain handling */ +static struct raplratedom { + int inst_id; + char *rapl_name; +} raplratedoms[] = { + { 1, "temp" } +}; +static struct raplrawdom { + int inst_id; + char *rapl_name; +} raplrawdoms[] = { + { 1, "temp" } +}; + +static void denki_rapl_clear(void); +static void denki_rapl_init(void); +static void denki_rapl_check(void); + +static char mypath[MAXPATHLEN]; + +/* command line option handling - both short and long options */ +static pmLongOptions longopts[] = { + PMDA_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, + PMDAOPT_DOMAIN, + PMDAOPT_LOGFILE, + { "rootpath", 1, 'r', "ROOTPATH", "use non-default rootpath instead of /" }, + PMDAOPT_USERNAME, + PMOPT_HELP, + PMDA_OPTIONS_TEXT("\nExactly one of the following options may appear:"), + PMDAOPT_INET, + PMDAOPT_PIPE, + PMDAOPT_UNIX, + PMDAOPT_IPV6, + PMDA_OPTIONS_END +}; +static pmdaOptions opts = { + .short_options = "D:d:i:l:r:pu:U:6:?", + .long_options = longopts, +}; + +/* + * Our rapl readings are in a 2-dimensional array, map them here + * to the 1-dimentional indom numbers + */ +long long lookup_rapl_dom(int instance) { + + int pkg,dom,domcnt=0; + + for(pkg=0;pkgm_desc.pmid); + unsigned int item = pmID_item(mdesc->m_desc.pmid); + + if (inst != PM_IN_NULL && + !((cluster == 0 && item == 0) || + (cluster == 0 && item == 1))) + return PM_ERR_INST; + + if (cluster == 0) { + if (item == 0) { /* rapl.rate */ + struct raplratedom *tsp; + if ((sts = pmdaCacheLookup(*rate_indom, inst, NULL, (void *)&tsp)) != PMDA_CACHE_ACTIVE) { + if (sts < 0) + pmNotifyErr(LOG_ERR, "pmdaCacheLookup failed: inst=%d: %s", inst, pmErrStr(sts)); + return PM_ERR_INST; + } + atom->ul = lookup_rapl_dom(inst)/1000000; + } + else if (item == 1) { /* rapl.raw */ + struct raplrawdom *tsp; + if ((sts = pmdaCacheLookup(*raw_indom, inst, NULL, (void *)&tsp)) != PMDA_CACHE_ACTIVE) { + if (sts < 0) + pmNotifyErr(LOG_ERR, "pmdaCacheLookup failed: inst=%d: %s", inst, pmErrStr(sts)); + return PM_ERR_INST; + } + atom->ul = lookup_rapl_dom(inst)/1000000; + } + } + else if (cluster == 1) { + if (item == 0) /* denki.energy_now_raw */ + atom->d = energy_now/1000000.0; + else if (item == 1) /* denki.energy_now_rate */ + atom->d = energy_rate_d; + else if (item == 2) /* denki.power_now */ + atom->d = power_now/1000000.0; + else + return PM_ERR_PMID; + } + else + return PM_ERR_PMID; + + return PMDA_FETCH_STATIC; +} + +/* + * This routine is called once for each pmFetch(3) operation, so is a + * good place to do once-per-fetch functions, such as value caching or + * instance domain evaluation (as we do in denki_rapl_check). + */ +static int +denki_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) +{ + if (has_rapl) + read_rapl(); + if (has_bat) { + read_battery(); + compute_energy_rate(); + } + return pmdaFetch(numpmid, pmidlist, resp, pmda); +} + +/* + * wrapper for pmdaInstance which we need to ensure is called with the + * _current_ contents of the rapl.rate/rapl.raw instance domain. + */ +static int +denki_instance(pmInDom indom, int foo, char *bar, pmInResult **iresp, pmdaExt *pmda) +{ + // We could call the check each fetch cycle here, but rapl + // should not change dynamically, so we can spare those cycles. + // denki_rapl_check(); + return pmdaInstance(indom, foo, bar, iresp, pmda); +} + +/* + * Initialize the instances + */ +static void +denki_rapl_check(void) +{ + denki_rapl_clear(); + denki_rapl_init(); +} + +/* + * clear the rapl.rate and rapl.raw metric instance domains + */ +static void +denki_rapl_clear(void) +{ + int sts; + + sts = pmdaCacheOp(*rate_indom, PMDA_CACHE_INACTIVE); + if (sts < 0) + pmNotifyErr(LOG_ERR, "pmdaCacheOp(INACTIVE) failed: indom=%s: %s", + pmInDomStr(*rate_indom), pmErrStr(sts)); + + sts = pmdaCacheOp(*raw_indom, PMDA_CACHE_INACTIVE); + if (sts < 0) + pmNotifyErr(LOG_ERR, "pmdaCacheOp(INACTIVE) failed: indom=%s: %s", + pmInDomStr(*raw_indom), pmErrStr(sts)); +#ifdef DESPERATE + __pmdaCacheDump(stderr, *now_indom, 1); +#endif +} + +/* + * register RAPL cores as indoms + */ +static void +denki_rapl_init(void) +{ + int sts; + int dom,pkg,domcnt=0; + char tmp[BUFSIZ]; + + for(pkg=0;pkg1 rapl packages, + we prepend the rapl-domain counter */ + if (total_packages > 1) + pmsprintf(tmp,sizeof(tmp),"%d-%s",pkg,event_names[pkg][dom]); + else + pmsprintf(tmp,sizeof(tmp),"%s",event_names[pkg][dom]); + + /* rapl.rate */ + sts = pmdaCacheStore(*rate_indom, PMDA_CACHE_ADD, tmp, &raplratedoms[domcnt]); + if (sts < 0) { + pmNotifyErr(LOG_ERR, "pmdaCacheStore failed: %s", pmErrStr(sts)); + return; + } + /* rapl.raw */ + sts = pmdaCacheStore(*raw_indom, PMDA_CACHE_ADD, tmp, &raplrawdoms[domcnt]); + if (sts < 0) { + pmNotifyErr(LOG_ERR, "pmdaCacheStore failed: %s", pmErrStr(sts)); + return; + } + domcnt++; + } + } + } + +#ifdef DESPERATE + __pmdaCacheDump(stderr, *now_indom, 1); +#endif + if (pmdaCacheOp(*rate_indom, PMDA_CACHE_SIZE_ACTIVE) < 1) + pmNotifyErr(LOG_WARNING, "\"rapl.rate\" instance domain is empty"); + if (pmdaCacheOp(*raw_indom, PMDA_CACHE_SIZE_ACTIVE) < 1) + pmNotifyErr(LOG_WARNING, "\"rapl.raw\" instance domain is empty"); +} + +static int +denki_label(int ident, int type, pmLabelSet **lpp, pmdaExt *pmda) +{ + int serial; + + switch (type) { + case PM_LABEL_DOMAIN: + pmdaAddLabels(lpp, "{\"role\":\"testing\"}"); + break; + case PM_LABEL_INDOM: + serial = pmInDom_serial((pmInDom)ident); + if (serial == RAPLRATE_INDOM) { + pmdaAddLabels(lpp, "{\"indom_name\":\"raplrate\"}"); + } + if (serial == RAPLRAW_INDOM) { + pmdaAddLabels(lpp, "{\"indom_name\":\"raplraw\"}"); + } + break; + case PM_LABEL_CLUSTER: + case PM_LABEL_ITEM: + /* no labels to add for these types, fall through */ + default: + break; + } + return pmdaLabel(ident, type, lpp, pmda); +} + +static int +denki_labelCallBack(pmInDom indom, unsigned int inst, pmLabelSet **lp) +{ + struct raplratedom *tsp; + + if (pmdaCacheLookup(indom, inst, NULL, (void *)&tsp) != PMDA_CACHE_ACTIVE) + return 0; + + if (pmInDom_serial(indom) == RAPLRATE_INDOM) + return pmdaAddLabels(lp, "{\"units\":\"%s\"}", tsp->rapl_name); + if (pmInDom_serial(indom) == RAPLRAW_INDOM) + return pmdaAddLabels(lp, "{\"units\":\"%s\"}", tsp->rapl_name); + return 0; +} + +/* + * Initialise the agent (both daemon and DSO). + */ +void +denki_init(pmdaInterface *dp) +{ + if (isDSO) { + int sep = pmPathSeparator(); + pmsprintf(mypath, sizeof(mypath), "%s%c" "denki" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDSO(dp, PMDA_INTERFACE_7, "denki DSO", mypath); + } else { + pmSetProcessIdentity(username); + } + + if (dp->status != 0) + return; + + dp->version.any.fetch = denki_fetch; + dp->version.any.instance = denki_instance; + dp->version.seven.label = denki_label; + + pmdaSetFetchCallBack(dp, denki_fetchCallBack); + pmdaSetLabelCallBack(dp, denki_labelCallBack); + + pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), metrictab, + sizeof(metrictab)/sizeof(metrictab[0])); +} + +/* + * Set up the agent if running as a daemon. + */ +int +main(int argc, char **argv) +{ + char filename[BUFSIZ]; + int c,sep = pmPathSeparator(); + DIR *directory; + pmdaInterface dispatch; + + isDSO = 0; + pmSetProgname(argv[0]); + pmGetUsername(&username); + + pmsprintf(mypath, sizeof(mypath), "%s%c" "denki" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDaemon(&dispatch, PMDA_INTERFACE_7, pmGetProgname(), DENKI, + "denki.log", mypath); + + while ((c = pmdaGetOptions(argc, argv, &opts, &dispatch)) != EOF) { + switch (c) { + case 'r': + strncpy(rootpath, opts.optarg, sizeof(rootpath)); + rootpath[sizeof(rootpath)-1] = '\0'; + break; + } + } + + if (opts.errors) { + pmdaUsageMessage(&opts); + exit(1); + } + if (opts.username) + username = opts.username; + + pmdaOpenLog(&dispatch); + pmdaConnect(&dispatch); + denki_init(&dispatch); + + pmNotifyErr(LOG_DEBUG, "configured to use this rootpath: %s", rootpath); + + pmsprintf(filename,sizeof(filename),"%s/sys/class/powercap/intel-rapl",rootpath); + directory = opendir(filename); + if ( directory == NULL ) + pmNotifyErr(LOG_DEBUG, "RAPL not detected"); + else { + has_rapl=1; + detect_rapl_packages(); + pmNotifyErr(LOG_DEBUG, "RAPL detected, with %d cpu-cores and %d rapl-packages.", total_cores, total_packages); + detect_rapl_domains(); + denki_rapl_check(); // now we register the found rapl indoms + } + closedir(directory); + + pmsprintf(filename,sizeof(filename),"%s/sys/class/power_supply/BAT0",rootpath); + directory = opendir(filename); + if ( directory == NULL ) + pmNotifyErr(LOG_DEBUG, "detected no battery"); + else { + pmNotifyErr(LOG_DEBUG, "detected battery"); + has_bat=1; + } + + pmdaMain(&dispatch); + + exit(0); +} diff -Nru pcp-5.3.1/src/pmdas/denki/domain.h pcp-5.3.2/src/pmdas/denki/domain.h --- pcp-5.3.1/src/pmdas/denki/domain.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/domain.h 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,4 @@ +/* + * built from ../../pmns/stdpmid + */ +#define DENKI 156 diff -Nru pcp-5.3.1/src/pmdas/denki/.gitignore pcp-5.3.2/src/pmdas/denki/.gitignore --- pcp-5.3.1/src/pmdas/denki/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/.gitignore 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,6 @@ +domain.h +exports +pmdadenki +pmda_denki.so +help.dir +help.pag diff -Nru pcp-5.3.1/src/pmdas/denki/GNUmakefile pcp-5.3.2/src/pmdas/denki/GNUmakefile --- pcp-5.3.1/src/pmdas/denki/GNUmakefile 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,82 @@ +# +# Copyright (c) 2018,2020-2021 Red Hat. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs + +IAM = denki +DOMAIN = DENKI +CMDTARGET = pmda$(IAM) +LIBTARGET = pmda_$(IAM).$(DSOSUFFIX) +PMDAINIT = $(IAM)_init + +PMDAADMDIR = $(PCP_PMDASADM_DIR)/$(IAM) +PMDATMPDIR = $(PCP_PMDAS_DIR)/$(IAM) + +LLDLIBS = $(PCP_PMDALIB) +LCFLAGS = $(INVISIBILITY) + +CFILES = denki.c + +SCRIPTS = Install Remove +VERSION_SCRIPT = exports +HELPTARGETS = help.dir help.pag +LDIRT = $(HELPTARGETS) domain.h $(VERSION_SCRIPT) + +MAN_SECTION = 1 +MAN_PAGES = pmda$(IAM).$(MAN_SECTION) +MAN_DEST = $(PCP_MAN_DIR)/man$(MAN_SECTION) + +default: build-me + +include $(BUILDRULES) + +ifeq "$(TARGET_OS)" "linux" +build-me: $(LIBTARGET) $(CMDTARGET) $(HELPTARGETS) + +install: default + $(INSTALL) -m 755 -d $(PMDAADMDIR) + $(INSTALL) -m 755 -d $(PMDATMPDIR) + $(INSTALL) -m 644 -t $(PMDATMPDIR) domain.h help help.dir help.pag $(PMDAADMDIR) + $(INSTALL) -m 644 -t $(PMDATMPDIR) root root_denki README $(PMDAADMDIR) + $(INSTALL) -m 755 -t $(PMDATMPDIR) $(LIBTARGET) $(CMDTARGET) $(SCRIPTS) $(PMDAADMDIR) + $(INSTALL) -m 644 -t $(PCP_PMNS_DIR)/root_denki root_denki $(PCP_PMNSADM_DIR)/root_denki + @$(INSTALL_MAN) +else +build-me: +install: +endif + +default_pcp : default + +install_pcp : install + +$(HELPTARGETS) : help + $(NEWHELP) -n root_denki -v 2 -o help < help + +$(VERSION_SCRIPT): + $(VERSION_SCRIPT_MAKERULE) + +domain.h: ../../pmns/stdpmid + $(DOMAIN_MAKERULE) + +$(OBJECTS): domain.h +pmda.o: $(VERSION_SCRIPT) +pmda.o: $(TOPDIR)/src/include/pcp/libpcp.h + +check:: $(CFILES) + $(CLINT) $^ + +check:: $(MAN_PAGES) + $(MANLINT) $^ diff -Nru pcp-5.3.1/src/pmdas/denki/help pcp-5.3.2/src/pmdas/denki/help --- pcp-5.3.1/src/pmdas/denki/help 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/help 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,52 @@ +# +# Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# denki PMDA help file in the ASCII format +# +# lines beginning with a # are ignored +# lines beginning @ introduce a new entry of the form +# @ metric_name oneline-text +# help text goes +# here over multiple lines +# ... +# +# the metric_name is decoded against the default PMNS -- as a special case, +# a name of the form NNN.MM (for numeric NNN and MM) is interpreted as an +# instance domain identification, and the text describes the instance domain +# +# blank lines before the @ line are ignored +# + +@ 156.0.0 denki.rapl.rate +Current electrical power consumption of Intel cpu components. +The rapl cores offered by the system are available as metric +instances. + +@ 156.0.1 denki.rapl.raw +Raw rapl values as reported by Intel cpus. These allow to +compute power consumption of longer running compute loads, with +higher accuracy. + +@ 156.1.0 denki.bat.energy_now_raw battery reported charge level +The current charge level as reported by the battery. This can +be used to calculate overall power consumption of longer running +compute loads, with high accuracy. + +@ 156.1.1 denki.bat.energy_now_rate calculated energy consumption +Systems current energy consumption, calculated by pmda-denki +from battery charge level. Only available while discharging. +Computed every 60 seconds. + +@ 156.1.2 denki.bat.power_now system calculated energy consumption +Systems current energy consumption, calculated by the system. +Only available while discharging, or charging the battery. diff -Nru pcp-5.3.1/src/pmdas/denki/Install pcp-5.3.2/src/pmdas/denki/Install --- pcp-5.3.1/src/pmdas/denki/Install 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/Install 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,43 @@ +#!/bin/sh +# +# Copyright (c) 2013 Red Hat. +# Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Install the denki PMDA and/or PMNS +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=denki +domain=156 + +dso_opt=false +socket_opt=false +pmns_source=root_denki + +# args="-U root -r " +args="-U root" + +# Set up the denki PMDA (domain 156) InDom cache +# +if [ -d $PCP_VAR_DIR/config/pmda ] +then + touch $PCP_VAR_DIR/config/pmda/$domain.1 + chown $PCP_USER:$PCP_GROUP $PCP_VAR_DIR/config/pmda/$domain.1 + chmod 644 $PCP_VAR_DIR/config/pmda/$domain.1 +fi + +pmdaSetup +pmdaInstall +exit diff -Nru pcp-5.3.1/src/pmdas/denki/pmdadenki.1 pcp-5.3.2/src/pmdas/denki/pmdadenki.1 --- pcp-5.3.1/src/pmdas/denki/pmdadenki.1 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/pmdadenki.1 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,119 @@ +'\"macro stdmacro +.\" +.\" Copyright (c) 2021 Red Hat. +.\" +.\" This program is free software; you can redistribute it and/or modify it +.\" under the terms of the GNU General Public License as published by the +.\" Free Software Foundation; either version 2 of the License, or (at your +.\" option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +.\" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +.\" for more details. +.\" +.TH PMDADENKI 1 "PCP" "Performance Co-Pilot" +.SH NAME +\f3pmdadenki\f1 \- metrics related to the systems electrical consumption +.SH SYNOPSIS +\f3$PCP_PMDAS_DIR/denki/pmdadenki\f1 +[\f3\-d\f1 \f2domain\f1] +[\f3\-l\f1 \f2logfile\f1] +.SH DESCRIPTION +.B pmdadenki +is a Performance Metrics Domain Agent (PMDA) which extracts +electricity related performance metrics. +.PP +Currently, metrics from RAPL (on Intel cpus) and battery +charge values are available, if supported by the hardware. +.PP +.B \-l +Location of the log file. By default, a log file named +.I denki.log +is written in the current directory of +.BR pmcd (1) +when +.B pmdadenki +is started, i.e. +.BR $PCP_LOG_DIR/pmcd . +If the log file cannot +be created or is not writable, output is written to the standard error instead. +.SH "INSTALLATION" +The +.B denki +PMDA is installed and available by default on Linux. +If you want to undo the installation, do the following as root: +.PP +.ft CW +.nf +.in +0.5i +# cd $PCP_PMDAS_DIR/denki +# ./Remove +.in +.fi +.ft 1 +.PP +If you want to establish access to the names, help text and values for the +denki metrics once more, after removal, do the following as root: +.PP +.ft CW +.nf +.in +0.5i +# cd $PCP_PMDAS_DIR/denki +# ./Install +.in +.fi +.ft 1 +.PP +.B pmdadenki +is launched by +.BR pmcd (1) +and should never be executed directly. +The Install and Remove scripts notify +.BR pmcd (1) +when the agent is installed or removed. +.SH "FILES" +.PD 0 +.TP 10 +.B $PCP_PMCDCONF_PATH +command line options used to launch +.B pmdadenki +.TP 10 +.B $PCP_PMDAS_DIR/denki/help +default help text file for the denki metrics +.TP 10 +.B $PCP_PMDAS_DIR/denki/Install +installation script for the +.B pmdadenki +agent +.TP 10 +.B $PCP_PMDAS_DIR/denki/Remove +undo installation script for the +.B pmdadenki +agent +.TP 10 +.B $PCP_LOG_DIR/pmcd/denki.log +default log file for error messages and other information from +.B pmdadenki +.PD +.SH "PCP ENVIRONMENT" +Environment variables with the prefix +.B PCP_ +are used to parameterize the file and directory names +used by PCP. +On each installation, the file +.I /etc/pcp.conf +contains the local values for these variables. +The +.B $PCP_CONF +variable may be used to specify an alternative +configuration file, +as described in +.BR pcp.conf (5). +.SH "SEE ALSO" +.BR PCPIntro (1), +.BR pmcd (1), +.BR denki/README file +.BR pcp.conf (5) +and +.BR pcp.env (5). diff -Nru pcp-5.3.1/src/pmdas/denki/pmns pcp-5.3.2/src/pmdas/denki/pmns --- pcp-5.3.1/src/pmdas/denki/pmns 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/pmns 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Metrics for denki PMDA + * + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +denki { + rapl + bat +} + +denki.rapl { + rate DENKI:0:0 + raw DENKI:0:1 +} +denki.bat { + energy_now_raw DENKI:1:0 + energy_now_rate DENKI:1:1 + power_now DENKI:1:2 +} diff -Nru pcp-5.3.1/src/pmdas/denki/README pcp-5.3.2/src/pmdas/denki/README --- pcp-5.3.1/src/pmdas/denki/README 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/README 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,120 @@ +Denki PMDA +=========== + +This is the PMDA providing metrics which are related to the systems +electricity. + +At the moment, metrics from 2 sources are available: + +- RAPL values, available on newer Intel CPUs. +- battery values + + +Metrics +======= + +The file ./help contains descriptions for all of the metrics exported +by this PMDA. + +Once the PMDA has been installed, the following command will list all +the available metrics and their explanatory "help" text: + + $ pminfo -fT denki + +Installation +============ + + + # cd $PCP_PMDAS_DIR/denki + + + Then simply use + + # ./Install + + + Watch the logfile: + + # less /var/log/pcp/pmcd/denki.log + + + Verify if the metrics which are available on the system appear: + + # pminfo -fF denki + # pmrep denki + +De-installation +=============== + + + Simply use + + # cd $PCP_PMDAS_DIR/denki + # ./Remove + +Troubleshooting +=============== + + + After installing or restarting the agent, the PMCD log file + ($PCP_LOG_DIR/pmcd/pmcd.log) and the PMDA log file + ($PCP_LOG_DIR/pmcd/denki.log) should be checked for any warnings + or errors. + +Usage scenarios/examples +======================== + + - denki.rapl.rate: + + If RAPL is available, denki.rapl.rate can give an estimation of + the current power consumption. On laptops, typically 4 RAPL + domains are available: + + inst [0 or "package-0"] - consumption of the other 3 domains + inst [1 or "core"] - cpus consumption + inst [2 or "uncore"] - typically GPU, if on motherboard + inst [3 or "dram"] - memory + + When accessed with 'pmrep denki.rapl.rate', these values can + be used to compare for example power consumption of various + webbrowsers while playing a video or webgl sites. One can + also verify if offloading to the GPU is working. + + On systems with multiple numa zones, also multiple RAPL + packages can be available, pmda-denki should properly deal + with these. For these, i.e. domains 0-package-0 and + 1-package-0 will become available as instances. + + - denki.rapl.raw: + + If RAPL is available, this provides the raw values from the + kernel. These can be utilized for more accurate power con- + sumption comparisons. Example workflow: + + 1) query the values, i.e. using 'pminfo denki.rapl.raw' + 2) run your workload + 3) query the current values again, use the values from 1) + and the time between 1) and 3) to compute the overall + consumption. + 4) Perform 1) to 3) again, with a different software or + a different software version. + + - denki.bat.energy_now_raw: + + If battery readings are available, this metric has the + current reading, so the charge level of the battery. + Battery readings are great for measuring overall system + consumption - RAPL is just covering some components. + The raw reading can like denki.rapl.raw be used to read + the current charge level at 2 points in time, do a work- + load in between, and compute the consumption. + + - denki.bat.energy_now_rate: + + If battery readings are available, this shows the rate + of discharging (positive value) or charging (negative + value) of the overall system. pmda-denki computes this + every 60 seconds, from the denki.bat.energy_now_raw + readings. + + - denki.bat.power_now: + + If battery readings are available, then this value + shows the current battery discharge rate, so also overall + system consumption. This is computed by firmware/driver, + and much more frequently updated than + denki.bat.energy_now_rate. diff -Nru pcp-5.3.1/src/pmdas/denki/Remove pcp-5.3.2/src/pmdas/denki/Remove --- pcp-5.3.1/src/pmdas/denki/Remove 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/Remove 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Remove the denki PMDA +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=denki +pmdaSetup +pmdaRemove +exit diff -Nru pcp-5.3.1/src/pmdas/denki/root pcp-5.3.2/src/pmdas/denki/root --- pcp-5.3.1/src/pmdas/denki/root 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/root 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,6 @@ +/* + * fake "root" for validating the local PMNS subtree + */ + +#include +#include "root_denki" diff -Nru pcp-5.3.1/src/pmdas/denki/root_denki pcp-5.3.2/src/pmdas/denki/root_denki --- pcp-5.3.1/src/pmdas/denki/root_denki 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/denki/root_denki 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018,2021 Red Hat. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DENKI +#define DENKI 156 +#endif + +root { + denki +} + +denki { + rapl + bat +} + +denki.rapl { + rate DENKI:0:0 + raw DENKI:0:1 +} +denki.bat { + energy_now_raw DENKI:1:0 + energy_now_rate DENKI:1:1 + power_now DENKI:1:2 +} diff -Nru pcp-5.3.1/src/pmdas/ds389/ds389.conf.example pcp-5.3.2/src/pmdas/ds389/ds389.conf.example --- pcp-5.3.1/src/pmdas/ds389/ds389.conf.example 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/ds389/ds389.conf.example 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +# +# pmdads389(1) configuration file +# + +# Bind password +our $bindpw = 'Manager12'; + +# Data clusters +%dclu = ( + # Must start from 4, 0-3 are reserved for default values + #'4' => ['0','cn=mycn','mycn.',$dfscope,$dffilter,$dattrs], +); + +# Additional attributes, ID (the first column) must match the one defined in %dclu +our @add_met = ( + #[4,0,$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','myattribute1'], + #[4,1,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'myattribute2'], + #[4,2,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'myattribute3'], +); diff -Nru pcp-5.3.1/src/pmdas/ds389/GNUmakefile pcp-5.3.2/src/pmdas/ds389/GNUmakefile --- pcp-5.3.1/src/pmdas/ds389/GNUmakefile 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/ds389/GNUmakefile 2021-06-15 01:03:49.000000000 +0000 @@ -1,16 +1,16 @@ # -# Copyright (c) 2014,2020 Red Hat. All Rights Reserved. -# +# Copyright (c) 2014,2020,2021 Red Hat. +# # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. -# +# # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. -# +# TOPDIR = ../../.. include $(TOPDIR)/src/include/builddefs @@ -33,7 +33,7 @@ $(INSTALL) -m 755 -d $(PMDAADMDIR) $(INSTALL) -m 755 -d $(PMDATMPDIR) $(INSTALL) -m 755 -t $(PMDATMPDIR) Install Remove $(PMDAADMDIR) - $(INSTALL) -m 644 -t $(PMDATMPDIR)/pmda$(IAM).pl pmda$(IAM).pl $(PMDAADMDIR)/pmda$(IAM).pl + $(INSTALL) -m 644 -t $(PMDATMPDIR) pmda$(IAM).pl $(IAM).conf.example $(PMDAADMDIR) @$(INSTALL_MAN) default_pcp : default diff -Nru pcp-5.3.1/src/pmdas/ds389/pmdads389.1 pcp-5.3.2/src/pmdas/ds389/pmdads389.1 --- pcp-5.3.1/src/pmdas/ds389/pmdads389.1 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/ds389/pmdads389.1 2021-06-15 01:03:49.000000000 +0000 @@ -1,6 +1,6 @@ '\"macro stdmacro .\" -.\" Copyright (c) 2014-2018 Red Hat. +.\" Copyright (c) 2014-2018,2021 Red Hat. .\" .\" This program is free software; you can redistribute it and/or modify it .\" under the terms of the GNU General Public License as published by the @@ -47,16 +47,21 @@ .IP \(bu bind password .IP \(bu -search scope +default search scope .IP \(bu -search base +default search base .IP \(bu -search filter +default search filter .IP \(bu query interval +.IP \(bu +List of sources +.IP \(bu +List of attributes to display for each source .RE .PD .PP +Please use the provided ds389.conf.example as a starting point. Once this is setup, you can access the names and values for the 389 DS performance metrics by doing the following as root: .sp 1 @@ -88,6 +93,9 @@ agent is installed or removed. .SH FILES .TP +.I \f(CW$PCP_PMDAS_DIR\fP/ds389/ds389.conf.example +example configuration file for the \fBpmdads389\fP agent +.TP .I \f(CW$PCP_PMDAS_DIR\fP/ds389/ds389.conf configuration file for the \fBpmdads389\fP agent .TP diff -Nru pcp-5.3.1/src/pmdas/ds389/pmdads389.pl pcp-5.3.2/src/pmdas/ds389/pmdads389.pl --- pcp-5.3.1/src/pmdas/ds389/pmdads389.pl 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/ds389/pmdads389.pl 2021-07-30 04:05:06.000000000 +0000 @@ -1,5 +1,6 @@ # # Copyright (C) 2014-2015 Marko Myllynen +# Copyright (C) 2021 Raul Mahiques # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -18,244 +19,452 @@ use POSIX; my $have_ldap = eval { - # check if we have LDAP - require Net::LDAP; - Net::LDAP->import(); - 1; + require Net::LDAP; + Net::LDAP->import(); + use Net::LDAP::Util; + 1; }; if (!$have_ldap) { die("Net::LDAP unavailable on this platform"); } +# Default values +our $aname = 'ds389'; our $server = 'localhost'; +# Default LDAP version to use. +our $ldapver = 3; our $binddn = 'cn=Directory Manager'; our $bindpw = 'Manager12'; -our $scope = 'base'; -our $cnbase = 'cn=monitor'; -our $urbase = 'cn=monitor,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'; -our $filter = '(objectclass=*)'; +# Default scope +our $dfscope = 'base'; +# Default LDAP filter +our $dffilter = '(objectclass=*)'; +# Default LDAP attributes to retrieve +our $dattrs = ['*', '+']; +# How often it will check our $query_interval = 2; # seconds +# Metrics defaults +our $mpm_type = PM_TYPE_U32; +our $mpm_indom = PM_INDOM_NULL; +our $mpm_sem = PM_SEM_INSTANT; +# Format: dim_space, dim_time, dim_count, scale_space, scale_time, scale_count +our $mpmda_units = '0,0,1,0,0,'.PM_COUNT_ONE; +our @add_met = (); +our %dclu; + +# Default base and metrics +our %dataclusters = ( + '0' => ['0','cn=monitor','cn.',$dfscope,$dffilter,$dattrs], + '1' => ['0','cn=monitor,cn=userRoot,cn=ldbm database,cn=plugins,cn=config','userroot.',$dfscope,$dffilter,$dattrs], + '2' => ['0','cn=monitor,cn=changelog,cn=ldbm database,cn=plugins,cn=config','changelog_mon.',$dfscope,$dffilter,$dattrs], + '3' => ['0','cn=snmp,cn=monitor','snmp_mon.',$dfscope,$dffilter,$dattrs] +); +our @def_met = ( + [0,0,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'threads'], + [0,1,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentconnections'], + [0,2,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'totalconnections'], + [0,3,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentconnectionsatmaxthreads'], + [0,4,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'maxthreadsperconnhits'], + [0,5,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dtablesize'], + [0,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'readwaiters'], + [0,7,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'opsinitiated'], + [0,8,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'opscompleted'], + [0,9,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entriessent'], + [0,10,PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','bytessent'], + [0,11,$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','uptime'], + [0,12,PM_TYPE_STRING,$mpm_indom,PM_SEM_DISCRETE,'0,0,0,0,0,0','version'], + [0,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nbackends'], + [1,0,$mpm_type,$mpm_indom,$mpm_sem,'0,0,0,0,0,0','readonly'], + [1,1,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachehits'], + [1,2,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachetries'], + [1,3,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entrycachehitratio'], + [1,4,PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currententrycachesize'], + [1,5,PM_TYPE_U64,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxentrycachesize'], + [1,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currententrycachecount'], + [1,7,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxentrycachecount'], + [1,8,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachehits'], + [1,9,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachetries'], + [1,10,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dncachehitratio'], + [1,11,$mpm_type,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentdncachesize'], + [1,12,$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxdncachesize'], + [1,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentdncachecount'], + [1,14,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxdncachecount'], + [1,15,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachehits'], + [1,16,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachetries'], + [1,17,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachehitratio'], + [1,18,PM_TYPE_32,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentnormalizeddncachesize'], + [1,19,PM_TYPE_32,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxnormalizeddncachesize'], + [1,20,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'currentnormalizeddncachecount'], + [1,21,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachemisses'], + [2,0,$mpm_type,$mpm_indom,$mpm_sem,'0,0,0,0,0,0','readonly'], + [2,1,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachehits'], + [2,2,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachetries'], + [2,3,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entrycachehitratio'], + [2,4,PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currententrycachesize'], + [2,5,PM_TYPE_U64,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxentrycachesize'], + [2,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currententrycachecount'], + [2,7,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxentrycachecount'], + [2,8,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachehits'], + [2,9,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachetries'], + [2,10,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dncachehitratio'], + [2,11,$mpm_type,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentdncachesize'], + [2,12,$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxdncachesize'], + [2,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentdncachecount'], + [2,14,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxdncachecount'], + [3,0,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'anonymousbinds'], + [3,1,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'unauthbinds'], + [3,2,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'simpleauthbinds'], + [3,3,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'strongauthbinds'], + [3,4,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'bindsecurityerrors'], + [3,5,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'inops'], + [3,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'readops'], + [3,7,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'compareops'], + [3,8,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'addentryops'], + [3,9,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'modifyentryops'], + [3,10,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'modifyrdnops'], + [3,11,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'listops'], + [3,12,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'searchops'], + [3,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'onelevelsearchops'], + [3,14,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'wholesubtreesearchops'], + [3,15,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'referrals'], + [3,16,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'chainings'], + [3,17,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'securityerrors'], + [3,18,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'errors'], + [3,19,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connections'], + [3,20,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connectionseq'], + [3,21,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connectionsinmaxthreads'], + [3,22,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connectionsmaxthreadscount'], + [3,23,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'bytesrecv'], + [3,24,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'bytessent'], + [3,25,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'entriesreturned'], + [3,26,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'referralsreturned'], + [3,27,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'masterentries'], + [3,28,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'cacheentries'], + [3,29,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'cachehits'], + [3,30,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'slavehits'] +); + +our @def_replagr_met = ( + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5ReplicaChangeCount'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicareapactive'] +); + +our @def_repl_met = ( + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicareapactive'], + [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsruvReplicaLastModified'], + [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastUpdateStart'], + [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastUpdateEnd'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicaChangesSentSinceStartup'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'replicaLastUpdateStatus'], + [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastInitStart'], + [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastInitEnd'], + [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastUpdateTime'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicaUpdateInProgeress'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'replicaChangesSkippedSinceStartup'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'replicaChangesSentSinceStartup'] +); + +our @def_mon_met = ( + [$mpm_type,$mpm_indom,$mpm_sem,'0,0,0,0,0,0','readonly'], + [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachehits'], + [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachetries'], + [PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entrycachehitratio'], + [PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currententrycachesize'], + [PM_TYPE_U64,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxentrycachesize'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currententrycachecount'], + [PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxentrycachecount'], + [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachehits'], + [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachetries'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dncachehitratio'], + [$mpm_type,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentdncachesize'], + [$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxdncachesize'], + [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentdncachecount'], + [PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxdncachecount'] +); + # Configuration files for overriding the above settings -for my $file (pmda_config('PCP_PMDAS_DIR') . '/ds389/ds389.conf', './ds389.conf') { - eval `cat $file` unless ! -f $file; +for my $file (pmda_config('PCP_PMDAS_DIR') . "/$aname/$aname.conf", "./$aname.conf") { + eval `cat $file` unless ! -f $file; } -use vars qw( $ldap $pmda %metrics ); +unless (!keys %dclu) { + %dataclusters = (%dataclusters, %dclu) +} -# Timestamps -my $ts_cn = 0; -my $ts_ur = 0; +use vars qw( $ldap $pmda %metrics ); sub ds389_connection_setup { - if (!defined($ldap)) { - $pmda->log("binding to $server"); - $ldap = Net::LDAP->new($server); - if (!defined($ldap)) { - $pmda->log("bind failed, server down?"); - return; - } - my $mesg = $ldap->bind($binddn, password => $bindpw); - if ($mesg->code) { - $pmda->log("bind failed: " . $mesg->error); - return; - } - $pmda->log("bind to $server ok"); - } + if (!defined($ldap)) { + $pmda->log("binding to $server"); + $ldap = Net::LDAP->new($server,version => $ldapver); + if (!defined($ldap)) { + $pmda->log("bind failed, server down?"); + return; + } + my $mesg = $ldap->bind($binddn, password => $bindpw); + if ($mesg->code) { + $pmda->log("bind failed: " . $mesg->error); + return; + } + $pmda->log("bind to $server ok"); + } } -sub ds389_time_to_epoch { - my ($time) = @_; +# Function copied from https://github.com/389ds/389-ds-base/blob/389-ds-base-1.3.10/ldap/admin/src/scripts/repl-monitor.pl.in +sub to_decimal_csn +{ + my ($maxcsn) = @_; + if (!$maxcsn || $maxcsn eq "" || $maxcsn eq "Unavailable") { + return "Unavailable"; + } + + my ($tm, $seq, $masterid, $subseq) = unpack("a8 a4 a4 a4", $maxcsn); + + $tm = hex($tm); + $seq = hex($seq); + $masterid = hex($masterid); + $subseq = hex($subseq); - return mktime(substr($time,12,2), - substr($time,10,2), - substr($time,8,2), - substr($time,6,2), - substr($time,4,2) - 1, - substr($time,0,4) - 1900); + return "$tm $seq $masterid $subseq"; } -sub ds389_process_entry { - my ($entry, $prefix, $cluster) = @_; - my $currtime; - foreach my $attr ($entry->attributes) { - my $value = $entry->get_value($attr); - if ($attr eq 'currenttime') { - $currtime = ds389_time_to_epoch($value); - next; - } - - if ($attr eq 'starttime') { - my $starttime = ds389_time_to_epoch($value); - $value = $currtime - $starttime; - $attr = 'uptime'; - } +sub ds389_time_to_epoch { + my ($time) = @_; + return mktime(substr($time,12,2), + substr($time,10,2), + substr($time,8,2), + substr($time,6,2), + substr($time,4,2) - 1, + substr($time,0,4) - 1900); +} - $metrics{'ds389.' . $prefix . $attr} = $value; - } +sub ds389_process_entry { + my ($entry, $prefix, $cluster) = @_; + my $currtime; + my $startrepltime = ''; + my $endrepltime = ''; + if ($entry && $entry->can('attributes')) { + foreach my $attr ($entry->attributes) { + my $value = $entry->get_value($attr); + + if ($attr eq 'currenttime') { + $currtime = ds389_time_to_epoch($value); + next; + } + + if ($attr eq 'starttime') { + my $starttime = ds389_time_to_epoch($value); + $value = $currtime - $starttime; + $attr = 'uptime'; + } + + if ($attr eq 'nsds5replicaLastUpdateStatus') { + if ($value =~ /No replication sessions started since server startup/i) { + $value = 30 + } elif ($value =~ /agreement disabled/i) { + $value = 31 + } elif ($value =~ /Problem connecting to the replica/i) { + $value = 20 + } else { + $value = (split /\)/, (split /Error \(/, $value)[1])[0]; + } + $attr = 'replicaLastUpdateStatus'; + } + + if ($attr eq 'nsds5replicaChangesSentSinceStartup' ) { +# my $rep_id = (split /:/, $value)[0]; + my ($sent, $skipped) = (split /\//, (split /:/, $value)[1]); +# $attr = 'replica'.$rep_id.'ChangesSentSinceStartup'; + $attr = 'replicaChangesSentSinceStartup'; + $metrics{"$aname." . $prefix . $attr} = $sent; + $value = $skipped; +# $attr = 'replica'.$rep_id.'ChangesSkippedSinceStartup'; + $attr = 'replicaChangesSkippedSinceStartup'; + } + + if ($attr eq 'nsds5replicaUpdateInProgress' ) { + if ($value =~ /^(true|TRUE)$/) { + $value = 1; + } else { + $value = 0; + } + } + + if ($attr =~ /^(nsds5replicaLastInitEnd|nsds5replicaLastUpdateStart|nsds5replicaLastInitStart)$/i ) { + $value = ds389_time_to_epoch($value); + if ($attr eq 'nsds5replicaLastUpdateStart') { + $startrepltime = $value; + } + $metrics{"$aname." . $prefix . $attr} = $value; + } + + if ($endrepltime ne '' && $startrepltime ne '' ) { + $attr = 'nsds5replicaLastUpdateTime'; + $value = $endrepltime - $startrepltime; + $startrepltime = $endrepltime = ''; + } + + if ($attr =~ /^(nsds5replicaLastUpdateEnd)$/i ) { + $value = ds389_time_to_epoch($value); + $endrepltime = $value; + } + + if ($attr =~ /^nsds5AgmtMaxCSN$/i ) { + my $maxcsn = &to_decimal_csn((split /\;/, $value)[5]); + $value = (split / /, $maxcsn)[0]; + } + + $metrics{"$aname." . $prefix . $attr} = $value; + } + } +} + +sub retrieve_ldap { + my ($cluster, $ts, $base, $tname, $scope, $filter, $lattrs) = @_; + my $mesg; + + if ((strftime("%s", localtime()) - $ts) > $query_interval) { + $ts = strftime("%s", localtime()); + $mesg = $ldap->search(scope => $scope, base => $base, filter => $filter, attrs => $lattrs); + if ($mesg->code) { + $pmda->log("search(scope: \"$scope\", base: \"$base\", filter: \"$filter\", attrs: \"". join(' ', @$lattrs) ."\") failed: " . $mesg->error); + undef $ldap; + return; + } + ds389_process_entry($mesg->entry, $tname, $cluster); + } } sub ds389_fetch { - if (!defined($ldap)) { - ds389_connection_setup(); - } - return unless defined($ldap); - - my ($cluster) = @_; - my $mesg; - - if ($cluster eq 0) { - if ((strftime("%s", localtime()) - $ts_cn) > $query_interval) { - # $pmda->log("cn search"); - $ts_cn = strftime("%s", localtime()); - $mesg = $ldap->search(scope => $scope, base => $cnbase, filter => $filter); - if ($mesg->code) { - $pmda->log("search failed: " . $mesg->error); - undef $ldap; - return; - } - ds389_process_entry($mesg->entry, 'cn.', 0); - } - } - - if ($cluster eq 1) { - if ((strftime("%s", localtime()) - $ts_ur) > $query_interval) { - # $pmda->log("ur search"); - $ts_ur = strftime("%s", localtime()); - $mesg = $ldap->search(scope => $scope, base => $urbase, filter => $filter); - if ($mesg->code) { - $pmda->log("search failed: " . $mesg->error); - undef $ldap; - return; - } - ds389_process_entry($mesg->entry, 'userroot.', 1); - } - } + if (!defined($ldap)) { + ds389_connection_setup(); + } + return unless defined($ldap); + + my ($cluster) = @_; + my $mesg; + + \&retrieve_ldap($cluster,$dataclusters{$cluster}[0],$dataclusters{$cluster}[1],$dataclusters{$cluster}[2],$dataclusters{$cluster}[3],$dataclusters{$cluster}[4], $dataclusters{$cluster}[5]); } sub ds389_fetch_callback { - my ($cluster, $item, $inst) = @_; + my ($cluster, $item, $inst) = @_; - if (!defined($ldap)) { return (PM_ERR_AGAIN, 0); } - if ($inst != PM_INDOM_NULL) { return (PM_ERR_INST, 0); } + if (!defined($ldap)) { return (PM_ERR_AGAIN, 0); } + if ($inst != PM_INDOM_NULL) { return (PM_ERR_INST, 0); } + + my $pmnm = pmda_pmid_name($cluster, $item); + my $value = $metrics{$pmnm}; + + if (!defined($value)) { return (PM_ERR_APPVERSION, 0); } + + return ($value, 1); +} - my $pmnm = pmda_pmid_name($cluster, $item); - my $value = $metrics{$pmnm}; - if (!defined($value)) { return (PM_ERR_APPVERSION, 0); } - - return ($value, 1); -} - -$pmda = PCP::PMDA->new('ds389', 130); - -# Metrics available on 389 DS 1.3.2.23 - -# cn=monitor -$pmda->add_metric(pmda_pmid(0,0), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.threads', '', ''); -$pmda->add_metric(pmda_pmid(0,1), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.currentconnections', '', ''); -$pmda->add_metric(pmda_pmid(0,2), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.totalconnections', '', ''); -$pmda->add_metric(pmda_pmid(0,3), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.currentconnectionsatmaxthreads', '', ''); -$pmda->add_metric(pmda_pmid(0,4), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.maxthreadsperconnhits', '', ''); -$pmda->add_metric(pmda_pmid(0,5), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.dtablesize', '', ''); -$pmda->add_metric(pmda_pmid(0,6), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.readwaiters', '', ''); -$pmda->add_metric(pmda_pmid(0,7), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.opsinitiated', '', ''); -$pmda->add_metric(pmda_pmid(0,8), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.opscompleted', '', ''); -$pmda->add_metric(pmda_pmid(0,9), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.cn.entriessent', '', ''); -$pmda->add_metric(pmda_pmid(0,10), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.cn.bytessent', '', ''); -$pmda->add_metric(pmda_pmid(0,11), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,1,0,0,PM_TIME_SEC,0), - 'ds389.cn.uptime', '', ''); # calculated - -# cn=monitor,cn=userRoot,cn=ldbm database,cn=plugins,cn=config -$pmda->add_metric(pmda_pmid(1,0), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,0,0,0,0), - 'ds389.userroot.readonly', '', ''); -$pmda->add_metric(pmda_pmid(1,1), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.entrycachehits', '', ''); -$pmda->add_metric(pmda_pmid(1,2), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.entrycachetries', '', ''); -$pmda->add_metric(pmda_pmid(1,3), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.entrycachehitratio', '', ''); -$pmda->add_metric(pmda_pmid(1,4), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.userroot.currententrycachesize', '', ''); -$pmda->add_metric(pmda_pmid(1,5), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_DISCRETE, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.userroot.maxentrycachesize', '', ''); -$pmda->add_metric(pmda_pmid(1,6), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.currententrycachecount', '', ''); -$pmda->add_metric(pmda_pmid(1,7), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.maxentrycachecount', '', ''); -$pmda->add_metric(pmda_pmid(1,8), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.dncachehits', '', ''); -$pmda->add_metric(pmda_pmid(1,9), PM_TYPE_U64, PM_INDOM_NULL, - PM_SEM_COUNTER, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.dncachetries', '', ''); -$pmda->add_metric(pmda_pmid(1,10), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.dncachehitratio', '', ''); -$pmda->add_metric(pmda_pmid(1,11), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.userroot.currentdncachesize', '', ''); -$pmda->add_metric(pmda_pmid(1,12), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_DISCRETE, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.userroot.maxdncachesize', '', ''); -$pmda->add_metric(pmda_pmid(1,13), PM_TYPE_U32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.currentdncachecount', '', ''); -$pmda->add_metric(pmda_pmid(1,14), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.maxdncachecount', '', ''); -$pmda->add_metric(pmda_pmid(1,15), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.normalizeddncachehits', '', ''); -$pmda->add_metric(pmda_pmid(1,16), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.normalizeddncachetries', '', ''); -$pmda->add_metric(pmda_pmid(1,17), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.normalizeddncachehitratio', '', ''); -$pmda->add_metric(pmda_pmid(1,18), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.userroot.currentnormalizeddncachesize', '', ''); -$pmda->add_metric(pmda_pmid(1,19), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(1,0,0,PM_SPACE_BYTE,0,0), - 'ds389.userroot.maxnormalizeddncachesize', '', ''); -$pmda->add_metric(pmda_pmid(1,20), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.currentnormalizeddncachecount', '', ''); -$pmda->add_metric(pmda_pmid(1,21), PM_TYPE_32, PM_INDOM_NULL, - PM_SEM_INSTANT, pmda_units(0,0,1,0,0,PM_COUNT_ONE), - 'ds389.userroot.normalizeddncachemisses', '', ''); +sub ds389_simple_search { + my ($scope, $base, $filter, $attrs) = @_; + + my $mesg = $ldap->search(scope => $scope, base => $base, filter => $filter, attrs => $attrs); + if ($mesg->code) { + $pmda->log("search(scope: \"$scope\", base: \"$base\", filter: \"$filter\", attrs: \"". join(' ', @$attrs) ."\") failed: " . $mesg->error); + undef $ldap; + return; + } + return $mesg +} + +sub push_to_met { + my ($tc, @myarr) = @_; + my $count = 0; + foreach my $c (0 .. $#myarr) { + push(@def_met, [$tc, $c, $myarr[$c][0], $myarr[$c][1], $myarr[$c][2], $myarr[$c][3], $myarr[$c][4]]); + }; +} + +$pmda = PCP::PMDA->new($aname, 130); + +# Add to the existing ones +my $topclu = 0; +foreach my $attr (keys %dataclusters) { + if ($attr gt $topclu) { + $topclu = $attr; + } +}; + +$ldap = Net::LDAP->new($server,version => $ldapver); +if (!defined($ldap)) { + $pmda->log("bind failed, server down?"); +} + +my $mesg = $ldap->bind($binddn, password => $bindpw); +if ($mesg->code) { + $pmda->log("bind failed: " . $mesg->error); +} + +$mesg = ds389_simple_search('sub','cn=config','objectclass=*',['nsslapd-defaultnamingcontext','nsslapd-backend']); + +my $max = $mesg->count; +for ( my $i = 0 ; $i < $max ; $i++ ) { + my $entry = $mesg->entry ( $i ); + foreach my $attr ($entry->attributes) { + my $value = $entry->get_value($attr); + my $value_short = $value =~ s/[,]*[a-zA-Z]*=/_/rgi; + my $value_ldap = $value =~ s/=/\\3D/igr =~ s/,/\\2C/igr; + if ($attr eq 'nsslapd-defaultnamingcontext') { + $topclu++; + $dataclusters{$topclu} = ['0',$value,$value_short . '.','sub','(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))',['nsds5agmtmaxcsn','nsds50ruv']]; + my $mesg2 = ds389_simple_search('sub',"cn=$value_ldap,cn=mapping tree,cn=config",'objectclass=nsds5replicationagreement',['cn']); + my $max2 = $mesg2->count; + for ( my $i2 = 0 ; $i2 < $max2 ; $i2++ ) { + my $entry2 = $mesg2->entry ( $i2 ); + my $rplagr = $entry2->get_value('cn'); + $topclu++; + my $value2_short = (split /\./, $rplagr)[0]; + $dataclusters{$topclu} = ['0',"cn=". $rplagr .",cn=replica,cn=". $value_ldap .",cn=mapping tree,cn=config",$value2_short . '.',$dfscope,$dffilter,$dattrs]; + push_to_met($topclu, @def_repl_met); + $topclu++; + $dataclusters{$topclu} = ['0',"cn=replica,cn=". $value_ldap .",cn=mapping tree,cn=config","rpl_". $value2_short . '.',$dfscope,$dffilter,$dattrs]; + push_to_met($topclu, @def_replagr_met); + } + } + if (($attr eq 'nsslapd-backend') and ($value eq 'ipaca')) { + $topclu++; + $dataclusters{$topclu} = ['0',$value,$value_short . '.','sub','(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))',['nsds5agmtmaxcsn','nsds50ruv']]; + my $mesg2 = ds389_simple_search('sub',"cn=o\\3D$value_ldap,cn=mapping tree,cn=config",'objectclass=nsds5replicationagreement',['cn']); + my $max2 = $mesg2->count; + for ( my $i2 = 0 ; $i2 < $max2 ; $i2++ ) { + my $entry2 = $mesg2->entry ( $i2 ); + my $rplagr = $entry2->get_value('cn'); + $topclu++; + my $value2_short = (split /\./, $rplagr)[0]; + $dataclusters{$topclu} = ['0',"cn=". $rplagr .",cn=replica,cn=o\\3D". $value_ldap .",cn=mapping tree,cn=config",$value2_short . '.',$dfscope,$dffilter,$dattrs]; + push_to_met($topclu, @def_repl_met); + $topclu++; + $dataclusters{$topclu} = ['0',"cn=replica,cn=o\\3D". $value_ldap .",cn=mapping tree,cn=config","rpl_". $value2_short . '.',$dfscope,$dffilter,$dattrs]; + push_to_met($topclu, @def_replagr_met); + $topclu++; + $dataclusters{$topclu} = ['0',"cn=monitor,cn=$value,cn=ldbm database,cn=plugins,cn=config",$value ."_mon.",$dfscope,$dffilter,$dattrs]; + push_to_met($topclu, @def_mon_met); + } + } + }; +}; + +# Add default metrics +while (my ($i, @met) = each @def_met) { + if (defined($dataclusters{$def_met[$i][0]})) { + $pmda->add_metric(pmda_pmid($def_met[$i][0],$def_met[$i][1]), $def_met[$i][2], $def_met[$i][3],$def_met[$i][4], pmda_units(split(',',$def_met[$i][5])),"$aname.$dataclusters{$def_met[$i][0]}[2]$def_met[$i][6]", '', ''); + } +}; + +# Add metrics from the configuration file +while (my ($i, @met) = each @add_met) { + if (defined($dataclusters{$add_met[$i][0]})) { + $pmda->add_metric(pmda_pmid($add_met[$i][0],$add_met[$i][1]), $add_met[$i][2], $add_met[$i][3],$add_met[$i][4], pmda_units(split(',',$add_met[$i][5])),"$aname.$dataclusters{$add_met[$i][0]}[2]$add_met[$i][6]", '', ''); + } +}; $pmda->set_refresh(\&ds389_fetch); $pmda->set_fetch_callback(\&ds389_fetch_callback); diff -Nru pcp-5.3.1/src/pmdas/GNUmakefile pcp-5.3.2/src/pmdas/GNUmakefile --- pcp-5.3.1/src/pmdas/GNUmakefile 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/pmdas/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -26,7 +26,7 @@ lustrecomm infiniband logger bash systemd \ gfs2 jbd2 cifs nvidia perfevent \ dm pipe openbsd docker smart podman statsd \ - hacluster linux_sockets + hacluster linux_sockets denki PLPMDAS = bonding netfilter zimbra postgresql \ dbping memcache mysql oracle vmware kvm \ diff -Nru pcp-5.3.1/src/pmdas/hacluster/corosync.c pcp-5.3.2/src/pmdas/hacluster/corosync.c --- pcp-5.3.1/src/pmdas/hacluster/corosync.c 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/corosync.c 2021-07-30 04:05:06.000000000 +0000 @@ -133,6 +133,13 @@ } int +hacluster_corosync_ring_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + +int hacluster_refresh_corosync_node(const char *node_name, struct member_votes *node) { char buffer[4096], local[8]; diff -Nru pcp-5.3.1/src/pmdas/hacluster/corosync.h pcp-5.3.2/src/pmdas/hacluster/corosync.h --- pcp-5.3.1/src/pmdas/hacluster/corosync.h 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/corosync.h 2021-07-30 04:05:06.000000000 +0000 @@ -73,6 +73,7 @@ extern int hacluster_refresh_corosync_global(); extern int hacluster_corosync_ring_fetch(int, struct rings *, pmAtomValue *); +extern int hacluster_corosync_ring_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_corosync_ring(const char *, struct rings *); extern void corosync_stats_setup(void); diff -Nru pcp-5.3.1/src/pmdas/hacluster/drbd.c pcp-5.3.2/src/pmdas/hacluster/drbd.c --- pcp-5.3.1/src/pmdas/hacluster/drbd.c 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/drbd.c 2021-07-30 04:05:06.000000000 +0000 @@ -91,6 +91,13 @@ } int +hacluster_drbd_resource_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + +int hacluster_drbd_peer_device_fetch(int item, struct peer_device *peer_device, pmAtomValue *atom) { /* check for bounds */ @@ -147,6 +154,13 @@ } int +hacluster_drbd_peer_device_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + +int hacluster_refresh_drbd_resource(const char *resource_name, struct resource *resource) { char buffer[4096]; diff -Nru pcp-5.3.1/src/pmdas/hacluster/drbd.h pcp-5.3.2/src/pmdas/hacluster/drbd.h --- pcp-5.3.1/src/pmdas/hacluster/drbd.h 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/drbd.h 2021-07-30 04:05:06.000000000 +0000 @@ -83,9 +83,11 @@ }; extern int hacluster_drbd_resource_fetch(int, struct resource *, pmAtomValue *); +extern int hacluster_drbd_resource_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_drbd_resource(const char *, struct resource *); extern int hacluster_drbd_peer_device_fetch(int, struct peer_device *, pmAtomValue *); +extern int hacluster_drbd_peer_device_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_drbd_peer_device(const char *, struct peer_device *); extern void drbd_stats_setup(void); diff -Nru pcp-5.3.1/src/pmdas/hacluster/help pcp-5.3.2/src/pmdas/hacluster/help --- pcp-5.3.1/src/pmdas/hacluster/help 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/help 2021-07-30 04:05:06.000000000 +0000 @@ -28,7 +28,7 @@ # @ HACLUSTER.0 Instance domain for High Availability Cluster component metrics -@ ha_cluster.pacemaker.config_last_change Unix timestamp corresponding to last Pacmaker configuration change +@ ha_cluster.pacemaker.config_last_change Unix timestamp corresponding to last Pacemaker configuration change Unix timestamp in seconds corresponding to the last time that the Pacemaker configuration was changed on the system. @@ -42,7 +42,11 @@ @ ha_cluster.pacemaker.node_attributes Metadata used by Resource Agents The raw values for the cluster metadata attributes and their value per node as -used by the Resource Agents. +used by the Resource Agents. + +@ ha_cluster.pacemaker.node_attributes_all Metadata information +Value is 1 if a node metadata exists. The details of the node metadata +is given as label metadata values for this metric. @ ha_cluster.pacemaker.stonith_enabled Whether stonith is enabled in the cluster Value returns as to whether stonith is enabled or disabled for the cluster. @@ -54,12 +58,16 @@ The resource that the location constraint applies to in the cluster. @ ha_cluster.pacemaker.location_constraints.role Resource role of the location constraint -The resource role that the location contraint applies to, if any. +The resource role that the location constraint applies to, if any. @ ha_cluster.pacemaker.location_constraints.score Score of the location constraint The score given to the location constraint by Pacemaker, the value depends on Pacemaker internals. +@ ha_cluster.pacemaker.location_constraints.all Location constraint information +Value is 1 if a location constraint exists. The details of the location constraint +is given as label metadata values for this metric. + @ ha_cluster.pacemaker.nodes.type The type given to the node The membership type given to the node in the Pacemaker cluster. @@ -137,6 +145,10 @@ Whether the failure_ignored status is reported by the resource in the cluster, a value of 1 confirms the resource status as failure_ignored. +@ ha_cluster.pacemaker.resources.all Pacemaker resources information +Value is 1 if a resources exists. The details of the resource +is given as label metadata values for this metric. + @ ha_cluster.corosync.quorate Value given for quorate The value represents whether or not the cluster is quorate. @@ -155,7 +167,7 @@ @ ha_cluster.corosync.quorum_votes.expected_votes Expected vote count The number of expected quorum votes for the cluster. -@ ha_cluster.corosync.quorum_votes.highest_expected Hightest expected vote count +@ ha_cluster.corosync.quorum_votes.highest_expected Highest expected vote count The highest number of expected quorum votes for the cluster. @ ha_cluster.corosync.quorum_votes.total_votes Total number of votes @@ -180,6 +192,10 @@ @ ha_cluster.corosync.rings.ring_id Ring ID The internal Corosync ring ID, corresponds to the first node to join. +@ ha_cluster.corosync.rings.all Corosync rings information +Value is 1 if a ring exists. The details of the corresponding ring +is given as label metadata values for this metric. + @ ha_cluster.sbd.devices.path Path of SBD device The full path given to each SBD device. @@ -187,6 +203,10 @@ The current status given for each of the SBD devices, the value is one of healthy or unhealthy. +@ ha_cluster.sbd.all SBD device information +Value is 1 if a sbd device exists. The details of the corresponding SBD device +is given as label metadata values for this metric. + @ ha_cluster.sbd.timeouts.mgswait mgswait timeout value The value threshold for msgwait timeouts for the given SBD device. @@ -220,7 +240,7 @@ The number of open requests to the local I/O subsystem by DRBD for the resource:volume. -@ ha_cluster.drbd.quorum Quorum satus of DRBD resource:volume +@ ha_cluster.drbd.quorum Quorum status of DRBD resource:volume The Quorum status of the DRBD resource according to resource:volume, 1 is quorate and 0 is non-quorate. @@ -245,21 +265,25 @@ the resource:volume. @ ha_cluster.drbd.split_brain Signal for split brain detection. -This metric signals if there has been a split brain occuring in DRBD for the +This metric signals if there has been a split brain occurring in DRBD for the resource:volume, value is 1 is a split brain has been detected. @ ha_cluster.drbd.resources.resource Name of the resource The name given for the DRBD resource for each resource:volume. @ ha_cluster.drbd.resources.role Role of the resource -The resported role for ther DRBD resource for each resource:volume. +The reported role for the DRBD resource for each resource:volume. @ ha_cluster.drbd.resources.volume Volume of the resource -The volume number of ther resource for each resource:volume. +The volume number of the resource for each resource:volume. @ ha_cluster.drbd.resources.disk_state Disk state The current reported disk state of for the resource:volume. +@ ha_cluster.drbd.resources.all DRBD resource information +Value is 1 if a drbd resource exists. The details of the corresponding drbd resource +is given as label metadata values for this metric. + @ ha_cluster.drbd.connections.resource Resource that the connection is for The given resource that the DRBD connection is for each resource:volume. @@ -274,3 +298,7 @@ @ ha_cluster.drbd.connections.peer_disk_state Peer disk state The reported peer disk state for the connection. + +@ ha_cluster.drbd.connections.all DRBD Peer disk information +Value is 1 if a drbd peer connection exists. The details of the corresponding DRBD peer +connection is given as label metadata values for this metric. diff -Nru pcp-5.3.1/src/pmdas/hacluster/pacemaker.c pcp-5.3.2/src/pmdas/hacluster/pacemaker.c --- pcp-5.3.1/src/pmdas/hacluster/pacemaker.c 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/pacemaker.c 2021-07-30 04:05:06.000000000 +0000 @@ -222,6 +222,13 @@ } int +hacluster_pacemaker_constraints_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + +int hacluster_pacemaker_nodes_fetch(int item, struct nodes *nodes, pmAtomValue *atom) { /* check for bounds */ @@ -298,6 +305,13 @@ } int +hacluster_pacemaker_node_attribs_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + +int hacluster_pacemaker_resources_fetch(int item, struct resources *resources, pmAtomValue *atom) { /* check for bounds */ @@ -354,6 +368,13 @@ } int +hacluster_pacemaker_resources_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + +int hacluster_refresh_pacemaker_global() { char buffer[4096]; diff -Nru pcp-5.3.1/src/pmdas/hacluster/pacemaker.h pcp-5.3.2/src/pmdas/hacluster/pacemaker.h --- pcp-5.3.1/src/pmdas/hacluster/pacemaker.h 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/pacemaker.h 2021-07-30 04:05:06.000000000 +0000 @@ -124,15 +124,18 @@ extern int hacluster_refresh_pacemaker_fail(const char *, struct fail_count *); extern int hacluster_pacemaker_constraints_fetch(int, struct location_constraints *, pmAtomValue *); +extern int hacluster_pacemaker_constraints_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_pacemaker_constraints(const char *, struct location_constraints *); extern int hacluster_pacemaker_nodes_fetch(int, struct nodes *, pmAtomValue *); extern int hacluster_refresh_pacemaker_nodes(const char *, struct nodes *); extern int hacluster_pacemaker_node_attribs_fetch(int, struct attributes *, pmAtomValue *); +extern int hacluster_pacemaker_node_attribs_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_pacemaker_node_attribs(const char *, struct attributes *); extern int hacluster_pacemaker_resources_fetch(int, struct resources *, pmAtomValue *); +extern int hacluster_pacemaker_resources_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_pacemaker_resources(const char *, struct resources *); extern void pacemaker_stats_setup(void); diff -Nru pcp-5.3.1/src/pmdas/hacluster/pmda.c pcp-5.3.2/src/pmdas/hacluster/pmda.c --- pcp-5.3.1/src/pmdas/hacluster/pmda.c 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/pmda.c 2021-07-30 04:05:06.000000000 +0000 @@ -42,6 +42,13 @@ { .it_indom = SBD_DEVICE_INDOM }, { .it_indom = DRBD_RESOURCE_INDOM }, { .it_indom = DRBD_PEER_DEVICE_INDOM }, + { .it_indom = PACEMAKER_CONSTRAINTS_ALL_INDOM }, + { .it_indom = PACEMAKER_NODE_ATTRIB_ALL_INDOM }, + { .it_indom = PACEMAKER_RESOURCES_ALL_INDOM }, + { .it_indom = COROSYNC_RING_ALL_INDOM}, + { .it_indom = SBD_DEVICE_ALL_INDOM}, + { .it_indom = DRBD_RESOURCE_ALL_INDOM}, + { .it_indom = DRBD_PEER_DEVICE_ALL_INDOM}, }; #define INDOM(x) (indomtable[x].it_indom) @@ -84,6 +91,10 @@ PM_TYPE_STRING, PACEMAKER_CONSTRAINTS_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, { .m_desc = { + PMDA_PMID(CLUSTER_PACEMAKER_CONSTRAINTS_ALL, 0), + PM_TYPE_U32, PACEMAKER_CONSTRAINTS_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc = { PMDA_PMID(CLUSTER_PACEMAKER_NODES, PACEMAKER_NODES_ONLINE), PM_TYPE_U32, PACEMAKER_NODES_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, @@ -128,6 +139,10 @@ PM_TYPE_STRING, PACEMAKER_NODE_ATTRIB_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, { .m_desc = { + PMDA_PMID(CLUSTER_PACEMAKER_NODE_ATTRIB_ALL, 0), + PM_TYPE_U32, PACEMAKER_NODE_ATTRIB_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc = { PMDA_PMID(CLUSTER_PACEMAKER_RESOURCES, PACEMAKER_RESOURCES_AGENT), PM_TYPE_STRING, PACEMAKER_RESOURCES_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, @@ -140,6 +155,10 @@ PM_TYPE_STRING, PACEMAKER_RESOURCES_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, { .m_desc = { + PMDA_PMID(CLUSTER_PACEMAKER_RESOURCES_ALL, 0), + PM_TYPE_U32, PACEMAKER_RESOURCES_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc = { PMDA_PMID(CLUSTER_PACEMAKER_RESOURCES, PACEMAKER_RESOURCES_MANAGED), PM_TYPE_U32, PACEMAKER_RESOURCES_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, @@ -228,6 +247,10 @@ PMDA_PMID(CLUSTER_COROSYNC_RING, COROSYNC_RINGS_RING_ID), PM_TYPE_STRING, COROSYNC_RING_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc = { + PMDA_PMID(CLUSTER_COROSYNC_RING_ALL, 0), + PM_TYPE_U32, COROSYNC_RING_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, /* SBD */ { .m_desc = { PMDA_PMID(CLUSTER_SBD_DEVICE, SBD_DEVICE_PATH), @@ -238,6 +261,10 @@ PM_TYPE_STRING, SBD_DEVICE_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, { .m_desc = { + PMDA_PMID(CLUSTER_SBD_DEVICE_ALL, 0), + PM_TYPE_U32, SBD_DEVICE_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc = { PMDA_PMID(CLUSTER_SBD_DEVICE, SBD_DEVICE_TIMEOUT_MSGWAIT), PM_TYPE_U32, SBD_DEVICE_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, @@ -270,6 +297,10 @@ PMDA_PMID(CLUSTER_DRBD_RESOURCE, DRBD_RESOURCE_DISK_STATE), PM_TYPE_STRING, DRBD_RESOURCE_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc ={ + PMDA_PMID(CLUSTER_DRBD_RESOURCE_ALL, 0), + PM_TYPE_U32, DRBD_RESOURCE_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, { .m_desc = { PMDA_PMID(CLUSTER_DRBD_RESOURCE, DRBD_RESOURCE_WRITTEN), PM_TYPE_U32, DRBD_RESOURCE_INDOM, PM_SEM_INSTANT, @@ -319,6 +350,10 @@ PM_TYPE_STRING, DRBD_PEER_DEVICE_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, { .m_desc = { + PMDA_PMID(CLUSTER_DRBD_PEER_DEVICE_ALL, 0), + PM_TYPE_U32, DRBD_PEER_DEVICE_ALL_INDOM, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, + { .m_desc = { PMDA_PMID(CLUSTER_DRBD_PEER_DEVICE, DRBD_PEER_DEVICE_CONNECTIONS_SYNC), PM_TYPE_FLOAT, DRBD_PEER_DEVICE_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, @@ -359,6 +394,12 @@ FILE *pf; pmInDom indom = INDOM(PACEMAKER_FAIL_INDOM); + /* + * Update indom cache based off the reading of crm_mon listed in + * the output from crm_mon + */ + pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmsprintf(buffer, sizeof(buffer), "%s 2>&1", crm_mon_command); if ((pf = popen(buffer, "r")) == NULL) @@ -425,6 +466,14 @@ int found_constraints = 0; FILE *pf; pmInDom indom = INDOM(PACEMAKER_CONSTRAINTS_INDOM); + pmInDom indom_all = INDOM(PACEMAKER_CONSTRAINTS_ALL_INDOM); + + /* + * Update indom cache based off the reading of cibadmin listed in + * the output from cibadmin + */ + pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); pmsprintf(buffer, sizeof(buffer), "%s 2>&1", cibadmin_command); buffer[sizeof(buffer)-1] = '\0'; @@ -457,6 +506,7 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, constraint_name, (void *)constraints); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, constraint_name, NULL); } } pclose(pf); @@ -472,6 +522,12 @@ FILE *pf; pmInDom indom = INDOM(PACEMAKER_NODES_INDOM); + /* + * Update indom cache based off the reading of crm_mon listed in + * the output from crm_mon + */ + pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmsprintf(buffer, sizeof(buffer), "%s 2>&1", crm_mon_command); if ((pf = popen(buffer, "r")) == NULL) @@ -524,6 +580,14 @@ int found_node_attributes = 0, found_node_name = 0; FILE *pf; pmInDom indom = INDOM(PACEMAKER_NODE_ATTRIB_INDOM); + pmInDom indom_all = INDOM(PACEMAKER_NODE_ATTRIB_ALL_INDOM); + + /* + * Update indom cache based off the reading of crm_mon listed in + * the output from crm_mon + */ + pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); pmsprintf(buffer, sizeof(buffer), "%s 2>&1", crm_mon_command); @@ -582,6 +646,7 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, instance_name, (void *)node_attrib); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, instance_name, NULL); } } } @@ -597,6 +662,14 @@ int found_resources = 0; FILE *pf; pmInDom indom= INDOM(PACEMAKER_RESOURCES_INDOM); + pmInDom indom_all = INDOM(PACEMAKER_RESOURCES_ALL_INDOM); + + /* + * Update indom cache based off the reading of crm_mon listed in + * the output from crm_mon + */ + pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); pmsprintf(buffer, sizeof(buffer), "%s 2>&1", crm_mon_command); @@ -652,6 +725,7 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, instance_name, (void *)pace_resources); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, instance_name, NULL); /* Clear node name in the event that a resource has not got a node attachment */ memset(node_name, '\0', sizeof(node_name)); @@ -730,12 +804,14 @@ char buffer[4096], ring_name[128]; FILE *pf; pmInDom indom = INDOM(COROSYNC_RING_INDOM); + pmInDom indom_all = INDOM(COROSYNC_RING_ALL_INDOM); /* * Update indom cache based off number of nodes listed in the * membership information section of corosync-quorumtool output */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); pmsprintf(buffer, sizeof(buffer), "%s 2>&1", cfgtool_command); @@ -774,6 +850,7 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, ring_name, (void *)ring); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, ring_name, NULL); } } pclose(pf); @@ -789,12 +866,14 @@ char *buffer_ptr; FILE *fp; pmInDom indom = INDOM(SBD_DEVICE_INDOM); + pmInDom indom_all = INDOM(SBD_DEVICE_ALL_INDOM); /* * Update indom cache based off number of nodes listed in the * membership information section of corosync-quorumtool output */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); if ((fp = fopen(sbd_path, "r")) == NULL) /* @@ -842,6 +921,7 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, dev_name, (void *)sbd); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, dev_name, NULL); } } } @@ -860,6 +940,7 @@ char *buffer_ptr; FILE *pf; pmInDom indom = INDOM(DRBD_RESOURCE_INDOM); + pmInDom indom_all = INDOM(DRBD_RESOURCE_ALL_INDOM); int found_node = 0, found_volume = 0, nesting = 0; @@ -868,6 +949,7 @@ * the json output from drbdsetup */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); pmsprintf(buffer, sizeof(buffer), "%s 2>&1", drbdsetup_command); @@ -921,6 +1003,8 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, resource_name, (void *)resource); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, resource_name, NULL); + found_volume = 0; } } @@ -937,6 +1021,7 @@ char *buffer_ptr; FILE *pf; pmInDom indom = INDOM(DRBD_PEER_DEVICE_INDOM); + pmInDom indom_all = INDOM(DRBD_PEER_DEVICE_ALL_INDOM); int found_node = 0, found_peer_node = 0, nesting = 0; @@ -945,6 +1030,7 @@ * the json output from drbdsetup */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + pmdaCacheOp(indom_all, PMDA_CACHE_INACTIVE); pmsprintf(buffer, sizeof(buffer), "%s 2>&1", drbdsetup_command); @@ -998,6 +1084,8 @@ continue; pmdaCacheStore(indom, PMDA_CACHE_ADD, peer_name, (void *)peer_device); + pmdaCacheStore(indom_all, PMDA_CACHE_ADD, peer_name, NULL); + found_peer_node = 0; } } @@ -1088,7 +1176,8 @@ if (!pmdaCacheLookup(INDOM(PACEMAKER_CONSTRAINTS_INDOM), i, &constraint_name, (void **)&constraints) || !constraints) continue; - if (need_refresh[CLUSTER_PACEMAKER_CONSTRAINTS]) + if (need_refresh[CLUSTER_PACEMAKER_CONSTRAINTS] || + need_refresh[CLUSTER_PACEMAKER_CONSTRAINTS_ALL]) hacluster_refresh_pacemaker_constraints(constraint_name, &constraints->location_constraints); } @@ -1108,7 +1197,8 @@ if (!pmdaCacheLookup(INDOM(PACEMAKER_NODE_ATTRIB_INDOM), i, &attrib_name, (void **)&node_attribs) || !node_attribs) continue; - if (need_refresh[CLUSTER_PACEMAKER_NODE_ATTRIB]) + if (need_refresh[CLUSTER_PACEMAKER_NODE_ATTRIB] || + need_refresh[CLUSTER_PACEMAKER_NODE_ATTRIB_ALL]) hacluster_refresh_pacemaker_node_attribs(attrib_name, &node_attribs->attributes); } @@ -1118,7 +1208,8 @@ if (!pmdaCacheLookup(INDOM(PACEMAKER_RESOURCES_INDOM), i, &pace_resource_name, (void **)&pace_resources) || !pace_resources) continue; - if (need_refresh[CLUSTER_PACEMAKER_RESOURCES]) + if (need_refresh[CLUSTER_PACEMAKER_RESOURCES] || + need_refresh[CLUSTER_PACEMAKER_RESOURCES_ALL]) hacluster_refresh_pacemaker_resources(pace_resource_name, &pace_resources->resources); } @@ -1141,7 +1232,8 @@ if (!pmdaCacheLookup(INDOM(COROSYNC_RING_INDOM), i, &ring_name, (void **)&ring) || !ring) continue; - if (need_refresh[CLUSTER_COROSYNC_RING]) + if (need_refresh[CLUSTER_COROSYNC_RING] || + need_refresh[CLUSTER_COROSYNC_RING_ALL]) hacluster_refresh_corosync_ring(ring_name, &ring->rings); } @@ -1151,7 +1243,8 @@ if (!pmdaCacheLookup(INDOM(SBD_DEVICE_INDOM), i, &sbd_dev, (void **)&sbd) || !sbd) continue; - if (need_refresh[CLUSTER_SBD_DEVICE]) + if (need_refresh[CLUSTER_SBD_DEVICE] || + need_refresh[CLUSTER_SBD_DEVICE_ALL]) hacluster_refresh_sbd_device(sbd_dev, &sbd->sbd); } @@ -1161,7 +1254,8 @@ if (!pmdaCacheLookup(INDOM(DRBD_RESOURCE_INDOM), i, &resource_name, (void **)&resource) || !resource) continue; - if (need_refresh[CLUSTER_DRBD_RESOURCE]) + if (need_refresh[CLUSTER_DRBD_RESOURCE] || + need_refresh[CLUSTER_DRBD_RESOURCE_ALL]) hacluster_refresh_drbd_resource(resource_name, &resource->resource); } @@ -1171,7 +1265,8 @@ if (!pmdaCacheLookup(INDOM(DRBD_PEER_DEVICE_INDOM), i, &peer_device, (void **)&peer) || !peer) continue; - if (need_refresh[CLUSTER_DRBD_PEER_DEVICE]) + if (need_refresh[CLUSTER_DRBD_PEER_DEVICE] || + need_refresh[CLUSTER_DRBD_PEER_DEVICE_ALL]) hacluster_refresh_drbd_peer_device(peer_device, &peer->peer_device); } @@ -1228,6 +1323,9 @@ return sts; return hacluster_pacemaker_constraints_fetch(item, &constraints->location_constraints, atom); + case CLUSTER_PACEMAKER_CONSTRAINTS_ALL: + return hacluster_pacemaker_constraints_all_fetch(item, atom); + case CLUSTER_PACEMAKER_NODES: sts = pmdaCacheLookup(INDOM(PACEMAKER_NODES_INDOM), inst, NULL, (void **)&pace_nodes); if (sts < 0) @@ -1239,6 +1337,9 @@ if (sts < 0) return sts; return hacluster_pacemaker_node_attribs_fetch(item, &pace_attribs->attributes, atom); + + case CLUSTER_PACEMAKER_NODE_ATTRIB_ALL: + return hacluster_pacemaker_node_attribs_all_fetch(item, atom); case CLUSTER_PACEMAKER_RESOURCES: sts = pmdaCacheLookup(INDOM(PACEMAKER_RESOURCES_INDOM), inst, NULL, (void **)&pace_resources); @@ -1246,6 +1347,9 @@ return sts; return hacluster_pacemaker_resources_fetch(item, &pace_resources->resources, atom); + case CLUSTER_PACEMAKER_RESOURCES_ALL: + return hacluster_pacemaker_resources_all_fetch(item, atom); + case CLUSTER_COROSYNC_NODE: sts = pmdaCacheLookup(INDOM(COROSYNC_NODE_INDOM), inst, NULL, (void **)&node); if (sts < 0) @@ -1260,18 +1364,27 @@ if (sts < 0) return sts; return hacluster_corosync_ring_fetch(item, &ring->rings, atom); + + case CLUSTER_COROSYNC_RING_ALL: + return hacluster_corosync_ring_all_fetch(item, atom); case CLUSTER_SBD_DEVICE: sts = pmdaCacheLookup(INDOM(SBD_DEVICE_INDOM), inst, NULL, (void **)&sbd); if (sts < 0) return sts; return hacluster_sbd_device_fetch(item, &sbd->sbd, atom); + + case CLUSTER_SBD_DEVICE_ALL: + return hacluster_sbd_device_all_fetch(item, atom); case CLUSTER_DRBD_RESOURCE: sts = pmdaCacheLookup(INDOM(DRBD_RESOURCE_INDOM), inst, NULL, (void **)&resource); if (sts < 0) return sts; - return hacluster_drbd_resource_fetch(item, &resource->resource, atom); + return hacluster_drbd_resource_fetch(item, &resource->resource, atom); + + case CLUSTER_DRBD_RESOURCE_ALL: + return hacluster_drbd_resource_all_fetch(item, atom); case CLUSTER_DRBD_PEER_DEVICE: sts = pmdaCacheLookup(INDOM(DRBD_PEER_DEVICE_INDOM), inst, NULL, (void **)&peer); @@ -1279,6 +1392,9 @@ return sts; return hacluster_drbd_peer_device_fetch(item, &peer->peer_device, atom); + case CLUSTER_DRBD_PEER_DEVICE_ALL: + return hacluster_drbd_peer_device_all_fetch(item, atom); + default: return PM_ERR_PMID; } @@ -1286,6 +1402,220 @@ return PMDA_FETCH_STATIC; } +static int +hacluster_labelInDom(pmID pmid, pmLabelSet **lp) +{ + unsigned int cluster = pmID_cluster(pmid); + + switch (cluster) { + case CLUSTER_PACEMAKER_CONSTRAINTS_ALL: + pmdaAddLabels(lp, "{\"constraint\":\"constraint\"}"); + pmdaAddLabels(lp, "{\"node\":\"node name\"}"); + pmdaAddLabels(lp, "{\"resource\":\"resource name\"}"); + pmdaAddLabels(lp, "{\"role\":\"role of node\"}"); + pmdaAddLabels(lp, "{\"score\":\"score\"}"); + return 1; + + case CLUSTER_PACEMAKER_NODE_ATTRIB_ALL: + pmdaAddLabels(lp, "{\"name\":\"attribute name\"}"); + pmdaAddLabels(lp, "{\"node\":\"node name\"}"); + pmdaAddLabels(lp, "{\"value\":\"value\"}"); + return 1; + + case CLUSTER_PACEMAKER_RESOURCES_ALL: + pmdaAddLabels(lp, "{\"agent\":\"agent\"}"); + pmdaAddLabels(lp, "{\"clone\":\"clone\"}"); + pmdaAddLabels(lp, "{\"group\":\"group\"}"); + pmdaAddLabels(lp, "{\"managed\":\"managed\"}"); + pmdaAddLabels(lp, "{\"node\":\"node name\"}"); + pmdaAddLabels(lp, "{\"resource\":\"resource name\"}"); + pmdaAddLabels(lp, "{\"role\":\"role\"}"); + return 1; + + case CLUSTER_COROSYNC_RING_ALL: + pmdaAddLabels(lp, "{\"address\":\"ip address\"}"); + pmdaAddLabels(lp, "{\"node_id\":\"id of node\"}"); + pmdaAddLabels(lp, "{\"number\":\"ring number\"}"); + pmdaAddLabels(lp, "{\"ring_id\":\"id of ring\"}"); + return 1; + + case CLUSTER_SBD_DEVICE_ALL: + pmdaAddLabels(lp, "{\"device\":\"device\"}"); + pmdaAddLabels(lp, "{\"status\":\"status\"}"); + return 1; + + case CLUSTER_DRBD_RESOURCE_ALL: + pmdaAddLabels(lp, "{\"disk_state\":\"disk state\"}"); + pmdaAddLabels(lp, "{\"resource\":\"resource name\"}"); + pmdaAddLabels(lp, "{\"role\":\"role\"}"); + pmdaAddLabels(lp, "{\"volume\":\"volume\"}"); + return 1; + + case CLUSTER_DRBD_PEER_DEVICE_ALL: + pmdaAddLabels(lp, "{\"peer_disk_state\":\"peer disk state\"}"); + pmdaAddLabels(lp, "{\"peer_node_id\":\"peer node id\"}"); + pmdaAddLabels(lp, "{\"peer_role\":\"peer role\"}"); + pmdaAddLabels(lp, "{\"resource\":\"resource\"}"); + pmdaAddLabels(lp, "{\"volume\":\"volume\"}"); + return 1; + + default: + break; + } + return 0; +} + +static int +hacluster_label(int ident, int type, pmLabelSet **lpp, pmdaExt *pmda) +{ + int sts; + + switch (type) { + case PM_LABEL_ITEM: + if ((sts = hacluster_labelInDom((pmID)ident, lpp)) <0) + return sts; + break; + + default: + break; + } + return pmdaLabel(ident, type, lpp, pmda); +} + +static int +hacluster_labelCallBack(pmInDom indom, unsigned int inst, pmLabelSet **lp) +{ + struct location_constraints *constraints; + struct attributes *attributes; + struct resources *resources; + struct rings *ring; + struct sbd *sbd; + struct resource *resource; + struct peer_device *peer_device; + + int sts; + int no_node_attachment = 0; + char *name; + char *node_name, *attribute_name, *node, *resource_id, *tofree, *str; + + if (indom == PM_INDOM_NULL) + return 0; + + switch (pmInDom_serial(indom)) { + case PACEMAKER_CONSTRAINTS_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(PACEMAKER_CONSTRAINTS_INDOM), inst, &name, (void **)&constraints); + if (sts < 0 || sts == PMDA_CACHE_INACTIVE) + return 0; + return pmdaAddLabels(lp, "{\"constraint\":\"%s\", \"node\":\"%s\", \"resource\":\"%s\", \"role\":\"%s\", \"score\":\"%s\"}", + name, + constraints->node, + constraints->resource, + constraints->role, + constraints->score + ); + + case PACEMAKER_NODE_ATTRIB_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(PACEMAKER_NODE_ATTRIB_INDOM), inst, &name, (void **)&attributes); + if (sts < 0 || sts == PMDA_CACHE_INACTIVE) + return 0; + /* + * We need to split our combined NODE:ATTRIBUTE_NAME instance names into their + * separated NODE and ATTRIBUTE_NAME fields + */ + tofree = str = strdup(name); + attribute_name = strsep(&str, ":"); + node_name = strsep(&str, ":"); + + sts = pmdaAddLabels(lp, "{\"name\":\"%s\", \"node\":\"%s\", \"value\":\"%s\"}", + node_name, + attribute_name, + attributes->value + ); + free(tofree); + return sts; + + case PACEMAKER_RESOURCES_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(PACEMAKER_RESOURCES_INDOM), inst, &name, (void **)&resources); + if (sts < 0 || sts == PMDA_CACHE_INACTIVE) + return 0; + + if (strchr(name, ':') == NULL) { + node = (char*)name; + no_node_attachment = 1; + resource_id = ""; + } else { + tofree = str = strdup(name); + node = strsep(&str, ":"); + resource_id = strsep(&str, ":"); + } + + sts = pmdaAddLabels(lp, "{\"agent\":\"%s\", \"clone\":\"%s\", \"group\":\"%s\", \"managed\":%u, \"node\":\"%s\", \"resource\":\"%s\", \"role\":\"%s\"}", + resources->agent, + resources->clone, + resources->group, + resources->managed, + resource_id, + node, + resources->role + ); + + if (!no_node_attachment) + free(tofree); + return sts; + + case COROSYNC_RING_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(COROSYNC_RING_INDOM), inst, &name, (void **)&ring); + if (sts <0 || sts == PMDA_CACHE_INACTIVE) + return 0; + + return pmdaAddLabels(lp, "{\"address\":\"%s\", \"node_id\":%"PRIu64", \"number\":%u, \"ring_id\":\"%s\"}", + ring->address, + ring->node_id, + ring->number, + ring->ring_id + ); + + case SBD_DEVICE_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(SBD_DEVICE_INDOM), inst, &name, (void**)&sbd); + if (sts <0 || sts == PMDA_CACHE_INACTIVE) + return 0; + + return pmdaAddLabels(lp, "{\"device\":\"%s\", \"status\":\"%s\"}", + sbd->path, + sbd->status + ); + + case DRBD_RESOURCE_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(DRBD_RESOURCE_INDOM), inst, &name, (void**)&resource); + if (sts <0 || sts == PMDA_CACHE_INACTIVE) + return 0; + + return pmdaAddLabels(lp, "{\"disk_state\":\"%s\", \"resource\":\"%s\", \"role\":\"%s\", \"volume\":\"%s\"}", + resource->disk_state, + resource->resource, + resource->role, + resource->volume + ); + + case DRBD_PEER_DEVICE_ALL_INDOM: + sts = pmdaCacheLookup(INDOM(DRBD_PEER_DEVICE_INDOM), inst, &name, (void**)&peer_device); + if (sts <0 || sts == PMDA_CACHE_INACTIVE) + return 0; + + return pmdaAddLabels(lp, "{\"peer_disk_state\":\"%s\", \"peer_node_id\":\"%s\", \"peer_role\":\"%s\", \"resource\":\"%s\", \"volume\":%"PRIu32"}", + peer_device->peer_disk_state, + peer_device->peer_node_id, + peer_device->peer_role, + peer_device->resource, + peer_device->volume + ); + + default: + break; + } + return 0; +} + void hacluster_inst_setup(void) { @@ -1378,7 +1708,7 @@ int sep = pmPathSeparator(); pmsprintf(helppath, sizeof(helppath), "%s%c" "hacluster" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); - pmdaDSO(dp, PMDA_INTERFACE_4, "HACLUSTER DSO", helppath); + pmdaDSO(dp, PMDA_INTERFACE_7, "HACLUSTER DSO", helppath); } if (dp->status != 0) @@ -1391,13 +1721,15 @@ sbd_stats_setup(); drbd_stats_setup(); - dp->version.four.instance = hacluster_instance; - dp->version.four.fetch = hacluster_fetch; - dp->version.four.text = hacluster_text; - dp->version.four.pmid = hacluster_pmid; - dp->version.four.name = hacluster_name; - dp->version.four.children = hacluster_children; + dp->version.seven.instance = hacluster_instance; + dp->version.seven.fetch = hacluster_fetch; + dp->version.seven.text = hacluster_text; + dp->version.seven.pmid = hacluster_pmid; + dp->version.seven.name = hacluster_name; + dp->version.seven.children = hacluster_children; + dp->version.seven.label = hacluster_label; pmdaSetFetchCallBack(dp, hacluster_fetchCallBack); + pmdaSetLabelCallBack(dp, hacluster_labelCallBack); pmdaSetFlags(dp, PMDA_EXT_FLAG_HASHED); pmdaInit(dp, indomtable, nindoms, metrictable, nmetrics); @@ -1428,7 +1760,7 @@ pmSetProgname(argv[0]); pmsprintf(helppath, sizeof(helppath), "%s%c" "hacluster" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); - pmdaDaemon(&dispatch, PMDA_INTERFACE_4, pmGetProgname(), HACLUSTER, "hacluster.log", helppath); + pmdaDaemon(&dispatch, PMDA_INTERFACE_7, pmGetProgname(), HACLUSTER, "hacluster.log", helppath); pmdaGetOptions(argc, argv, &opts, &dispatch); if (opts.errors) { diff -Nru pcp-5.3.1/src/pmdas/hacluster/pmdahacluster.h pcp-5.3.2/src/pmdas/hacluster/pmdahacluster.h --- pcp-5.3.1/src/pmdas/hacluster/pmdahacluster.h 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/pmdahacluster.h 2021-07-30 04:05:06.000000000 +0000 @@ -23,32 +23,46 @@ #include "drbd.h" enum { - CLUSTER_PACEMAKER_GLOBAL = 0, /* 0 -- NULL INDOM */ - CLUSTER_PACEMAKER_FAIL, /* 1 -- PACEMAKER_FAIL_INDOM */ - CLUSTER_PACEMAKER_CONSTRAINTS, /* 2 -- PACEMAKER_CONSTRAINTS_INDOM */ - CLUSTER_PACEMAKER_NODES, /* 3 -- PACEMAKER_NODES_IDOM*/ - CLUSTER_PACEMAKER_NODE_ATTRIB, /* 4 -- PACEMAKER_NODE_ATRRIB_INDOM */ - CLUSTER_PACEMAKER_RESOURCES, /* 5 -- PACEMAKER_RESOURCES_INDOM */ - CLUSTER_COROSYNC_NODE, /* 6 -- COROSYNC_NODE_INDOM */ - CLUSTER_COROSYNC_GLOBAL, /* 7 -- NULL INDOM */ - CLUSTER_COROSYNC_RING, /* 8 -- COROSYNC_RING INDOM */ - CLUSTER_SBD_DEVICE, /* 9 -- SBD_DEVICES_INDOM */ - CLUSTER_DRBD_RESOURCE, /* 10 -- DRBD_RESOURCE_INDOM */ - CLUSTER_DRBD_PEER_DEVICE, /* 11 -- DRBD_PEER_DEVICE_INDOM */ + CLUSTER_PACEMAKER_GLOBAL = 0, /* 0 -- NULL INDOM */ + CLUSTER_PACEMAKER_FAIL, /* 1 -- PACEMAKER_FAIL_INDOM */ + CLUSTER_PACEMAKER_CONSTRAINTS, /* 2 -- PACEMAKER_CONSTRAINTS_INDOM */ + CLUSTER_PACEMAKER_NODES, /* 3 -- PACEMAKER_NODES_IDOM*/ + CLUSTER_PACEMAKER_NODE_ATTRIB, /* 4 -- PACEMAKER_NODE_ATRRIB_INDOM */ + CLUSTER_PACEMAKER_RESOURCES, /* 5 -- PACEMAKER_RESOURCES_INDOM */ + CLUSTER_COROSYNC_NODE, /* 6 -- COROSYNC_NODE_INDOM */ + CLUSTER_COROSYNC_GLOBAL, /* 7 -- NULL INDOM */ + CLUSTER_COROSYNC_RING, /* 8 -- COROSYNC_RING INDOM */ + CLUSTER_SBD_DEVICE, /* 9 -- SBD_DEVICES_INDOM */ + CLUSTER_DRBD_RESOURCE, /* 10 -- DRBD_RESOURCE_INDOM */ + CLUSTER_DRBD_PEER_DEVICE, /* 11 -- DRBD_PEER_DEVICE_INDOM */ + CLUSTER_PACEMAKER_CONSTRAINTS_ALL, /* 12 -- PACEMAKER_CONSTRAINTS_ALL_INDOM */ + CLUSTER_PACEMAKER_NODE_ATTRIB_ALL, /* 13 -- PACEMAKER_NODE_ATTRIB_ALL_INDOM */ + CLUSTER_PACEMAKER_RESOURCES_ALL, /* 14 -- PACEMAKER_RESOURCES_ALL_INDOM */ + CLUSTER_COROSYNC_RING_ALL, /* 15 -- COROSYNC_RING_ALL_INDOM */ + CLUSTER_SBD_DEVICE_ALL, /* 16 -- SBD_DEVICES_ALL_INDOM */ + CLUSTER_DRBD_RESOURCE_ALL, /* 17 -- DRBD_RESOURCE_ALL_INDOM */ + CLUSTER_DRBD_PEER_DEVICE_ALL, /* 18 -- DRBD_PEER_DEVICE_ALL_INDOM */ NUM_CLUSTERS }; enum { - PACEMAKER_FAIL_INDOM = 0, /* 0 -- Pacemaker failure/migrations */ - PACEMAKER_CONSTRAINTS_INDOM, /* 1 -- Pacemaker location constraints */ - PACEMAKER_NODES_INDOM, /* 2 -- Pacemaker nodes data */ - PACEMAKER_NODE_ATTRIB_INDOM, /* 3 -- Pacemaker node attributes */ - PACEMAKER_RESOURCES_INDOM, /* 4 -- Pacemaker resources */ - COROSYNC_NODE_INDOM, /* 5 -- Corosync available nodes */ - COROSYNC_RING_INDOM, /* 6 -- Corosync available rings */ - SBD_DEVICE_INDOM, /* 7 -- SBD available devices */ - DRBD_RESOURCE_INDOM, /* 8 -- DRBD Resources */ - DRBD_PEER_DEVICE_INDOM, /* 9 -- DRBD Peer Devices */ + PACEMAKER_FAIL_INDOM = 0, /* 0 -- Pacemaker failure/migrations */ + PACEMAKER_CONSTRAINTS_INDOM, /* 1 -- Pacemaker location constraints */ + PACEMAKER_NODES_INDOM, /* 2 -- Pacemaker nodes data */ + PACEMAKER_NODE_ATTRIB_INDOM, /* 3 -- Pacemaker node attributes */ + PACEMAKER_RESOURCES_INDOM, /* 4 -- Pacemaker resources */ + COROSYNC_NODE_INDOM, /* 5 -- Corosync available nodes */ + COROSYNC_RING_INDOM, /* 6 -- Corosync available rings */ + SBD_DEVICE_INDOM, /* 7 -- SBD available devices */ + DRBD_RESOURCE_INDOM, /* 8 -- DRBD Resources */ + DRBD_PEER_DEVICE_INDOM, /* 9 -- DRBD Peer Devices */ + PACEMAKER_CONSTRAINTS_ALL_INDOM, /* 10 -- Pacemaker location constraints all (labels) */ + PACEMAKER_NODE_ATTRIB_ALL_INDOM, /* 11 -- Pacemaker node attributes all(labels) */ + PACEMAKER_RESOURCES_ALL_INDOM, /* 12 -- Pacemaker resources all (labels) */ + COROSYNC_RING_ALL_INDOM, /* 13 -- Corosync available rings all (labels) */ + SBD_DEVICE_ALL_INDOM, /* 14 -- SBD available devices all (labels) */ + DRBD_RESOURCE_ALL_INDOM, /* 15 -- DRBD Resources all (labels) */ + DRBD_PEER_DEVICE_ALL_INDOM, /* 16 -- DRBD Peer Devicesall (labels) */ NUM_INDOMS }; diff -Nru pcp-5.3.1/src/pmdas/hacluster/pmns pcp-5.3.2/src/pmdas/hacluster/pmns --- pcp-5.3.1/src/pmdas/hacluster/pmns 2021-02-08 03:22:27.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/pmns 2021-07-30 04:05:06.000000000 +0000 @@ -21,131 +21,138 @@ ha_cluster.pacemaker { config_last_change HACLUSTER:0:0 - fail_count HACLUSTER:1:0 + fail_count HACLUSTER:1:0 location_constraints migration_threshold HACLUSTER:1:1 nodes node_attributes HACLUSTER:4:0 + node_attributes_all HACLUSTER:13:0 resources stonith_enabled HACLUSTER:0:1 } ha_cluster.pacemaker.location_constraints { - node HACLUSTER:2:0 - resource HACLUSTER:2:1 - role HACLUSTER:2:2 - score HACLUSTER:2:3 + node HACLUSTER:2:0 + resource HACLUSTER:2:1 + role HACLUSTER:2:2 + score HACLUSTER:2:3 + all HACLUSTER:12:0 } ha_cluster.pacemaker.nodes { status - type HACLUSTER:3:9 + type HACLUSTER:3:9 } ha_cluster.pacemaker.nodes.status { - online HACLUSTER:3:0 - standby HACLUSTER:3:1 + online HACLUSTER:3:0 + standby HACLUSTER:3:1 standby_on_fail HACLUSTER:3:2 - maintenance HACLUSTER:3:3 - pending HACLUSTER:3:4 - unclean HACLUSTER:3:5 - shutdown HACLUSTER:3:6 - expected_up HACLUSTER:3:7 - dc HACLUSTER:3:8 + maintenance HACLUSTER:3:3 + pending HACLUSTER:3:4 + unclean HACLUSTER:3:5 + shutdown HACLUSTER:3:6 + expected_up HACLUSTER:3:7 + dc HACLUSTER:3:8 } ha_cluster.pacemaker.resources { - agent HACLUSTER:5:0 - clone HACLUSTER:5:1 - group HACLUSTER:5:2 - managed HACLUSTER:5:3 - role HACLUSTER:5:4 + agent HACLUSTER:5:0 + clone HACLUSTER:5:1 + group HACLUSTER:5:2 + managed HACLUSTER:5:3 + role HACLUSTER:5:4 status + all HACLUSTER:14:0 } ha_cluster.pacemaker.resources.status { - active HACLUSTER:5:5 - orphaned HACLUSTER:5:6 - blocked HACLUSTER:5:7 - failed HACLUSTER:5:8 + active HACLUSTER:5:5 + orphaned HACLUSTER:5:6 + blocked HACLUSTER:5:7 + failed HACLUSTER:5:8 failure_ignored HACLUSTER:5:9 } ha_cluster.corosync { member_votes - quorate HACLUSTER:7:0 + quorate HACLUSTER:7:0 quorum_votes - ring_errors HACLUSTER:7:5 + ring_errors HACLUSTER:7:5 rings } ha_cluster.corosync.member_votes { - votes HACLUSTER:6:0 - local HACLUSTER:6:1 - node_id HACLUSTER:6:2 + votes HACLUSTER:6:0 + local HACLUSTER:6:1 + node_id HACLUSTER:6:2 } ha_cluster.corosync.quorum_votes { expected_votes HACLUSTER:7:1 highest_expected HACLUSTER:7:2 - total_votes HACLUSTER:7:3 - quorum HACLUSTER:7:4 + total_votes HACLUSTER:7:3 + quorum HACLUSTER:7:4 } ha_cluster.corosync.rings { - status HACLUSTER:8:0 - address HACLUSTER:8:1 - node_id HACLUSTER:8:2 - number HACLUSTER:8:3 - ring_id HACLUSTER:8:4 + status HACLUSTER:8:0 + address HACLUSTER:8:1 + node_id HACLUSTER:8:2 + number HACLUSTER:8:3 + ring_id HACLUSTER:8:4 + all HACLUSTER:15:0 } ha_cluster.sbd { devices timeouts + all HACLUSTER:16:0 } ha_cluster.sbd.devices { - path HACLUSTER:9:0 - status HACLUSTER:9:1 + path HACLUSTER:9:0 + status HACLUSTER:9:1 } ha_cluster.sbd.timeouts { - mgswait HACLUSTER:9:2 - allocate HACLUSTER:9:3 - loop HACLUSTER:9:4 - watchdog HACLUSTER:9:5 + mgswait HACLUSTER:9:2 + allocate HACLUSTER:9:3 + loop HACLUSTER:9:4 + watchdog HACLUSTER:9:5 } ha_cluster.drbd { - resources - written HACLUSTER:10:4 - read HACLUSTER:10:5 - al_writes HACLUSTER:10:6 - bm_writes HACLUSTER:10:7 + resources + written HACLUSTER:10:4 + read HACLUSTER:10:5 + al_writes HACLUSTER:10:6 + bm_writes HACLUSTER:10:7 upper_pending HACLUSTER:10:8 lower_pending HACLUSTER:10:9 - quorum HACLUSTER:10:10 + quorum HACLUSTER:10:10 connections connections_sync HACLUSTER:11:5 - connections_received HACLUSTER:11:6 + connections_received HACLUSTER:11:6 connections_sent HACLUSTER:11:7 connections_pending HACLUSTER:11:8 connections_unacked HACLUSTER:11:9 - split_brain HACLUSTER:10:11 + split_brain HACLUSTER:10:11 } ha_cluster.drbd.resources { - resource HACLUSTER:10:0 - role HACLUSTER:10:1 - volume HACLUSTER:10:2 - disk_state HACLUSTER:10:3 + resource HACLUSTER:10:0 + role HACLUSTER:10:1 + volume HACLUSTER:10:2 + disk_state HACLUSTER:10:3 + all HACLUSTER:17:0 } ha_cluster.drbd.connections { - resource HACLUSTER:11:0 + resource HACLUSTER:11:0 peer_node_id HACLUSTER:11:1 - peer_role HACLUSTER:11:2 - volume HACLUSTER:11:3 + peer_role HACLUSTER:11:2 + volume HACLUSTER:11:3 peer_disk_state HACLUSTER:11:4 + all HACLUSTER:18:0 } diff -Nru pcp-5.3.1/src/pmdas/hacluster/sbd.c pcp-5.3.2/src/pmdas/hacluster/sbd.c --- pcp-5.3.1/src/pmdas/hacluster/sbd.c 2021-04-12 03:55:40.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/sbd.c 2021-07-30 04:05:06.000000000 +0000 @@ -68,6 +68,13 @@ return PMDA_FETCH_NOVALUES; } +int +hacluster_sbd_device_all_fetch(int item, pmAtomValue *atom) +{ + atom->ul = 1; /* Assign default exists value 1 */ + return PMDA_FETCH_STATIC; +} + int hacluster_refresh_sbd_device(const char *sbd_dev, struct sbd *sbd) { diff -Nru pcp-5.3.1/src/pmdas/hacluster/sbd.h pcp-5.3.2/src/pmdas/hacluster/sbd.h --- pcp-5.3.1/src/pmdas/hacluster/sbd.h 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/hacluster/sbd.h 2021-07-30 04:05:06.000000000 +0000 @@ -37,6 +37,7 @@ }; extern int hacluster_sbd_device_fetch(int, struct sbd *, pmAtomValue *); +extern int hacluster_sbd_device_all_fetch(int, pmAtomValue *); extern int hacluster_refresh_sbd_device(const char *, struct sbd *); extern void sbd_stats_setup(void); diff -Nru pcp-5.3.1/src/pmdas/kvm/pmdakvm.1 pcp-5.3.2/src/pmdas/kvm/pmdakvm.1 --- pcp-5.3.1/src/pmdas/kvm/pmdakvm.1 2020-10-28 06:10:31.000000000 +0000 +++ pcp-5.3.2/src/pmdas/kvm/pmdakvm.1 2021-07-30 04:05:06.000000000 +0000 @@ -1,6 +1,6 @@ '\"macro stdmacro .\" -.\" Copyright (c) 2020 Red Hat. +.\" Copyright (c) 2020-2021 Red Hat. .\" Copyright (c) 2008 Aconex. All Rights Reserved. .\" .\" This program is free software; you can redistribute it and/or modify it @@ -55,6 +55,20 @@ \fBpmdakvm\fR is launched by \fIpmcd\fR(1) and should never be executed directly. The Install and Remove scripts notify \fIpmcd\fR(1) when the agent is installed or removed. +.SH CAVEATS +When +.B pmdakvm +is running, it holds references to kernel resources within the KVM +device driver. +It is thus not possible to unload or reload the device driver module +while the PMDA is running. +The ideal procedure to follow in order to reload the kernel module is +the reverse of that described in the ``INSTALLATION'' section above - +i.e. first run +.BR ./Remove , +then reload the kernel module, +then run +.BR ./Install . .SH FILES .IP "\fB$PCP_SYSCONF_DIR/kvm/kvm.conf\fR" 4 configuration file for the \fBpmdakvm\fR agent diff -Nru pcp-5.3.1/src/pmdas/linux/pmda.c pcp-5.3.2/src/pmdas/linux/pmda.c --- pcp-5.3.1/src/pmdas/linux/pmda.c 2021-04-13 23:37:26.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux/pmda.c 2021-07-30 04:05:06.000000000 +0000 @@ -8719,8 +8719,10 @@ _pm_assign_ulong(atom, proc_buddyinfo.buddys[inst].value); break; case 1: - atom->ull = proc_buddyinfo.buddys[inst].value << _pm_pageshift; - atom->ull /= 1024; /* convert to kilobytes */ + atom->ull = (unsigned long long)proc_buddyinfo.buddys[inst].value; + atom->ull <<= proc_buddyinfo.buddys[inst].order; + atom->ull <<= _pm_pageshift; + atom->ull >>= 10; /* convert to kilobytes */ break; default: return PM_ERR_PMID; diff -Nru pcp-5.3.1/src/pmdas/linux/proc_buddyinfo.c pcp-5.3.2/src/pmdas/linux/proc_buddyinfo.c --- pcp-5.3.1/src/pmdas/linux/proc_buddyinfo.c 2019-08-16 01:19:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux/proc_buddyinfo.c 2021-07-30 04:05:06.000000000 +0000 @@ -137,14 +137,14 @@ while (fgets(buf,sizeof(buf),fp) != NULL) { char node_name[128]; char *zone_name; - int values[SPLIT_MAX]; + unsigned int values[SPLIT_MAX]; i = read_node_name(buf, node_name); i+=6; /* erase ", zone" */ read_buddyinfo(buf+i, read_buf, MAX_ORDER+1); /* read zone name and page order */ zone_name=read_buf[0]; for (i=0; i < MAX_ORDER; i++) - values[i] = atoi(read_buf[i+1]); + values[i] = strtoul(read_buf[i+1], NULL, 10); for (i=0; i < proc_buddyinfo->nbuddys; i++) { if (strcmp(proc_buddyinfo->buddys[i].node_name, node_name)==0 && strcmp(proc_buddyinfo->buddys[i].zone_name, zone_name)==0) diff -Nru pcp-5.3.1/src/pmdas/linux/proc_buddyinfo.h pcp-5.3.2/src/pmdas/linux/proc_buddyinfo.h --- pcp-5.3.1/src/pmdas/linux/proc_buddyinfo.h 2019-08-16 01:19:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux/proc_buddyinfo.h 2021-07-30 04:05:06.000000000 +0000 @@ -18,18 +18,18 @@ * All fields in /proc/buddyinfo */ typedef struct { - int id; - char id_name[128]; - char node_name[128]; - char zone_name[128]; - int order; - int value; + int id; + char id_name[128]; + char node_name[128]; + char zone_name[128]; + unsigned int order; + unsigned int value; } buddyinfo_t; typedef struct { - int nbuddys; - buddyinfo_t *buddys; - pmdaIndom *indom; + unsigned int nbuddys; + buddyinfo_t *buddys; + pmdaIndom *indom; } proc_buddyinfo_t; extern int refresh_proc_buddyinfo(proc_buddyinfo_t *); diff -Nru pcp-5.3.1/src/pmdas/linux_proc/clusters.h pcp-5.3.2/src/pmdas/linux_proc/clusters.h --- pcp-5.3.1/src/pmdas/linux_proc/clusters.h 2020-08-06 23:53:46.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_proc/clusters.h 2021-07-30 04:05:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014,2018-2020 Red Hat. + * Copyright (c) 2013-2014,2018-2021 Red Hat. * Copyright (c) 2005,2007-2008 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ #define CLUSTER_HOTPROC_GLOBAL 60 /* overall hotproc stats and controls*/ #define CLUSTER_HOTPROC_PRED 61 /* derived hotproc metrics */ -#define CLUSTER_PID_OOM_SCORE 62 /* /proc//oom_score */ +#define CLUSTER_PID_OOM_SCORE 62 /* /proc//oom_score */ #define CLUSTER_HOTPROC_PID_OOM_SCORE 63 /* /proc//oom_score */ #define CLUSTER_CGROUP2_CPU_PRESSURE 64 @@ -63,7 +63,12 @@ #define CLUSTER_ACCT 70 +#define CLUSTER_PID_EXE 69 /* /proc//exe */ +#define CLUSTER_HOTPROC_PID_EXE 71 /* /proc//exe */ +#define CLUSTER_PID_CWD 72 /* /proc//cwd */ +#define CLUSTER_HOTPROC_PID_CWD 73 /* /proc//cwd */ + #define MIN_CLUSTER 8 /* first cluster number we use here */ -#define MAX_CLUSTER 71 /* one more than highest cluster number used */ +#define MAX_CLUSTER 74 /* one more than highest cluster number used */ #endif /* _CLUSTERS_H */ diff -Nru pcp-5.3.1/src/pmdas/linux_proc/help_text.h pcp-5.3.2/src/pmdas/linux_proc/help_text.h --- pcp-5.3.1/src/pmdas/linux_proc/help_text.h 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_proc/help_text.h 2021-07-30 04:05:06.000000000 +0000 @@ -77,6 +77,8 @@ { .name = "psinfo.cguest_time", .shorthelp = "Guest time of the process’s children", .longhelp = "" }, { .name = "psinfo.environ", .shorthelp = "process environment (from /proc//environ ascii space replaces null).", .longhelp = "" }, { .name = "psinfo.labels", .shorthelp = "list of processes security labels (from /proc//attr/current)", .longhelp = "" }, +{ .name = "psinfo.cwd", .shorthelp = "current working directory (from /proc//cwd)", .longhelp = "" }, +{ .name = "psinfo.exe", .shorthelp = "current process executable (from /proc//exe)", .longhelp = "" }, { .name = "psinfo.oom_score", .shorthelp = "out-of-memory process selection score (from /proc//oom_score)", .longhelp = "" }, { .name = "psinfo.blocked", .shorthelp = "the value in the blocked field of struct task_struct for the process", .longhelp = "" }, { .name = "cgroup.subsys.hierarchy", .shorthelp = "subsystem hierarchy from /proc/cgroups", .longhelp = "" }, diff -Nru pcp-5.3.1/src/pmdas/linux_proc/pmda.c pcp-5.3.2/src/pmdas/linux_proc/pmda.c --- pcp-5.3.1/src/pmdas/linux_proc/pmda.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_proc/pmda.c 2021-07-30 04:05:06.000000000 +0000 @@ -399,6 +399,12 @@ /* proc.psinfo.oom_score */ { NULL, { PMDA_PMID(CLUSTER_PID_OOM_SCORE, 0), PM_TYPE_U32, PROC_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0)}}, +/* proc.psinfo.cwd */ + { NULL, { PMDA_PMID(CLUSTER_PID_CWD, 0), PM_TYPE_STRING, PROC_INDOM, + PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0)}}, +/* proc.psinfo.exe */ + { NULL, { PMDA_PMID(CLUSTER_PID_EXE, 0), PM_TYPE_STRING, PROC_INDOM, + PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0)}}, /* proc.memory.size */ { NULL, { PMDA_PMID(CLUSTER_PID_STATM,0), PM_TYPE_U32, PROC_INDOM, PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) } }, @@ -1392,6 +1398,8 @@ need_refresh[CLUSTER_PID_CGROUP] || need_refresh[CLUSTER_PID_SCHEDSTAT] || need_refresh[CLUSTER_PID_OOM_SCORE] || + need_refresh[CLUSTER_PID_CWD] || + need_refresh[CLUSTER_PID_EXE] || need_refresh[CLUSTER_PID_FD] || need_refresh[CLUSTER_PROC_RUNQ]) { refresh_proc_pid(&proc_pid, @@ -1409,6 +1417,8 @@ need_refresh[CLUSTER_HOTPROC_PID_CGROUP] || need_refresh[CLUSTER_HOTPROC_PID_SCHEDSTAT] || need_refresh[CLUSTER_HOTPROC_PID_OOM_SCORE] || + need_refresh[CLUSTER_HOTPROC_PID_CWD] || + need_refresh[CLUSTER_HOTPROC_PID_EXE] || need_refresh[CLUSTER_HOTPROC_PID_FD] || need_refresh[CLUSTER_HOTPROC_GLOBAL] || need_refresh[CLUSTER_HOTPROC_PRED]){ @@ -1436,6 +1446,8 @@ need_refresh[CLUSTER_PID_CGROUP]++; need_refresh[CLUSTER_PID_SCHEDSTAT]++; need_refresh[CLUSTER_PID_OOM_SCORE]++; + need_refresh[CLUSTER_PID_EXE]++; + need_refresh[CLUSTER_PID_CWD]++; need_refresh[CLUSTER_PID_IO]++; need_refresh[CLUSTER_PID_FD]++; break; @@ -1447,6 +1459,8 @@ need_refresh[CLUSTER_HOTPROC_PID_CGROUP]++; need_refresh[CLUSTER_HOTPROC_PID_SCHEDSTAT]++; need_refresh[CLUSTER_HOTPROC_PID_OOM_SCORE]++; + need_refresh[CLUSTER_HOTPROC_PID_EXE]++; + need_refresh[CLUSTER_HOTPROC_PID_CWD]++; need_refresh[CLUSTER_HOTPROC_PID_IO]++; need_refresh[CLUSTER_HOTPROC_PID_FD]++; need_refresh[CLUSTER_HOTPROC_GLOBAL]++; @@ -3254,6 +3268,34 @@ else return PM_ERR_PMID; break; + + case CLUSTER_HOTPROC_PID_CWD: + active_proc_pid = &hotproc_pid; + /*FALLTHROUGH*/ + case CLUSTER_PID_CWD: + if (!have_access) + return PM_ERR_PERMISSION; + if ((entry = fetch_proc_pid_cwd(inst, active_proc_pid, &sts)) == NULL) + return sts; + if (item == 0) /* proc.psinfo.cwd */ + atom->cp = proc_strings_lookup(entry->cwd_id); + else + return PM_ERR_PMID; + break; + + case CLUSTER_HOTPROC_PID_EXE: + active_proc_pid = &hotproc_pid; + /*FALLTHROUGH*/ + case CLUSTER_PID_EXE: + if (!have_access) + return PM_ERR_PERMISSION; + if ((entry = fetch_proc_pid_exe(inst, active_proc_pid, &sts)) == NULL) + return sts; + if (item == 0) /* proc.psinfo.exe */ + atom->cp = proc_strings_lookup(entry->exe_id); + else + return PM_ERR_PMID; + break; case CLUSTER_ACCT: return acct_fetchCallBack(inst, item, &proc_acct, atom); diff -Nru pcp-5.3.1/src/pmdas/linux_proc/proc_dynamic.c pcp-5.3.2/src/pmdas/linux_proc/proc_dynamic.c --- pcp-5.3.1/src/pmdas/linux_proc/proc_dynamic.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_proc/proc_dynamic.c 2021-07-30 04:05:06.000000000 +0000 @@ -65,6 +65,8 @@ { CLUSTER_PID_FD, CLUSTER_HOTPROC_PID_FD }, { CLUSTER_PID_OOM_SCORE, CLUSTER_HOTPROC_PID_OOM_SCORE }, { CLUSTER_PID_SMAPS, CLUSTER_HOTPROC_PID_SMAPS }, + { CLUSTER_PID_EXE, CLUSTER_HOTPROC_PID_EXE }, + { CLUSTER_PID_CWD, CLUSTER_HOTPROC_PID_CWD }, }; @@ -146,6 +148,8 @@ { .name = "ngid", .cluster = CLUSTER_PID_STATUS, .item=32 }, { .name = "tgid", .cluster = CLUSTER_PID_STATUS, .item=41 }, { .name = "oom_score", .cluster = CLUSTER_PID_OOM_SCORE, .item=0 }, + { .name = "exe", .cluster = CLUSTER_PID_EXE, .item=0 }, + { .name = "cwd", .cluster = CLUSTER_PID_CWD, .item=0 }, }; static dynproc_metric_t id_metrics[] = { diff -Nru pcp-5.3.1/src/pmdas/linux_proc/proc_pid.c pcp-5.3.2/src/pmdas/linux_proc/proc_pid.c --- pcp-5.3.1/src/pmdas/linux_proc/proc_pid.c 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_proc/proc_pid.c 2021-07-30 04:05:06.000000000 +0000 @@ -588,7 +588,7 @@ len--; } - strncpy(vars.fname, cmd, sizeof(vars.fname)); + strncpy(vars.fname, cmd, sizeof(vars.fname)-1); if (len < sizeof(vars.fname) && parens && cmd[len-1] == ')') vars.fname[len-1] = '\0'; /* skip closing parenthesis */ vars.fname[sizeof(vars.fname) - 1] = '\0'; @@ -1088,6 +1088,31 @@ return dir; } +static int +proc_readlink(const char *base, proc_pid_entry_t *ep, size_t *lenp, char **bufp) +{ + char buf[1024]; + int sts; + + if (*lenp < MAXPATHLEN) { + if ((*bufp = (char *)realloc(*bufp, MAXPATHLEN)) == NULL) + return -ENOMEM; + *lenp = MAXPATHLEN; + } + pmsprintf(buf, sizeof(buf), "%s/proc/%d/%s", proc_statspath, ep->id, base); + if ((sts = readlink(buf, *bufp, *lenp)) <= 0) { + if (sts < 0) /* expected for kernel threads */ + sts = 0; + if (pmDebugOptions.appl1 && pmDebugOptions.desperate) + fprintf(stderr, "%s: readlink(\"%s\") failed: %s\n", + "proc_readlink", buf, pmErrStr(-oserror())); + (*bufp)[0] = '\0'; + return sts; + } + (*bufp)[sts] = '\0'; + return sts; +} + /* * error mapping for fetch routines ... * EACCESS, EINVAL => no values (don't disclose anything else) @@ -2150,3 +2175,71 @@ } return (*sts < 0) ? NULL : ep; } + +static int +refresh_proc_pid_cwd(proc_pid_entry_t *ep) +{ + int sts; + + if (ep->flags & PROC_PID_FLAG_CWD_SUCCESS) + return 0; + if ((sts = proc_readlink("cwd", ep, &procbuflen, &procbuf)) >= 0) { + ep->cwd_id = proc_strings_insert(procbuf); + ep->flags |= PROC_PID_FLAG_CWD_SUCCESS; + } + return sts; +} + +/* + * fetch a proc//cwd value for pid + */ +proc_pid_entry_t * +fetch_proc_pid_cwd(int id, proc_pid_t *proc_pid, int *sts) +{ + proc_pid_entry_t *ep = proc_pid_entry_lookup(id, proc_pid); + + *sts = 0; + if (!ep) + return NULL; + + if (!(ep->flags & PROC_PID_FLAG_CWD_FETCHED)) { + *sts = refresh_proc_pid_cwd(ep); + ep->flags |= PROC_PID_FLAG_CWD_FETCHED; + } + + return (*sts < 0) ? NULL : ep; +} + +static int +refresh_proc_pid_exe(proc_pid_entry_t *ep) +{ + int sts; + + if (ep->flags & PROC_PID_FLAG_EXE_SUCCESS) + return 0; + if ((sts = proc_readlink("exe", ep, &procbuflen, &procbuf)) >= 0) { + ep->exe_id = proc_strings_insert(procbuf); + ep->flags |= PROC_PID_FLAG_EXE_SUCCESS; + } + return sts; +} + +/* + * fetch a proc//exe value for pid + */ +proc_pid_entry_t * +fetch_proc_pid_exe(int id, proc_pid_t *proc_pid, int *sts) +{ + proc_pid_entry_t *ep = proc_pid_entry_lookup(id, proc_pid); + + *sts = 0; + if (!ep) + return NULL; + + if (!(ep->flags & PROC_PID_FLAG_EXE_FETCHED)) { + *sts = refresh_proc_pid_exe(ep); + ep->flags |= PROC_PID_FLAG_EXE_FETCHED; + } + + return (*sts < 0) ? NULL : ep; +} diff -Nru pcp-5.3.1/src/pmdas/linux_proc/proc_pid.h pcp-5.3.2/src/pmdas/linux_proc/proc_pid.h --- pcp-5.3.1/src/pmdas/linux_proc/proc_pid.h 2021-05-20 00:59:58.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_proc/proc_pid.h 2021-07-30 04:05:06.000000000 +0000 @@ -217,6 +217,8 @@ PROC_PID_FLAG_ENVIRON_FETCHED = 1<<11, PROC_PID_FLAG_OOM_SCORE_FETCHED = 1<<12, PROC_PID_FLAG_SMAPS_FETCHED = 1<<13, + PROC_PID_FLAG_CWD_FETCHED = 1<<14, + PROC_PID_FLAG_EXE_FETCHED = 1<<15, PROC_PID_FLAG_STAT_SUCCESS = 1<<16, PROC_PID_FLAG_STATM_SUCCESS = 1<<17, @@ -231,6 +233,8 @@ PROC_PID_FLAG_ENVIRON_SUCCESS = 1<<26, PROC_PID_FLAG_OOM_SCORE_SUCCESS = 1<<27, PROC_PID_FLAG_SMAPS_SUCCESS = 1<<28, + PROC_PID_FLAG_CWD_SUCCESS = 1<<29, + PROC_PID_FLAG_EXE_SUCCESS = 1<<30, }; typedef struct { @@ -277,6 +281,12 @@ /* /proc//oom_score cluster */ uint32_t oom_score; + /* /proc//cwd cluster */ + int cwd_id; + + /* /proc//exe cluster */ + int exe_id; + /* /proc//smaps_rollup cluster */ proc_pid_smaps_t smaps; } proc_pid_entry_t; @@ -356,4 +366,10 @@ /* fetch a proc//oom_score entry for pid */ extern proc_pid_entry_t *fetch_proc_pid_oom_score(int, proc_pid_t *, int *); +/* fetch a proc//cwd entry for pid */ +extern proc_pid_entry_t *fetch_proc_pid_cwd(int, proc_pid_t *, int *); + +/* fetch a proc//exe entry for pid */ +extern proc_pid_entry_t *fetch_proc_pid_exe(int, proc_pid_t *, int *); + #endif /* _PROC_PID_H */ diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/filter.conf pcp-5.3.2/src/pmdas/linux_sockets/filter.conf --- pcp-5.3.1/src/pmdas/linux_sockets/filter.conf 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/filter.conf 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,9 @@ +# This file specifies the initial ss filter used by pmdasockets(1). +# This filter can be overridden by storing a new filter, for example: +# pmstore network.persocket.filter "state established" +# If the default is overridden with a pmstore, it only remains in +# effect until the PMDA is restarted. To persist a filter, edit this +# file. For details of filters, see ss(8). + +# current initial (persisted) filter: +state connected diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/GNUmakefile pcp-5.3.2/src/pmdas/linux_sockets/GNUmakefile --- pcp-5.3.1/src/pmdas/linux_sockets/GNUmakefile 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/GNUmakefile 2021-07-30 04:05:06.000000000 +0000 @@ -23,6 +23,7 @@ PMDAINIT = $(IAM)_init PMDATMPDIR = $(PCP_PMDAS_DIR)/$(IAM) PMDAADMDIR = $(PCP_PMDASADM_DIR)/$(IAM) +PMDACONFIG = $(PCP_SYSCONF_DIR)/$(IAM) PMIEDIR = $(PCP_SYSCONF_DIR)/pmieconf/$(IAM) PMIEVARDIR = $(PCP_VAR_DIR)/config/pmieconf/$(IAM) @@ -32,6 +33,7 @@ LCFLAGS = $(INVISIBILITY) SCRIPTS = Install Remove Upgrade +CONF = filter.conf VERSION_SCRIPT = exports LDIRT = domain.h $(VERSION_SCRIPT) $(IAM).log @@ -49,6 +51,8 @@ install: default $(INSTALL) -m 755 -d $(PMDAADMDIR) $(INSTALL) -m 755 -d $(PMDATMPDIR) + $(INSTALL) -m 755 -d $(PMDACONFIG) + $(INSTALL) -m 644 -t $(PMDATMPDIR)/$(CONF) $(CONF) $(PMDACONFIG)/$(CONF) $(INSTALL) -m 755 -t $(PMDATMPDIR) $(LIBTARGET) $(CMDTARGET) $(SCRIPTS) $(PMDAADMDIR) $(INSTALL) -m 644 -t $(PMDATMPDIR) domain.h help $(PMNSFILES) $(PMDAADMDIR) @$(INSTALL_MAN) diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/help pcp-5.3.2/src/pmdas/linux_sockets/help --- pcp-5.3.1/src/pmdas/linux_sockets/help 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/help 2021-07-30 04:05:06.000000000 +0000 @@ -120,11 +120,15 @@ an estimate of current connection performance by excluding periods when the connection was idle due to lack of application data to send. -@ network.persocket.delivered +@ network.persocket.delivered data segments and retransmits delivered to the receiver +Data segments delivered to the receiver including retransmits, as reported by +returning ACKs, used by ECN. Kernel: delivered in include/linux/tcp.h @ network.persocket.app_limited TCP flows are limited with application-limiting -@ network.persocket.reord_seen +@ network.persocket.reord_seen received ACKs that were out of order +Received ACKs that were out of order. Estimates reordering on the +return path. Kernel: reord_seen @ network.persocket.busy TCP connection is busy?? diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/Install pcp-5.3.2/src/pmdas/linux_sockets/Install --- pcp-5.3.1/src/pmdas/linux_sockets/Install 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/Install 2021-07-30 04:05:06.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/sh +#!/bin/sh # # Copyright (c) 2021 Red Hat. # @@ -19,12 +19,6 @@ . $PCP_SHARE_DIR/lib/pmdaproc.sh iam=sockets - -# preferred: DSO -dso_opt=true -pipe_opt=false -daemon_opt=false - pmns_name=network.persocket # differs to PMDA name which ss >/dev/null 2>&1 diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/pmda.c pcp-5.3.2/src/pmdas/linux_sockets/pmda.c --- pcp-5.3.1/src/pmdas/linux_sockets/pmda.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/pmda.c 2021-07-30 04:05:06.000000000 +0000 @@ -188,6 +188,36 @@ } /* + * Load the initial filter from filter.conf. This may subsequently be + * overridden by pmstore network.persocket.filter ... + */ +static void +load_filter_config(void) +{ + FILE *fp; + int sep = pmPathSeparator(); + char *p; + char filterpath[MAXPATHLEN]; + char buf[MAXPATHLEN]; + + pmsprintf(filterpath, sizeof(filterpath), "%s%c" "sockets" "%c" "filter.conf", + pmGetConfig("PCP_SYSCONF_DIR"), sep, sep); + if ((fp = fopen(filterpath, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (buf[0] == '#' || buf[0] == '\n') + continue; + if ((p = strrchr(buf, '\n')) != NULL) + *p = '\0'; + ss_filter = strndup(buf, sizeof(buf)); + break; + } + fclose(fp); + } + if (pmDebugOptions.appl0) + pmNotifyErr(LOG_DEBUG, "loaded %s = \"%s\"\n", filterpath, ss_filter ? ss_filter : ""); +} + +/* * Initialise the agent (both daemon and DSO). */ void @@ -207,6 +237,9 @@ if (dp->status != 0) return; + /* load the initial filter */ + load_filter_config(); + int nindoms = sizeof(indomtable)/sizeof(indomtable[0]); if (dp->status != 0) diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/pmdasockets.1 pcp-5.3.2/src/pmdas/linux_sockets/pmdasockets.1 --- pcp-5.3.1/src/pmdas/linux_sockets/pmdasockets.1 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/pmdasockets.1 2021-07-30 04:05:06.000000000 +0000 @@ -65,12 +65,19 @@ IP addresses and other options that .B pmdasockets will collect (to populate it's instance domain). -By default, this is +This is loaded on PMDA startup from the file +.B $(PCP_SYSCONF_DIR)/sockets/filter.conf +(typically +.BR /etc/pcp/sockets/filter.conf ) +and defaults to .B state connected meaning only sockets in the .B connected state will be included. -This can be changed dynamically by using +This can be changed persistently by editing +.BR filter.conf +as the root user. +The filter can also be changed dynamically after the PMDA has started by using .BR pmstore (1) to store a new filter string in the .B network.persocket.filter @@ -87,8 +94,8 @@ .RE .sp 1 will change the filter to include sockets in all states. -Note that the filter string is not persisted across PMDA restarts or reboots -(this may change in the future). +Note a dynamically stored filter is not persisted across PMDA restarts or reboots +(edit the config file for a persistent change). For further details of the filter syntax and options, consult .BR ss (8). .SH LOGGING CONFIGURATION diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/Remove pcp-5.3.2/src/pmdas/linux_sockets/Remove --- pcp-5.3.1/src/pmdas/linux_sockets/Remove 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/Remove 2021-07-30 04:05:06.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/sh +#!/bin/sh # # Copyright (c) 2021 Red Hat. # diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/ss_parse.c pcp-5.3.2/src/pmdas/linux_sockets/ss_parse.c --- pcp-5.3.1/src/pmdas/linux_sockets/ss_parse.c 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/ss_parse.c 2021-07-30 04:05:06.000000000 +0000 @@ -180,20 +180,31 @@ sscanf(p, "%lf/%lf", &s->round_trip_rtt, &s->round_trip_rttvar); } +/* + * parse one line - socket instance + */ int -ss_parse(char *line, ss_stats_t *ss) +ss_parse(char *line, int has_state_field, ss_stats_t *ss) { int i; char *r, *s, *p = line; int sts = 0; memset(&ss_p, 0, sizeof(ss_p)); - sscanf(line, "%s %s %u %u %s %s", - ss_p.netid, ss_p.state, &ss_p.sendq, &ss_p.recvq, ss_p.src, ss_p.dst); - - /* skip first 6 fields, already scanned (above) */ - for (i=0; i < 6; i++) - p = skip(p, ' '); + if (has_state_field) { + sscanf(line, "%s %s %u %u %s %s", + ss_p.netid, ss_p.state, &ss_p.sendq, &ss_p.recvq, ss_p.src, ss_p.dst); + for (i=0; i < 6; i++) + p = skip(p, ' '); + + } else { + /* Some filters cause ss to omit the State column */ + strcpy(ss_p.state, "FILTER"); + sscanf(line, "%s %u %u %s %s", + ss_p.netid, &ss_p.sendq, &ss_p.recvq, ss_p.src, ss_p.dst); + for (i=0; i < 5; i++) + p = skip(p, ' '); + } for (i=0; parse_table[i].field != NULL; i++) parse_table[i].found = 0; @@ -256,12 +267,14 @@ p = skip(p, ' '); } -#if DEBUG - fprintf(stderr, "\nLINE:%s", line); - for (i=0; parse_table[i].field != NULL; i++) - if (parse_table[i].found) - fprintf(stderr, "Found %s\n", parse_table[i].field); -#endif + if (pmDebugOptions.appl1) { + pmNotifyErr(LOG_DEBUG, "\nLINE:%s", line); + if (pmDebugOptions.desperate) { + for (i=0; parse_table[i].field != NULL; i++) + if (parse_table[i].found) + fprintf(stderr, "Found %s\n", parse_table[i].field); + } + } extract_subfields(&ss_p); *ss = ss_p; /* struct assign */ diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/ss_refresh.c pcp-5.3.2/src/pmdas/linux_sockets/ss_refresh.c --- pcp-5.3.1/src/pmdas/linux_sockets/ss_refresh.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/ss_refresh.c 2021-07-30 04:05:06.000000000 +0000 @@ -39,6 +39,7 @@ int sts = 0; ss_stats_t *ss, parsed_ss; int inst; + int has_state_field; char instname[128]; char line[4096] = {0}; @@ -48,16 +49,30 @@ /* invalidate all cache entries */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); + has_state_field = 0; + memset(&parsed_ss, 0, sizeof(parsed_ss)); while (fgets(line, sizeof(line), fp) != NULL) { - ss_parse(line, &parsed_ss); + /* check the header */ + if (strncmp(line, "Netid", 5) == 0) { + if (strncmp(line, "Netid State", 11) == 0) { + has_state_field = 1; + } + continue; + } + + ss_parse(line, has_state_field, &parsed_ss); ss_instname(&parsed_ss, instname, sizeof(instname)); - if (parsed_ss.state[0] == '\0') - continue; /* transient with no state, ignore */ ss = NULL; sts = pmdaCacheLookupName(indom, instname, &inst, (void **)&ss); if (sts < 0 || ss == NULL) { /* new entry */ - ss = (ss_stats_t *)malloc(sizeof(ss_stats_t)); + if (ss == NULL) + ss = (ss_stats_t *)malloc(sizeof(ss_stats_t)); + if (ss == NULL) { + ss_close_stream(fp); + return -ENOMEM; + } + sts = 0; } *ss = parsed_ss; ss->instid = pmdaCacheStore(indom, PMDA_CACHE_ADD, instname, (void **)ss); diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/ss_stats.h pcp-5.3.2/src/pmdas/linux_sockets/ss_stats.h --- pcp-5.3.1/src/pmdas/linux_sockets/ss_stats.h 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/ss_stats.h 2021-07-30 04:05:06.000000000 +0000 @@ -87,7 +87,7 @@ } ss_stats_t; extern int ss_refresh(int); -extern int ss_parse(char *, ss_stats_t *); +extern int ss_parse(char *, int, ss_stats_t *); extern FILE *ss_open_stream(void); extern void ss_close_stream(FILE *); extern char *ss_filter; /* current string value of network.persocket.filter */ diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/ss_stream.c pcp-5.3.2/src/pmdas/linux_sockets/ss_stream.c --- pcp-5.3.1/src/pmdas/linux_sockets/ss_stream.c 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/ss_stream.c 2021-07-30 04:05:06.000000000 +0000 @@ -16,10 +16,7 @@ #include #include "ss_stats.h" -#define SS_OPTIONS "-noemitauOH" - -/* default filter: reduces logging overheads */ -#define SS_DEFAULT_FILTER "state connected" +#define SS_OPTIONS "-noemitauO" char *ss_filter = NULL; /* storable: network.persocket.filter */ @@ -32,15 +29,16 @@ if (ss_filter == NULL) { /* pmstore to network.persocket.filter frees this if changing */ - if ((ss_filter = strdup(SS_DEFAULT_FILTER)) == NULL) + if ((ss_filter = strdup("")) == NULL) return NULL; } - if ((path = getenv("PCPQA_PMDA_SOCKETS")) != NULL) + if ((path = getenv("PCPQA_PMDA_SOCKETS")) != NULL) { /* PCPQA input file */ fp = fopen(path, "r"); - else { - /* TODO use a config file for ss options and ss filters */ + if (pmDebugOptions.appl0) + fprintf(stderr, "ss_open_stream: open PCPQA_PMDA_SOCKETS=%s\n", path); + } else { if (access((path = "/usr/sbin/ss"), X_OK) != 0) { if (access((path = "/usr/bin/ss"), X_OK) != 0) { fprintf(stderr, "Error: no \"ss\" binary found\n"); @@ -49,6 +47,8 @@ } pmsprintf(cmd, sizeof(cmd), "%s %s %s", path, SS_OPTIONS, ss_filter); fp = popen(cmd, "r"); + if (pmDebugOptions.appl0) + fprintf(stderr, "ss_open_stream: popen %s\n", cmd); } return fp; diff -Nru pcp-5.3.1/src/pmdas/linux_sockets/Upgrade pcp-5.3.2/src/pmdas/linux_sockets/Upgrade --- pcp-5.3.1/src/pmdas/linux_sockets/Upgrade 2021-01-27 22:58:21.000000000 +0000 +++ pcp-5.3.2/src/pmdas/linux_sockets/Upgrade 2021-07-30 04:05:06.000000000 +0000 @@ -16,8 +16,10 @@ . $PCP_DIR/etc/pcp.env -if grep -q ^sockets "$PCP_PMCDCONF_PATH" 2>/dev/null +if grep -q "^sockets.*dso.*\.so" "$PCP_PMCDCONF_PATH" 2>/dev/null then + # migrate from dso to daemon + sed -i '/^sockets/d' "$PCP_PMCDCONF_PATH" touch "$PCP_PMDAS_DIR/sockets/.NeedInstall" fi diff -Nru pcp-5.3.1/src/pmdas/lmsensors/pmdalmsensors.1 pcp-5.3.2/src/pmdas/lmsensors/pmdalmsensors.1 --- pcp-5.3.1/src/pmdas/lmsensors/pmdalmsensors.1 2020-05-28 23:27:15.000000000 +0000 +++ pcp-5.3.2/src/pmdas/lmsensors/pmdalmsensors.1 2021-07-30 04:05:06.000000000 +0000 @@ -11,11 +11,11 @@ .\" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License .\" for more details. .\" -.TH "PMDALMSENSORS" "1" "PCP" "Performance Co-Pilot" "" -.SH "NAME" -\f3pmdalmsensors.python\f1 \- Linux hardware monitoring performance metrics domain agent (PMDA) +.TH PMDALMSENSORS 1 "PCP" "Performance Co-Pilot" "" +.SH NAME +\f3pmdalmsensors\f1 \- Linux hardware monitoring performance metrics domain agent (PMDA) .SH "SYNOPSIS" -\f3$PCP_PMDAS_DIR/lmsensors/pmdalmsensors.python\f1 +\f3$PCP_PMDAS_DIR/lmsensors/pmdalmsensors\f1 [\f3debug\f1] .SH "DESCRIPTION" .B pmdalmsensors diff -Nru pcp-5.3.1/src/pmdas/mmv/src/mmv.c pcp-5.3.2/src/pmdas/mmv/src/mmv.c --- pcp-5.3.1/src/pmdas/mmv/src/mmv.c 2020-05-28 23:27:15.000000000 +0000 +++ pcp-5.3.2/src/pmdas/mmv/src/mmv.c 2021-07-30 04:05:06.000000000 +0000 @@ -286,18 +286,61 @@ return 0; } -/* check client item number validity - must not be too large to fit in PMID! */ +/* + * Check client item number validity - must not be too large to fit in PMID! + * and must be unique within a cluster + * + * We're checking the kth entry in ml[]. + */ static int -verify_metric_item(unsigned int item, char *name, stats_t *s) +verify_metric_item(mmv_disk_metric_t *ml, int k, char *name, stats_t *s) { + mmv_disk_metric_t *mp = &ml[k]; + unsigned int item = mp->item; + int j; + if (pmDebugOptions.appl0) pmNotifyErr(LOG_DEBUG, "MMV: verify_metric_item: %u - %s", item, name); if (pmID_item(item) != item) { - pmNotifyErr(LOG_WARNING, "invalid item %u (%s) in %s, ignored", + pmNotifyErr(LOG_WARNING, "MMV: verify_metric_item: invalid item %u (%s) in %s, ignored", item, name, s->name); return -EINVAL; } + + for (j = 0; j < k; j++) { + if (ml[j].item == item) { + pmNotifyErr(LOG_DEBUG, "MMV: verify_metric_item: duplicate item %u - [%d] and [%d] %s, second will be ignored", item, j, k, name); + return -EINVAL; + } + } + + return 0; +} + +static int +verify_metric_item2(mmv_disk_metric2_t *ml, int k, char *name, stats_t *s) +{ + mmv_disk_metric2_t *mp = &ml[k]; + unsigned int item = mp->item; + int j; + + if (pmDebugOptions.appl0) + pmNotifyErr(LOG_DEBUG, "MMV: verify_metric_item2: %u - %s", item, name); + + if (pmID_item(item) != item) { + pmNotifyErr(LOG_WARNING, "MMV: verify_metric_item2: invalid item %u (%s) in %s, ignored", + item, name, s->name); + return -EINVAL; + } + + for (j = 0; j < k; j++) { + if (ml[j].item == item) { + pmNotifyErr(LOG_DEBUG, "MMV: verify_metric_item2: duplicate item %u - [%d] and [%d] %s, second will be ignored", item, j, k, name); + return -EINVAL; + } + } + return 0; } @@ -629,7 +672,7 @@ strcat(name, mp->name); if (verify_metric_name(ap, name, k, s) != 0) continue; - if (verify_metric_item(mp->item, name, s) != 0) + if (verify_metric_item(ml, k, name, s) != 0) continue; pmid = pmID_build(pmda->e_domain, s->cluster, mp->item); @@ -684,7 +727,7 @@ if (verify_metric_name(ap, name, k, s) != 0) continue; - if (verify_metric_item(mp->item, name, s) != 0) + if (verify_metric_item2(ml, k, name, s) != 0) continue; pmid = pmID_build(pmda->e_domain, s->cluster, mp->item); diff -Nru pcp-5.3.1/src/pmdas/openmetrics/pmdaopenmetrics.1 pcp-5.3.2/src/pmdas/openmetrics/pmdaopenmetrics.1 --- pcp-5.3.1/src/pmdas/openmetrics/pmdaopenmetrics.1 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/openmetrics/pmdaopenmetrics.1 2021-07-30 04:05:06.000000000 +0000 @@ -386,6 +386,45 @@ .BR gauge . For full details of the openmetrics exposition formats, see .IR https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md . +.SH "SELinux CONSIDERATIONS" +Scripted config files are executed by the +.B pmdaopenmetrics +PMDA with the same SELinux context and policy as the local +.BR pmcd (1). +For simple scripts, such as the load average example described above, +this is normally fine. +However AVC errors may result for scripts that make library or system +calls that are restricted by the prevailing SELinux context and policies. +In these cases it is not feasible to unilaterally grant +.B pmcd +or it's PMDAs an unconfined execution policy. +In these site specific cases it will be necessary to create a local +SELinux policy module. +This can be done by capturing the AVC record(s) from the local audit log, +generate a local policy module using +.BR audit2allow , +and then load the new module using +.BR semodule , +e.g. as follows : +.in 1i +.ft CW +.nf + + $ sudo grep '^type=AVC.*pcp' /var/log/audit/audit.log \\ + | audit2allow -M mypolicy + $ sudo semodule -i mypolicy.pp + +.in +.fi +.ft 1 +If these local policies need to be persistent across reboots, +then a scriptlet similar to the above example may be added to +the local pmcd RC file (typically +.BR /etc/pcp/pmcd/rc.local ). +For further details, see +.BR audit2allow (1) +and +.BR semodule (1). .SH "METRIC NAMING" All metrics from a file named .IR JOB .* @@ -648,12 +687,14 @@ .IR pcp.conf (5). .SH SEE ALSO .BR PCPIntro (1), +.BR audit2allow (1), .BR pmcd (1), .BR pminfo (1), .BR pmlogger (1), .BR pmstore (1), .BR PMWEBAPI (3), -.BR pmFetch (3) -.BR pmLookupLabels (3) +.BR pmFetch (3), +.BR pmLookupLabels (3), +.BR semodule (1), and .IR https://prometheus.io/docs/instrumenting/exposition_formats . diff -Nru pcp-5.3.1/src/pmdas/pmcd/help pcp-5.3.2/src/pmdas/pmcd/help --- pcp-5.3.1/src/pmdas/pmcd/help 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/pmcd/help 2021-06-15 01:03:49.000000000 +0000 @@ -351,6 +351,17 @@ Enables determination of "local" time for timestamps returned via PMCD from a remote host. +@ pmcd.zoneinfo local timezone tzfile identification +Alternative value for the timezone where the PMCD is running, but in the +style of a specification for a tzfile(5)-format file, so a colon followed +by the path to a file below /usr/share/zoneinfo, e.g. ":Australia/Melbourne" +or ":America/Argentina/Ushuaia". + +May be used to set $TZ. + +If the zoneinfo cannot be deduced, the value of this metric is "" (an +empty string). + @ pmcd.sighups count of SIGHUP signals pmcd has received @ pmcd.labels Context level metadata labels associated with all values diff -Nru pcp-5.3.1/src/pmdas/pmcd/root_pmcd pcp-5.3.2/src/pmdas/pmcd/root_pmcd --- pcp-5.3.1/src/pmdas/pmcd/root_pmcd 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/pmcd/root_pmcd 2021-06-15 01:03:49.000000000 +0000 @@ -23,6 +23,7 @@ numclients PMCD:0:3 pmlogger timezone PMCD:0:5 + zoneinfo PMCD:0:26 simabi PMCD:0:6 version PMCD:0:7 services PMCD:0:16 diff -Nru pcp-5.3.1/src/pmdas/pmcd/src/pmcd.c pcp-5.3.2/src/pmdas/pmcd/src/pmcd.c --- pcp-5.3.1/src/pmdas/pmcd/src/pmcd.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmdas/pmcd/src/pmcd.c 2021-06-15 01:03:49.000000000 +0000 @@ -87,6 +87,8 @@ { PMDA_PMID(0,24), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, /* labels */ { PMDA_PMID(0,25), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* zoneinfo -- local timezone tzfile identification -- for pmlogger timezone */ + { PMDA_PMID(0,26), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, /* pdu_in.error */ { PMDA_PMID(1,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, @@ -297,6 +299,8 @@ }; static const int nbufsz = sizeof(bufinst) / sizeof(bufinst[0]); +static char *zoneinfo = NULL; + /* * Per-context structures */ @@ -1119,6 +1123,175 @@ return __pmTimezone(); } +#define ZONEINFO "/zoneinfo/" +#define LOCALTIME "/etc/localtime" + +/* + * Plan B + * + * Get the size for /etc/localtime if possible. + * + * Descend /usr/share/zoneinfo looking for a file with the same size + * and then compare file contents ... if equal, consider it a match. + * + * If more than one file matches, pick the first but emit a warning. + */ +char * +getzoneinfo_plan_b(void) +{ + FILE *fp; /* find ... pipe */ + FILE *f1; /* /etc/localtime */ + FILE *f2; /* candidate file */ + int c1; + int c2; + char *p; + char *path = NULL; + struct stat sbuf; /* sbuf.st_size is all that matters */ + char tmp[MAXPATHLEN+2]; /* shell command and line buffer */ + + if ((f1 = fopen(LOCALTIME, "r")) == NULL) { + fprintf(stderr, "getzoneinfo_plan_b: cannot open %s: %s\n", LOCALTIME, pmErrStr(-oserror())); + return NULL; + } + + if (fstat(fileno(f1), &sbuf) < 0) { + fprintf(stderr, "getzoneinfo_plan_b: cannot stat %s: %s\n", LOCALTIME, pmErrStr(-oserror())); + fclose(f1); + return NULL; + } + sprintf(tmp, "find /usr/share/zoneinfo -type f -a -size %ldc", sbuf.st_size); + if ((fp = popen(tmp, "r")) == NULL) { + fprintf(stderr, "getzoneinfo_plan_b: pipe(%s) failed: %s\n", tmp, pmErrStr(-oserror())); + fclose(f1); + return NULL; + } + /* start at reading at tmp[1], so ':' can be inserted at tmp[0] */ + while (fgets(&tmp[1], sizeof(tmp)-1, fp) != NULL) { + /* strip \n at end of line */ + for (p = &tmp[1]; *p != '\n'; p++) + ; + *p = '\0'; + if ((f2 = fopen(&tmp[1], "r")) == NULL) { + fprintf(stderr, "getzoneinfo_plan_b: cannot open %s: %s\n", &tmp[1], pmErrStr(-oserror())); + fclose(f1); + pclose(fp); + if (path != NULL) + free(path); + return NULL; + } + rewind(f1); + + for ( ; ; ) { + c1 = fgetc(f1); + c2 = fgetc(f2); + if (c1 == EOF && c2 == EOF) { + /* contents match */ + if (path == NULL) { + tmp[0] = ':'; + path = strdup(tmp); + if (path == NULL) { + fprintf(stderr, "getzoneinfo_plan_b: match %s but strdup failed\n", &tmp[1]); + fclose(f2); + fclose(f1); + pclose(fp); + return NULL; + } + } + else { + /* + * Duplicates ... pick shortest path, as this will favour, for + * example, Australia/Melbourne over posix/Australia/Melbourne + */ + if (strlen(&path[1]) <= strlen(&tmp[1])) + fprintf(stderr, "getzoneinfo_plan_b: Warning: match %s and %s, choosing first one\n", &path[1], &tmp[1]); + else { + fprintf(stderr, "getzoneinfo_plan_b: Warning: match %s and %s, choosing second one\n", &path[1], &tmp[1]); + free(path); + tmp[0] = ':'; + path = strdup(tmp); + if (path == NULL) { + fprintf(stderr, "getzoneinfo_plan_b: strdup failed\n"); + fclose(f2); + fclose(f1); + pclose(fp); + return NULL; + } + } + } + break; + } + if (c1 != c2) + break; + } + fclose(f2); + } + fclose(f1); + pclose(fp); + + return path; +} + +/* + * Get the local timezone tzfile identification + * + * We'd like this to return something like ":Australia/Melbourne" + * that can be used as a $TZ setting. + * + * Plan A + * If /etc/localtime is a symbolic link, get the pathname it points + * to and strip anything up to (and including) the string "/zoneinfo/". + * + * Return NULL on failure. + */ +char * +getzoneinfo(void) +{ + ssize_t sts; + char *buf; + char *tmp_buf; + char *p; + char *q; + + /* +1 for : +1 for NULL */ + buf = (char *)malloc(MAXPATHLEN+2); + if (buf == NULL) + return NULL; + + sts = readlink(LOCALTIME, &buf[1], MAXPATHLEN); + if (sts < 0) { + /* + * Hmm, not a symlink. Now try Plan B. + */ + free(buf); + buf = getzoneinfo_plan_b(); + if (buf == NULL) + return NULL; + } + else + buf[sts+1] = '\0'; + + /* try to find prefix .../zoneinfo/... */ + p = strstr(buf, ZONEINFO); + if (p != NULL) { + /* found it! */ + q = &p[strlen(ZONEINFO)-1]; + tmp_buf = strdup(q); + if (tmp_buf != NULL) { + free(buf); + buf = tmp_buf; + } + } + else { + /* no prefix, truncate ... nice to have, not necessary */ + tmp_buf = realloc(buf, sts+2); + if (tmp_buf != NULL) + buf = tmp_buf; + } + buf[0] = ':'; + + return buf; +} + static char * services(void) { @@ -1540,6 +1713,17 @@ fetch_labels(pmda->e_context, &atom, &host); break; + case 26: /* zoneinfo */ + if (zoneinfo == NULL) { + zoneinfo = getzoneinfo(); + if (zoneinfo == NULL) { + /* value is an empty string if not available */ + zoneinfo = ""; + } + } + atom.cp = zoneinfo; + break; + default: sts = atom.l = PM_ERR_PMID; break; diff -Nru pcp-5.3.1/src/pmdas/statsd/pmdastatsd.1 pcp-5.3.2/src/pmdas/statsd/pmdastatsd.1 --- pcp-5.3.1/src/pmdas/statsd/pmdastatsd.1 2020-08-06 23:53:48.000000000 +0000 +++ pcp-5.3.2/src/pmdas/statsd/pmdastatsd.1 2021-07-30 04:05:06.000000000 +0000 @@ -521,6 +521,12 @@ .B total - Number of tracked metrics total. .TP +.B statsd.pmda.time_spent_parsing +Total time in microseconds spent parsing metrics. Includes time spent parsing a datagram and failing midway. +.TP +.B statsd.pmda.time_spent_aggregating +Total time in microseconds spent aggregating metrics. Includes time spent aggregating a metric and failing midway. +.TP .B statsd.pmda.settings.max_udp_packet_size Maximum UDP packet size .TP @@ -530,9 +536,6 @@ .B statsd.pmda.settings.verbose Verbosity flag .TP -.B statsd.pmda.settings.debug -Debug flag -.TP .B statsd.pmda.settings.debug_output_filename Debug output filename .TP diff -Nru pcp-5.3.1/src/pmdas/statsd/README.md pcp-5.3.2/src/pmdas/statsd/README.md --- pcp-5.3.1/src/pmdas/statsd/README.md 2020-08-06 23:53:48.000000000 +0000 +++ pcp-5.3.2/src/pmdas/statsd/README.md 2021-07-30 04:05:06.000000000 +0000 @@ -43,15 +43,20 @@ ## Installation steps -1. Put contents of this repo into $PCP_PMDAS_DIR/statsd/ ($PCP_PMDAS_DIR is sourced from /etc/pcp.conf, which should be available if you have PCP installed) -2. First make sure you have "STATSD" namespace set to "510" in stdpmid file. [How-to](https://pcp.io/books/PCP_PG/html/id5189538.html) -3. Compile with **make** -4. Activate agent with **sudo make activate** - +Do the following as root: +``` +cd $PCP_PMDAS_DIR/statsd +./Install +``` ## Uninstallation steps -1. Run **sudo make deactivate** within $PCP_PMDAS_DIR/statsd/ directory -2. Remove the statsd folder +Do the following as root: +``` +cd $PCP_PMDAS_DIR/statsd +./Remove +``` + +Remove the statsd folder, if you wish. # Configuration @@ -320,6 +325,14 @@
+ statsd.pmda.time_spent_parsing + Total time in microseconds spent parsing metrics. Includes time spent parsing a datagram and failing midway. +
+
+ statsd.pmda.time_spent_aggregating + Total time in microseconds spent aggregating metrics. Includes time spent aggregating a metric and failing midway. +
+
statsd.pmda.settings.max_udp_packet_size Maximum UDP packet size
@@ -332,10 +345,6 @@ Verbosity flag
- statsd.pmda.settings.debug - Debug flag -
-
statsd.pmda.settings.debug_output_filename Debug output filename
@@ -353,30 +362,3 @@ These names are blocklisted for user usage. No messages with these names will processed. While not yet reserved, whole statsd.pmda.* namespace is not recommended to use for user metrics. - -# Roadmap -- Make sure code is optimized - -# FAQ - -## I installed both **chan** and **HdrHistogram_c** yet the program won't run... there seem to be .so missing. -You may need to make sure that /usr/local is actually looked into. You may need to add the directory to **/etc/ld.so.conf** yourself: -``` -tee /etc/ld.so.conf.d/local.conf < Parser -> Aggregator => Data structures (PMDA stats and StatsD metrics) guarded by locks <= PCP - -Legend: -- "->" = channel -- "=>" = shared data structures diff -Nru pcp-5.3.1/src/pmdumplog/pmdumplog.c pcp-5.3.2/src/pmdumplog/pmdumplog.c --- pcp-5.3.1/src/pmdumplog/pmdumplog.c 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/pmdumplog/pmdumplog.c 2021-07-30 04:05:06.000000000 +0000 @@ -20,6 +20,7 @@ #include #include #include +#include "../libpcp/src/internal.h" static struct timeval tv; static char timebuf[32]; /* for pmCtime result + .xxx */ @@ -38,6 +39,7 @@ { "descs", 0, 'd', 0, "dump metric descriptions" }, { "labelsets", 0, 'e', 0, "dump all metric label metadata" }, { "helptext", 0, 'h', 0, "dump all metric help text" }, + { "on-disk-insts", 0, 'I', 0, "dump on-disk instance domain descriptions" }, { "insts", 0, 'i', 0, "dump instance domain descriptions" }, { "", 0, 'L', 0, "more verbose form of archive label dump" }, { "label", 0, 'l', 0, "dump the archive label" }, @@ -61,7 +63,7 @@ static int overrides(int, pmOptions *); static pmOptions opts = { .flags = PM_OPTFLAG_DONE | PM_OPTFLAG_STDOUT_TZ | PM_OPTFLAG_BOUNDARIES, - .short_options = "aD:dehilLmMn:rS:sT:tv:xZ:z?", + .short_options = "aD:dehIilLmMn:rS:sT:tv:xZ:z?", .long_options = longopts, .short_usage = "[options] [archive [metricname ...]]", .override = overrides, @@ -475,6 +477,100 @@ } static void +dumpDiskInDom(__pmContext *ctxp) +{ + size_t n; + size_t rlen; + __int32_t check; + __pmLogHdr hdr; + __pmFILE *f = ctxp->c_archctl->ac_log->l_mdfp; + + printf("\nInstance Domains on-disk ...\n"); + + __pmFseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); + for ( ; ; ) { + n = __pmFread(&hdr, 1, sizeof(__pmLogHdr), f); + hdr.len = ntohl(hdr.len); + hdr.type = ntohl(hdr.type); + if (n != sizeof(__pmLogHdr)) { + if (__pmFeof(f)) { + /* end-of-file, all done. */ + return; + } + if (__pmFerror(f)) { + fprintf(stderr, "dumpDiskInDom: hdr __pmFread(%zd) -> %s\n", sizeof(__pmLogHdr), pmErrStr(-oserror())); + return; + } + fprintf(stderr, "dumpDiskInDom: Botch: hdr __pmFread(%zd) -> %zd\n", sizeof(__pmLogHdr), n); + return; + } + if (hdr.len <= 0) { + fprintf(stderr, "dumpDiskInDom: Botch: hdr.len < 0 (%d)\n", hdr.len); + return; + } + rlen = (size_t)hdr.len - sizeof(__pmLogHdr) - sizeof(__int32_t); + if (hdr.type == TYPE_INDOM) { + pmTimeval *tvp; + pmInResult in; + char *namebase; + __int32_t *rbuf; + __int32_t *stridx; + int i; + int k; + + if ((rbuf = (__int32_t *)malloc(rlen)) == NULL) { + fprintf(stderr, "dumpDiskInDom: tbuf: malloc failed: %zd\n", rlen); + exit(1); + } + if ((n = __pmFread(rbuf, 1, rlen, f)) != rlen) { + fprintf(stderr, "dumpDiskInDom: indom __pmFread(%zd) -> %zd\n", + rlen, n); + free(rbuf); + return; + } + + k = 0; + tvp = (pmTimeval *)&rbuf[k]; + tv.tv_sec = ntohl(tvp->tv_sec); + tv.tv_usec = ntohl(tvp->tv_usec); + k += sizeof(pmTimeval)/sizeof(int); + in.indom = __ntohpmInDom((unsigned int)rbuf[k++]); + in.numinst = ntohl(rbuf[k++]); + mytimestamp(&tv); + printf(" InDom: %s", pmInDomStr(in.indom)); + printf(" %d instances\n", in.numinst); + if (in.numinst > 0) { + in.instlist = &rbuf[k]; + k += in.numinst; + stridx = &rbuf[k]; + k += in.numinst; + namebase = (char *)&rbuf[k]; + for (i = 0; i < in.numinst; i++) { + printf(" %d or \"%s\"\n", + ntohl(in.instlist[i]), &namebase[ntohl(stridx[i])]); + } + } + free(rbuf); + } + else { + /* skip this record, not TYPE_INDOM */ + __pmFseek(f, (off_t)rlen, SEEK_CUR); + } + /* trailer check */ + n = __pmFread(&check, 1, sizeof(check), f); + if (n != sizeof(check)) { + fprintf(stderr, "dumpDiskInDom: Botch: trailer __pmFread(%zd) -> %zd\n", sizeof(__pmLogHdr), n); + return; + } + check = ntohl(check); + if (hdr.len != check) { + fprintf(stderr, "dumpDiskInDom: Botch: trailer len (%d) != hdr len (%d)\n", check, hdr.len); + return; + } + } +} + +static void dumpInDom(__pmContext *ctxp) { int i; @@ -973,6 +1069,7 @@ int dflag = 0; int eflag = 0; int hflag = 0; + int Iflag = 0; int iflag = 0; int Lflag = 0; int lflag = 0; @@ -1006,6 +1103,10 @@ hflag = 1; break; + case 'I': /* dump on-disk instance domains */ + Iflag = 1; + break; + case 'i': /* dump instance domains */ iflag = 1; break; @@ -1071,7 +1172,7 @@ exit(0); } - if (dflag + eflag + hflag + iflag + lflag + mflag + tflag == 0) + if (dflag + eflag + hflag + Iflag + iflag + lflag + mflag + tflag == 0) mflag = 1; /* default */ /* delay option end processing until now that we have the archive name */ @@ -1179,6 +1280,9 @@ if (hflag) dumpHelpText(ctxp); + if (Iflag) + dumpDiskInDom(ctxp); + if (iflag) dumpInDom(ctxp); diff -Nru pcp-5.3.1/src/pminfo/pminfo.c pcp-5.3.2/src/pminfo/pminfo.c --- pcp-5.3.1/src/pminfo/pminfo.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pminfo/pminfo.c 2021-07-30 04:05:06.000000000 +0000 @@ -895,6 +895,8 @@ pmFreeResult(xresult); xresult = NULL; } + free(all_inst); + free(all_names); if (opts.context == PM_CONTEXT_ARCHIVE) { if ((sts = pmSetMode(PM_MODE_FORW, &opts.origin, 0)) < 0) { fprintf(stderr, "%s: pmSetMode failed: %s\n", pmGetProgname(), pmErrStr(sts)); @@ -907,8 +909,6 @@ } vsp = xresult->vset[0]; /* leave the profile in the default state */ - free(all_inst); - free(all_names); pmDelProfile(desc.indom, 0, NULL); pmAddProfile(desc.indom, 0, NULL); } diff -Nru pcp-5.3.1/src/pmlogconf/tools/htop pcp-5.3.2/src/pmlogconf/tools/htop --- pcp-5.3.1/src/pmlogconf/tools/htop 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogconf/tools/htop 2021-07-30 04:05:06.000000000 +0000 @@ -40,6 +40,7 @@ mem.util.free mem.util.bufmem mem.util.cached + mem.util.shmem mem.util.slabReclaimable mem.util.swapCached mem.util.swapTotal diff -Nru pcp-5.3.1/src/pmlogconf/tools/htop-proc pcp-5.3.2/src/pmlogconf/tools/htop-proc --- pcp-5.3.1/src/pmlogconf/tools/htop-proc 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogconf/tools/htop-proc 2021-07-30 04:05:06.000000000 +0000 @@ -32,6 +32,8 @@ proc.psinfo.labels proc.psinfo.environ proc.psinfo.ttyname + proc.psinfo.cwd + proc.psinfo.exe proc.id.uid proc.id.uid_nm proc.io.rchar diff -Nru pcp-5.3.1/src/pmlogconf/tools/htop-zfs pcp-5.3.2/src/pmlogconf/tools/htop-zfs --- pcp-5.3.1/src/pmlogconf/tools/htop-zfs 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/src/pmlogconf/tools/htop-zfs 2021-07-30 04:05:06.000000000 +0000 @@ -0,0 +1,14 @@ +#pmlogconf-setup 2.0 +ident ZFS metrics sampled by the htop command +probe zfs.arc.size values ? include : exclude + zfs.arc.anon_size + zfs.arc.bonus_size + zfs.arc.compressed_size + zfs.arc.uncompressed_size + zfs.arc.c_max + zfs.arc.dbuf_size + zfs.arc.dnode_size + zfs.arc.hdr_size + zfs.arc.mfu_size + zfs.arc.mru_size + zfs.arc.size diff -Nru pcp-5.3.1/src/pmlogconf/tools/localdefs pcp-5.3.2/src/pmlogconf/tools/localdefs --- pcp-5.3.1/src/pmlogconf/tools/localdefs 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogconf/tools/localdefs 2021-07-30 04:05:06.000000000 +0000 @@ -22,6 +22,7 @@ htop \ htop-proc \ htop-summary \ + htop-zfs \ iostat \ ip \ ipcs \ diff -Nru pcp-5.3.1/src/pmlogextract/pmlogextract.c pcp-5.3.2/src/pmlogextract/pmlogextract.c --- pcp-5.3.1/src/pmlogextract/pmlogextract.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogextract/pmlogextract.c 2021-07-30 04:05:06.000000000 +0000 @@ -44,6 +44,7 @@ { "", 0, 'x', 0, "skip metrics with mismatched metadata" }, PMOPT_TIMEZONE, PMOPT_HOSTZONE, + PMOPT_HELP, PMAPI_OPTIONS_END }; diff -Nru pcp-5.3.1/src/pmlogger/pmlogger_daily.sh pcp-5.3.2/src/pmlogger/pmlogger_daily.sh --- pcp-5.3.1/src/pmlogger/pmlogger_daily.sh 2021-02-08 03:22:27.000000000 +0000 +++ pcp-5.3.2/src/pmlogger/pmlogger_daily.sh 2021-07-30 04:05:06.000000000 +0000 @@ -1212,7 +1212,26 @@ then echo "+ $KILL -s USR2 $pid" else + $VERY_VERBOSE && echo >&2 "Sending SIGUSR2 to $pid" $KILL -s USR2 "$pid" + if $VERY_VERBOSE + then + # We have seen in qa/793, but never in a "real" + # deployment, cases where the pmlogger process + # vanishes a short time after the SIGUSR2 has been + # sent and caught, the process has called exec() and + # main() has restarted. This check is intended + # detect and report when this happens if -VV is + # in play. + # + sleep 1 + if $PCP_PS_PROG -p "$pid" 2>&1 | grep "^$pid[ ]" >/dev/null + then + : still alive + else + echo >&2 "Error: pmlogger process $pid has vanished" + fi + fi fi fi diff -Nru pcp-5.3.1/src/pmlogger/src/callback.c pcp-5.3.2/src/pmlogger/src/callback.c --- pcp-5.3.1/src/pmlogger/src/callback.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogger/src/callback.c 2021-07-30 04:05:06.000000000 +0000 @@ -438,14 +438,10 @@ * is guarded by the pmDesc logging-once logic. */ if (sts == 0) { - if (text[0] == '\0') - free(text); - else { - sts = __pmLogPutText(&archctl, ident, types, text, indom); - free(text); - if (sts < 0) + sts = __pmLogPutText(&archctl, ident, types, text, indom); + free(text); + if (sts < 0) break; - } } } } diff -Nru pcp-5.3.1/src/pmlogger/src/fetch.c pcp-5.3.2/src/pmlogger/src/fetch.c --- pcp-5.3.1/src/pmlogger/src/fetch.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogger/src/fetch.c 2021-07-30 04:05:06.000000000 +0000 @@ -277,12 +277,14 @@ else { fprintf(stderr, "myFetch: ERROR PDU: %s\n", pmErrStr(n)); disconnect(PM_ERR_IPC); + changed = 0; } __pmUnpinPDUBuf(pb); } else if (n == 0) { fprintf(stderr, "myFetch: End of File: PMCD exited?\n"); disconnect(PM_ERR_IPC); + changed = 0; } else if (n == -EINTR) { /* SIGINT, let the normal cleanup happen */ @@ -292,11 +294,13 @@ /* other badness, disconnect */ fprintf(stderr, "myFetch: __pmGetPDU: Error: %s\n", pmErrStr(n)); disconnect(PM_ERR_IPC); + changed = 0; } else { /* protocol botch, disconnect */ fprintf(stderr, "myFetch: Unexpected %s PDU from PMCD\n", __pmPDUTypeStr(n)); disconnect(PM_ERR_IPC); + changed = 0; __pmUnpinPDUBuf(pb); } } while (n == 0); diff -Nru pcp-5.3.1/src/pmlogger/src/pmlogger.c pcp-5.3.2/src/pmlogger/src/pmlogger.c --- pcp-5.3.1/src/pmlogger/src/pmlogger.c 2021-04-09 03:57:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogger/src/pmlogger.c 2021-07-30 04:05:06.000000000 +0000 @@ -11,6 +11,16 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * Debugging options + * appl0 control request pdus (via pmlc) + * appl1 credentials exchange + * appl2 alarm (timing) loop + * callback (do_work()) + * record mode control messages + * appl3 signal callbacks and exit logging + * appl4 desperate tracing to help triage qa/793 failures + * [THIS IS TEMPORARY AND WILL BE REMOVED] */ #include @@ -75,6 +85,9 @@ { int i, lsts; + /* no more timer events, especially on the re-exec path */ + __pmAFblock(); + if (pmDebugOptions.services || (pmDebugOptions.log && pmDebugOptions.desperate)) { fprintf(stderr, "run_done(%d, %s) last_log_offset=%d last_stamp=", sts, msg, last_log_offset); @@ -712,12 +725,12 @@ */ if (getcwd(dir, sizeof(dir)) == NULL) { if (pmDebugOptions.services) - fprintf(stderr, "Info: updateLatestFolio: getcwd() failed for host %s: %s", host, strerror(errno)); + fprintf(stderr, "Info: updateLatestFolio: getcwd() failed for host %s: %s\n", host, strerror(errno)); return; } if (strncmp(dir, logdir, strlen(logdir)) != 0) { if (pmDebugOptions.services) - fprintf(stderr, "Info: not creating \"Latest\" archive folio for host %s: %s", host, strerror(errno)); + fprintf(stderr, "Info: not creating \"Latest\" archive folio for host %s: cwd %s not below %s\n", host, dir, logdir); return; } @@ -725,7 +738,7 @@ thishost[MAXHOSTNAMELEN-1] = '\0'; if ((fp = fopen("Latest", "w")) == NULL) { - fprintf(stderr, "Warning: failed to create \"Latest\" archive folio for host %s: %s", host, strerror(errno)); + fprintf(stderr, "Warning: failed to create \"Latest\" archive folio for host %s: %s\n", host, strerror(errno)); return; } time(&now); @@ -1030,7 +1043,7 @@ /* only open a new log if we are NOT reexec'd */ if (pmlogger_reexec) { if (pmDebugOptions.services) - fprintf(stderr, "existing pmlogger.log remains open after re-exec\n"); + fprintf(stderr, "existing log %s remains open after re-exec\n", logfile); } else { pmOpenLog("pmlogger", logfile, stderr, &sts); if (sts != 1) { @@ -1095,10 +1108,12 @@ else if (pmcd_host_conn == NULL) pmcd_host_conn = "local:"; + if (pmDebugOptions.appl4) fprintf(stderr, "@pmNewContext\n"); if ((ctx = pmNewContext(host_context, pmcd_host_conn)) < 0) { fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmGetProgname(), pmcd_host_conn, pmErrStr(ctx)); exit(1); } + if (pmDebugOptions.appl4) fprintf(stderr, "@pmGetContextHostName\n"); pmcd_host = (char *)pmGetContextHostName(ctx); if (strlen(pmcd_host) == 0) { fprintf(stderr, "%s: pmGetContextHostName(%d) failed\n", @@ -1108,6 +1123,7 @@ if (rsc_fd == -1 && host_context != PM_CONTEXT_LOCAL) { /* no -x, so register client id with pmcd */ + if (pmDebugOptions.appl4) fprintf(stderr, "@__pmSetClientIdArgv\n"); __pmSetClientIdArgv(argc, argv); } @@ -1115,6 +1131,7 @@ * discover fd for comms channel to PMCD ... */ if (host_context != PM_CONTEXT_LOCAL) { + if (pmDebugOptions.appl4) fprintf(stderr, "@__pmHandleToPtr\n"); if ((ctxp = __pmHandleToPtr(ctx)) == NULL) { fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmGetProgname(), ctx); exit(1); @@ -1123,6 +1140,7 @@ PM_UNLOCK(ctxp->c_lock); } + if (pmDebugOptions.appl4) fprintf(stderr, "@do_pmcpp\n"); yyin = do_pmcpp(configfile); /* do not return unless yyin is valid */ if (configfile == NULL) diff -Nru pcp-5.3.1/src/pmlogger/src/ports.c pcp-5.3.2/src/pmlogger/src/ports.c --- pcp-5.3.1/src/pmlogger/src/ports.c 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/pmlogger/src/ports.c 2021-07-30 04:05:06.000000000 +0000 @@ -20,6 +20,9 @@ #include #include #include "logger.h" +#ifdef HAVE_EXECINFO_H +#include +#endif #if !defined(SIGRTMAX) #if defined(NSIG) @@ -127,18 +130,53 @@ unlink(socketPath); } +/* borrowed from libpcp/lock.c */ +static void +mybacktrace(void) +{ +#ifdef HAVE_BACKTRACE +#define MAX_TRACE_DEPTH 32 + void *backaddr[MAX_TRACE_DEPTH]; + int sts; + sts = backtrace(backaddr, MAX_TRACE_DEPTH); + if (sts > 0) { + char **symbols; + symbols = backtrace_symbols(backaddr, MAX_TRACE_DEPTH); + if (symbols != NULL) { + int i; + fprintf(stderr, "backtrace:\n"); + for (i = 0; i < sts; i++) + fprintf(stderr, " %s\n", symbols[i]); + free(symbols); + } + } +#endif /* HAVE_BACKTRACE */ + return; +} + static void sigexit_handler(int sig) { - if (pmDebugOptions.desperate) - fprintf(stderr, "pmlogger: Signalled (signal=%d), exiting\n", sig); + if (pmDebugOptions.appl3) + fprintf(stderr, "sigexit_handler: Signalled (signal=%d)\n", sig); cleanup(); _exit(sig); } static void +sigmisc_handler(int sig) +{ + if (pmDebugOptions.appl3) + fprintf(stderr, "sigmisc_handler: Signalled (signal=%d)\n", sig); + /* just ignore these ones ... */ + __pmSetSignalHandler(sig, sigmisc_handler); +} + +static void sigterm_handler(int sig) { + if (pmDebugOptions.appl3) + fprintf(stderr, "sigterm_handler: Signalled (signal=%d)\n", sig); /* exit as soon as possible, handler is deferred for log cleanup */ sig_code = sig; } @@ -146,7 +184,9 @@ static void sighup_handler(int sig) { - __pmSetSignalHandler(SIGHUP, sighup_handler); + if (pmDebugOptions.appl3) + fprintf(stderr, "sighup_handler: Signalled (signal=%d)\n", sig); + __pmSetSignalHandler(sig, sighup_handler); vol_switch_flag = 1; } @@ -154,9 +194,9 @@ static void sigcore_handler(int sig) { - if (pmDebugOptions.desperate) - fprintf(stderr, "pmlogger: Signalled (signal=%d), exiting (core dumped)\n", sig); - __pmSetSignalHandler(SIGABRT, SIG_DFL); /* Don't come back here */ + if (pmDebugOptions.appl3) + fprintf(stderr, "sigcore_handler: Signalled (signal=%d), exiting (core dumped)\n", sig); + __pmSetSignalHandler(sig, SIG_DFL); /* Don't come back here */ cleanup(); _exit(sig); } @@ -164,6 +204,8 @@ static void sigpipe_handler(int sig) { + if (pmDebugOptions.appl3) + fprintf(stderr, "sigpipe_handler: Signalled (signal=%d)\n", sig); /* * just ignore the signal, the write() will fail, and the PDU * xmit will return with an error @@ -174,6 +216,8 @@ static void sigusr2_handler(int sig) { + if (pmDebugOptions.appl3) + fprintf(stderr, "sigusr2_handler: Signalled (signal=%d)\n", sig); __pmSetSignalHandler(SIGUSR2, sigusr2_handler); log_switch_flag = 1; sig_code = sig; /* triggers break from main loop so we can re-exec */ @@ -211,20 +255,20 @@ #ifndef IS_MINGW { SIGUSR1, sigterm_handler }, /* Exit User Signal 1 */ { SIGUSR2, sigusr2_handler }, /* reexec User Signal 2 */ - { SIGCHLD, SIG_IGN }, /* NOP Child stopped or terminated */ + { SIGCHLD, sigmisc_handler }, /* NOP Child stopped or terminated */ #ifdef SIGPWR - { SIGPWR, SIG_DFL }, /* Ignore Power Fail/Restart */ + { SIGPWR, sigmisc_handler }, /* Ignore Power Fail/Restart */ #endif - { SIGWINCH, SIG_DFL }, /* Ignore Window Size Change */ - { SIGURG, SIG_DFL }, /* Ignore Urgent Socket Condition */ + { SIGWINCH, sigmisc_handler }, /* Ignore Window Size Change */ + { SIGURG, sigmisc_handler }, /* Ignore Urgent Socket Condition */ #ifdef SIGPOLL { SIGPOLL, sigexit_handler }, /* Exit Pollable Event [see streamio(7)] */ #endif { SIGSTOP, SIG_DFL }, /* Stop Stopped (signal) */ - { SIGTSTP, SIG_DFL }, /* Stop Stopped (user) */ - { SIGCONT, SIG_DFL }, /* Ignore Continued */ - { SIGTTIN, SIG_DFL }, /* Stop Stopped (tty input) */ - { SIGTTOU, SIG_DFL }, /* Stop Stopped (tty output) */ + { SIGTSTP, sigmisc_handler }, /* Stop Stopped (user) */ + { SIGCONT, sigmisc_handler }, /* Ignore Continued */ + { SIGTTIN, sigmisc_handler }, /* Stop Stopped (tty input) */ + { SIGTTOU, sigmisc_handler }, /* Stop Stopped (tty output) */ { SIGVTALRM, sigterm_handler }, /* Exit Virtual Timer Expired */ { SIGPROF, sigterm_handler }, /* Exit Profiling Timer Expired */ @@ -555,6 +599,12 @@ cleanup(); exit(1); } + if (pmDebugOptions.appl3) { + if (atexit(mybacktrace) != 0) { + fprintf(stderr, "%s: Warning: unable to register atexit mybacktrace function\n", + pmGetProgname()); + } + } #endif /* create the control port file (make the directory if necessary). */ diff -Nru pcp-5.3.1/src/pmloglabel/pmloglabel.c pcp-5.3.2/src/pmloglabel/pmloglabel.c --- pcp-5.3.1/src/pmloglabel/pmloglabel.c 2018-08-04 03:33:07.000000000 +0000 +++ pcp-5.3.2/src/pmloglabel/pmloglabel.c 2021-07-30 04:05:06.000000000 +0000 @@ -155,6 +155,7 @@ { "verbose", 0, 'v', 0, "run in verbose mode, reporting on each stage of checking" }, { "version", 1, 'V', "NUM", "write magic and version numbers for all files in archive" }, { "timezone", 1, 'Z', "TZ", "set the timezone for all files in archive" }, + PMOPT_HELP, PMAPI_OPTIONS_END }; diff -Nru pcp-5.3.1/src/pmlogrewrite/pmlogrewrite.c pcp-5.3.2/src/pmlogrewrite/pmlogrewrite.c --- pcp-5.3.1/src/pmlogrewrite/pmlogrewrite.c 2020-05-28 23:27:16.000000000 +0000 +++ pcp-5.3.2/src/pmlogrewrite/pmlogrewrite.c 2021-07-30 04:05:06.000000000 +0000 @@ -50,6 +50,7 @@ { "scale", 0, 's', 0, "do scale conversion" }, { "verbose", 0, 'v', 0, "increased diagnostic verbosity" }, { "warnings", 0, 'w', 0, "emit warnings [default is silence]" }, + PMOPT_HELP, PMAPI_OPTIONS_TEXT(""), PMAPI_OPTIONS_TEXT("output-archive is required unless -i is specified"), PMAPI_OPTIONS_END diff -Nru pcp-5.3.1/src/pmns/stdpmid.pcp pcp-5.3.2/src/pmns/stdpmid.pcp --- pcp-5.3.1/src/pmns/stdpmid.pcp 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmns/stdpmid.pcp 2021-07-30 04:05:06.000000000 +0000 @@ -134,6 +134,8 @@ ZFS 153 SOCKETS 154 HACLUSTER 155 +DENKI 156 +BPF 157 ### NEXT FREE SLOT ### SCHIZO 241 SLOW_PYTHON 242 diff -Nru pcp-5.3.1/src/pmproxy/src/secure.c pcp-5.3.2/src/pmproxy/src/secure.c --- pcp-5.3.1/src/pmproxy/src/secure.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmproxy/src/secure.c 2021-07-30 04:05:06.000000000 +0000 @@ -16,13 +16,25 @@ #include #include +/* called with proxy->mutex locked */ static void remove_connection_from_queue(struct client *client) { + struct proxy *proxy = client->proxy; + if (client->secure.pending.writes_buffer != NULL) free(client->secure.pending.writes_buffer); - if (client->secure.pending.prev != NULL) - *client->secure.pending.prev = client->secure.pending.next; + if (client->secure.pending.prev == NULL) { + /* next (if any) becomes first in pending_writes list */ + proxy->pending_writes = client->secure.pending.next; + if (proxy->pending_writes) + proxy->pending_writes->secure.pending.prev = NULL; + } + else { + /* link next and prev */ + client->secure.pending.prev->secure.pending.next = client->secure.pending.next; + client->secure.pending.next->secure.pending.prev = client->secure.pending.prev; + } memset(&client->secure.pending, 0, sizeof(client->secure.pending)); } @@ -32,7 +44,9 @@ if (pmDebugOptions.auth || pmDebugOptions.http) fprintf(stderr, "%s: client %p\n", "on_secure_client_close", client); + uv_mutex_lock(&client->proxy->mutex); remove_connection_from_queue(client); + uv_mutex_unlock(&client->proxy->mutex); /* client->read and client->write freed by SSL_free */ SSL_free(client->secure.ssl); } @@ -40,6 +54,8 @@ static void maybe_flush_ssl(struct proxy *proxy, struct client *client) { + struct client *c; + if (client->secure.pending.queued) return; @@ -47,13 +63,19 @@ client->secure.pending.writes_count > 0) return; - client->secure.pending.next = proxy->pending_writes; - if (client->secure.pending.next != NULL) - client->secure.pending.next->secure.pending.prev = &client->secure.pending.next; - client->secure.pending.prev = &proxy->pending_writes; + uv_mutex_lock(&proxy->mutex); + if (proxy->pending_writes == NULL) { + proxy->pending_writes = client; + client->secure.pending.prev = client->secure.pending.next = NULL; + } + else { + for (c=proxy->pending_writes; c->secure.pending.next; c = c->secure.pending.next) + ; /**/ + c->secure.pending.next = client; + client->secure.pending.prev = c; + } client->secure.pending.queued = 1; - - proxy->pending_writes = client; + uv_mutex_unlock(&proxy->mutex); } static void @@ -135,10 +157,12 @@ void flush_secure_module(struct proxy *proxy) { - struct client *client, **head = &proxy->pending_writes; + struct client *client, **head; size_t i, used; int sts; + uv_mutex_lock(&proxy->mutex); + head = &proxy->pending_writes; while ((client = *head) != NULL) { flush_ssl_buffer(client); @@ -188,6 +212,7 @@ sizeof(uv_buf_t) * client->secure.pending.writes_count); } } + uv_mutex_unlock(&proxy->mutex); } void @@ -264,6 +289,11 @@ int flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |SSL_OP_NO_TLSv1_1; + if ((option = pmIniFileLookup(config, "pmproxy", "secure.enabled"))) { + if (strncmp(option, "true", sdslen(option)) != 0) + return; + } + if ((option = pmIniFileLookup(config, "pmproxy", "certificates"))) certificates = option; if ((option = pmIniFileLookup(config, "pmproxy", "private_key"))) diff -Nru pcp-5.3.1/src/pmproxy/src/server.c pcp-5.3.2/src/pmproxy/src/server.c --- pcp-5.3.1/src/pmproxy/src/server.c 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmproxy/src/server.c 2021-07-30 04:05:06.000000000 +0000 @@ -106,49 +106,20 @@ } } -static void -server_metrics_init(struct proxy *proxy) -{ - mmv_registry_t *registry; - pmAtomValue *value; - pmInDom noindom = MMV_INDOM_NULL; - pmUnits nounits = MMV_UNITS(0,0,0,0,0,0); - pid_t pid = getpid(); - char buffer[64]; - void *map; - - if ((registry = proxy->metrics[METRICS_SERVER]) == NULL) - return; - - mmv_stats_add_metric(registry, "pid", SERVER_PID, - MMV_TYPE_U32, MMV_SEM_DISCRETE, nounits, noindom, - "pmproxy PID", - "PID for the current pmproxy invocation"); - pmsprintf(buffer, sizeof(buffer), "%u", pid); - mmv_stats_add_metric_label(registry, SERVER_PID, - "pid", buffer, MMV_NUMBER_TYPE, 0); - - if ((map = mmv_stats_start(registry)) == NULL) { - fprintf(stderr, "%s: instrumentation disabled\n", pmGetProgname()); - return; - } - - if ((value = mmv_lookup_value_desc(map, "pid", NULL)) != NULL) - mmv_set_value(map, value, pid); -} - static struct proxy * server_init(int portcount, const char *localpath) { struct server *servers; struct proxy *proxy; int count; + mmv_registry_t *registry; if ((proxy = calloc(1, sizeof(struct proxy))) == NULL) { fprintf(stderr, "%s: out-of-memory in proxy server setup\n", pmGetProgname()); return NULL; } + uv_mutex_init(&proxy->mutex); count = portcount + (*localpath ? 1 : 0); if (count) { @@ -169,8 +140,8 @@ proxy->config = config; - proxymetrics(proxy, METRICS_SERVER); - server_metrics_init(proxy); + if ((registry = proxymetrics(proxy, METRICS_SERVER)) != NULL) + pmWebTimerSetMetricRegistry(registry); proxy->events = uv_default_loop(); @@ -251,6 +222,7 @@ client_put(struct client *client) { unsigned int refcount; + struct proxy *proxy = client->proxy; uv_mutex_lock(&client->mutex); assert(client->refcount); @@ -259,9 +231,11 @@ if (refcount == 0) { /* remove client from the doubly-linked list */ + uv_mutex_lock(&proxy->mutex); if (client->next != NULL) client->next->prev = client->prev; *client->prev = client->next; + uv_mutex_unlock(&proxy->mutex); if (client->protocol & STREAM_PCP) on_pcp_client_close(client); @@ -514,10 +488,12 @@ client->proxy = proxy; /* insert client into doubly-linked list at the head */ + uv_mutex_lock(&proxy->mutex); if ((client->next = proxy->first) != NULL) proxy->first->prev = &client->next; proxy->first = client; client->prev = &proxy->first; + uv_mutex_unlock(&proxy->mutex); status = uv_read_start((uv_stream_t *)&client->stream.u.tcp, on_buffer_alloc, on_client_read); diff -Nru pcp-5.3.1/src/pmproxy/src/server.h pcp-5.3.2/src/pmproxy/src/server.h --- pcp-5.3.1/src/pmproxy/src/server.h 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/pmproxy/src/server.h 2021-07-30 04:05:06.000000000 +0000 @@ -43,11 +43,6 @@ NUM_REGISTRY } proxy_registry; -typedef enum server_metric { - SERVER_PID, - NUM_SERVER_METRIC -} server_metric; - typedef struct stream_write_baton { uv_write_t writer; uv_buf_t buffer[2]; @@ -118,7 +113,7 @@ BIO *write; struct { struct client *next; - struct client **prev; + struct client *prev; unsigned int queued; size_t writes_count; uv_buf_t *writes_buffer; @@ -166,6 +161,7 @@ struct dict *config; /* configuration dictionary */ uv_loop_t *events; /* global, async event loop */ uv_callback_t write_callbacks; + uv_mutex_t mutex; /* protects client lists and pending writes */ } proxy; extern void proxylog(pmLogLevel, sds, void *); diff -Nru pcp-5.3.1/src/pmrep/conf/pmproxy.conf pcp-5.3.2/src/pmrep/conf/pmproxy.conf --- pcp-5.3.1/src/pmrep/conf/pmproxy.conf 2021-05-20 00:59:59.000000000 +0000 +++ pcp-5.3.2/src/pmrep/conf/pmproxy.conf 2021-07-30 04:05:06.000000000 +0000 @@ -23,6 +23,17 @@ pmproxy.discover.changed_callbacks = changed,,,,,1 pmproxy.discover.throttled_changed_callbacks = throttled,,,,,1 +[pmproxy-resource] +timestamp = yes +repeat_header = auto +cpu_percent = pmproxy.cpu.percent +cpu_percent.label = %%CPU +cpu_percent.formula = 100 * pmproxy.cpu.total +cpu_percent.unit = s +pmproxy.mem.datasz = Datasz,,,,6 +pmproxy.mem.maxrss = MaxRss,,,,6 + + [pmproxy-series] timestamp = yes repeat_header = auto diff -Nru pcp-5.3.1/src/python/pcp/pmapi.py pcp-5.3.2/src/python/pcp/pmapi.py --- pcp-5.3.1/src/python/pcp/pmapi.py 2020-09-24 23:13:08.000000000 +0000 +++ pcp-5.3.2/src/python/pcp/pmapi.py 2021-07-30 04:05:06.000000000 +0000 @@ -1,6 +1,6 @@ """ Wrapper module for LIBPCP - the core Performace Co-Pilot API # -# Copyright (C) 2012-2020 Red Hat +# Copyright (C) 2012-2021 Red Hat # Copyright (C) 2009-2012 Michael T. Werner # # This file is part of the "pcp" module, the python interfaces for the @@ -2844,7 +2844,8 @@ def __del__(self): """Override pmContext ctor to eschew pmDestroyContext.""" - self._ctx = c_api.PM_ERR_NOCONTEXT + if c_api is not None and self._ctx != c_api.PM_ERR_NOCONTEXT: + self._ctx = c_api.PM_ERR_NOCONTEXT def __init__(self, typed=c_api.PM_CONTEXT_HOST, target="local:"): """Create a fetchgroup from a pmContext.""" diff -Nru pcp-5.3.1/src/python/pcp/pmconfig.py pcp-5.3.2/src/python/pcp/pmconfig.py --- pcp-5.3.1/src/python/pcp/pmconfig.py 2021-05-20 00:59:59.000000000 +0000 +++ pcp-5.3.2/src/python/pcp/pmconfig.py 2021-07-30 04:05:07.000000000 +0000 @@ -869,8 +869,8 @@ self.util.metrics[metric][3] = 1 else: self.util.metrics[metric][3] = 0 - # As a special service for the pmrep(1) utility, - # we force raw output with its archive mode. + # Force raw output with archive mode of any tool in order to + # create pmlogger(1) compatible archives that can be merged. if (hasattr(self.util, 'type') and self.util.type == 1) or \ self.util.metrics[metric][3] == 'raw' or \ (hasattr(self.util, 'output') and self.util.output == 'archive'): @@ -930,6 +930,11 @@ if not self.util.metrics[metric][2]: self.util.metrics[metric][2] = str(unit) + # Force native units with archive mode of any tool in order to + # create pmlogger(1) compatible archives that can be merged. + if hasattr(self.util, 'output') and self.util.output == 'archive': + self.util.metrics[metric][2] = str(unit) + # Finalize text label and unit/scale try: label = self.util.metrics[metric][2] diff -Nru pcp-5.3.1/src/selinux/GNUlocaldefs pcp-5.3.2/src/selinux/GNUlocaldefs --- pcp-5.3.1/src/selinux/GNUlocaldefs 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/selinux/GNUlocaldefs 2021-06-15 01:03:49.000000000 +0000 @@ -22,6 +22,7 @@ ifeq "$(PCP_SELINUX_CAP_USERNS_PTRACE)" "true" PCP_CAPUSERNS_PTRACE="class cap_userns sys_ptrace; \# pmda.proc" PCP_CAPUSERNS_PTRACE_RULE_PMIE="allow pcp_pmie_t self:cap_userns sys_ptrace;" +PCP_CAPUSERNS_PTRACE_RULE_PMCD="allow pcp_pmcd_t self:cap_userns sys_ptrace;" endif ifeq "$(PCP_SELINUX_UNRESERVED_PORT)" "true" diff -Nru pcp-5.3.1/src/selinux/GNUmakefile pcp-5.3.2/src/selinux/GNUmakefile --- pcp-5.3.1/src/selinux/GNUmakefile 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/selinux/GNUmakefile 2021-06-15 01:03:49.000000000 +0000 @@ -41,6 +41,7 @@ -e 's+@PCP_DOCKER_VAR_LIB_RULE@+'$(PCP_DOCKER_VAR_LIB_RULE)'+' \ -e 's+@PCP_CAPUSERNS_PTRACE@+'$(PCP_CAPUSERNS_PTRACE)'+' \ -e 's+@PCP_CAPUSERNS_PTRACE_RULE_PMIE@+'$(PCP_CAPUSERNS_PTRACE_RULE_PMIE)'+' \ + -e 's+@PCP_CAPUSERNS_PTRACE_RULE_PMCD@+'$(PCP_CAPUSERNS_PTRACE_RULE_PMCD)'+' \ -e 's+@PCP_UNRESERVED_PORT@+'$(PCP_UNRESERVED_PORT)'+' \ -e 's+@PCP_UNRESERVED_PORT_RULE_TCP@+'$(PCP_UNRESERVED_PORT_RULE_TCP)'+' \ -e 's+@PCP_UNRESERVED_PORT_RULE_UDP@+'$(PCP_UNRESERVED_PORT_RULE_UDP)'+' \ diff -Nru pcp-5.3.1/src/selinux/pcpupstream.te.in pcp-5.3.2/src/selinux/pcpupstream.te.in --- pcp-5.3.1/src/selinux/pcpupstream.te.in 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/src/selinux/pcpupstream.te.in 2021-06-15 01:03:49.000000000 +0000 @@ -150,7 +150,7 @@ #type=AVC msg=audit(YYY.11): avc: denied { sys_chroot kill sys_resource } for pid=25873 comm="pmdalinux" capability=18 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability #type=AVC msg=audit(YYY.87): avc: denied { chown } for pid=8999 comm="pmdasimple" capability=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability #type=AVC msg=audit(YYY.98): avc: denied { sys_pacct } for pid=YYYY comm="pmdaproc" capability=20 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0 -allow pcp_pmcd_t self:capability { kill sys_pacct chown sys_chroot ipc_lock sys_resource }; +allow pcp_pmcd_t self:capability { kill sys_pacct chown sys_chroot ipc_owner ipc_lock sys_resource }; #type=AVC msg=audit(YYY.12): avc: denied { read } for pid=29112 comm="pmdalinux" dev="nsfs" ino=4026532454 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:nsfs_t:s0 tclass=file permissive=1 @PCP_NSFS_RULE@ @@ -290,6 +290,9 @@ # type=AVC msg=audit(YYY.95): avc: denied { write } for pid=389594 comm="python3" name=".s.PGSQL.5432" dev="tmpfs" ino=746636 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:postgresql_var_run_t:s0 tclass=sock_file permissive=0 allow pcp_pmcd_t postgresql_var_run_t:sock_file { write }; +# type=AVC msg=audit(YYY.104): avc: denied { sys_ptrace } for pid=9375 comm="pmdaproc" capability=19 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=cap_userns permissive=1 +@PCP_CAPUSERNS_PTRACE_RULE_PMCD@ + #============= pcp_pmlogger_t ============== #type=AVC msg=audit(XXX.44): avc: denied { open write } for pid=YYYY comm="pmdaX" name="/" dev="tracefs" ino=1 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:kmsg_device_t:s0 tclass=chr_file permissive=0 allow pcp_pmlogger_t kmsg_device_t:chr_file { open write }; diff -Nru pcp-5.3.1/src/zshrc/_pcp pcp-5.3.2/src/zshrc/_pcp --- pcp-5.3.1/src/zshrc/_pcp 2021-06-03 23:38:03.000000000 +0000 +++ pcp-5.3.2/src/zshrc/_pcp 2021-07-30 04:05:07.000000000 +0000 @@ -1,4 +1,4 @@ -#compdef pcp pcp2elasticsearch pcp2graphite pcp2influxdb pcp2json pcp2spark pcp2xlsx pcp2xml pcp2zabbix pmafm pmchart pmclient pmclient_fg=pmclient pmdbg pmdiff pmdumplog pmdumptext pmerr pmfind pmie pmie2col pmiectl=pmlogctl pminfo pmiostat pmjson pmlc pmlogcheck pmlogctl pmlogextract pmlogger pmloglabel pmlogpaste pmlogreduce pmlogsize pmlogsummary pmprobe pmrep pmseries pmstat pmstore pmval pmevent +#compdef pcp pcp2elasticsearch pcp2graphite pcp2influxdb pcp2json pcp2spark pcp2xlsx pcp2xml pcp2zabbix pmafm pmchart pmclient pmclient_fg=pmclient pmdbg pmdiff pmdumplog pmdumptext pmerr pmevent=pmval pmfind pmie pmie2col pmiectl=pmlogctl pminfo pmiostat pmjson pmlc pmlogcheck pmlogctl pmlogextract pmlogger pmloglabel pmlogpaste pmlogreduce pmlogsize pmlogsummary pmprobe pmrep pmseries pmstat pmstore pmval # # PCP completions for zsh . # @@ -301,8 +301,6 @@ _arguments -C -S -s \ "$common_help[@]" \ "$common_most[@]" \ - "(-g --guimode $exargs)"{-g,--guimode}'[GUI mode with new time control]' \ - "(-p --guiport $exargs)"{-p+,--guiport=}'[specify existing time control port]:port:' \ "(-n --namespace $exargs)"{-n+,--namespace=}'[specify alternative PMNS]:pmnsfile:_files' \ "(-P --pause -h --host $exargs)"{-P,--pause}'[pause between updates in archive mode]' \ && return 0 @@ -346,6 +344,7 @@ "(-d --descs $exargs)"{-d,--descs}'[dump metric descriptions]' \ "(-e --labelsets $exargs)"{-e,--labelsets}'[dump all metric label metadata]' \ "(-h --helptext $exargs)"{-h,--helptext}'[dump all metric help text]' \ + "(-I --on-disk-insts $exargs)"{-I,--on-disk-insts}'[dump on-disk instance domain descriptions]' \ "(-i --insts $exargs)"{-i,--insts}'[dump instance domain descriptions]' \ "(-L $exargs)"-L'[verbose label dump]' \ "(-l --label $exargs)"{-l,--label}'[dump archive log label]' \ @@ -846,29 +845,7 @@ "(-a --archive --container -h --host -L --local-PMDA -K --spec-local $exargs)"{-U+,--nointerp=}'[specify uninterpolated metrics source archive]:archive:->archives' \ "(-v --verbose $exargs)"{-v,--verbose}'[verbose mode]' \ "(-w --width $exargs)"{-w+,--width=}'[set column width]:width:' \ - "(-X --timestamp $exargs)"{-X --timestamp}'[timestamps with more precision]' \ - "(-x --filter $exargs)"{-x+,--filter=}'[define event filter pattern]:filter:' \ - '1:metric:->metrics' \ - && return 0 - ;; - pmevent) - _arguments -C -S -s \ - "$common_help[@]" \ - "$common_most[@]" \ - "$common_pmda[@]" \ - "(-g --guimode $exargs)"{-g,--guimode}'[GUI mode with new time control]' \ - "(-p --guiport $exargs)"{-p+,--guiport=}'[specify existing time control port]:port:' \ - "(-n --namespace $exargs)"{-n+,--namespace=}'[specify alternative PMNS]:pmnsfile:_files' \ - "(--container -a --archive -U --nointerp $exargs)"--container=+'[specify container to query]:container:->containers' \ - "(--derived $exargs)"--derived=+'[specify derived metrics config]:file:_files' \ - "(-d --delay --container -h --host -L --local-PMDA -K --spec-local $exargs)"{-d,--delay}'[delay between updates in archive mode]' \ - "(-f --precision $exargs)"{-f+,--precision=}'[set fixed output format precision]:precision:' \ - "($exargs)"\*{-i+,--instances=}'[specify instances to report]:instances:->instances' \ - "(-r --raw $exargs)"{-r,--raw}'[report raw values]' \ - "(-a --archive --container -h --host -L --local-PMDA -K --spec-local $exargs)"{-U+,--nointerp=}'[specify uninterpolated metrics source archive]:archive:->archives' \ - "(-v --verbose $exargs)"{-v,--verbose}'[verbose mode]' \ - "(-w --width $exargs)"{-w+,--width=}'[set column width]:width:' \ - "(-X --timestamp $exargs)"{-X --timestamp}'[timestamps with more precision]' \ + "(-X --timestamp $exargs)"{-X,--timestamp}'[timestamps with more precision]' \ "(-x --filter $exargs)"{-x+,--filter=}'[define event filter pattern]:filter:' \ '1:metric:->metrics' \ && return 0 diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Action.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Action.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Action.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Action.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,709 @@ +/* +htop - Action.c +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "Action.h" + +#include +#include +#include + +#include "CategoriesPanel.h" +#include "CommandScreen.h" +#include "CRT.h" +#include "EnvScreen.h" +#include "FunctionBar.h" +#include "Hashtable.h" +#include "IncSet.h" +#include "InfoScreen.h" +#include "ListItem.h" +#include "Macros.h" +#include "MainPanel.h" +#include "OpenFilesScreen.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "ProvideCurses.h" +#include "ScreenManager.h" +#include "SignalsPanel.h" +#include "TraceScreen.h" +#include "Vector.h" +#include "XUtils.h" + +#if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY)) +#include "Affinity.h" +#include "AffinityPanel.h" +#endif + + +Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess) { + MainPanel* mainPanel = st->mainPanel; + Header* header = st->header; + + int y = ((Panel*)mainPanel)->y; + ScreenManager* scr = ScreenManager_new(header, st->settings, st, false); + scr->allowFocusChange = false; + ScreenManager_add(scr, list, x - 1); + ScreenManager_add(scr, (Panel*)mainPanel, -1); + Panel* panelFocus; + int ch; + bool unfollow = false; + int pid = followProcess ? MainPanel_selectedPid(mainPanel) : -1; + if (followProcess && header->pl->following == -1) { + header->pl->following = pid; + unfollow = true; + } + ScreenManager_run(scr, &panelFocus, &ch); + if (unfollow) { + header->pl->following = -1; + } + ScreenManager_delete(scr); + Panel_move((Panel*)mainPanel, 0, y); + Panel_resize((Panel*)mainPanel, COLS, LINES - y - 1); + if (panelFocus == list && ch == 13) { + if (followProcess) { + const Process* selected = (const Process*)Panel_getSelected((Panel*)mainPanel); + if (selected && selected->pid == pid) + return Panel_getSelected(list); + + beep(); + } else { + return Panel_getSelected(list); + } + } + + return NULL; +} + +// ---------------------------------------- + +static void Action_runSetup(State* st) { + ScreenManager* scr = ScreenManager_new(st->header, st->settings, st, true); + CategoriesPanel* panelCategories = CategoriesPanel_new(scr, st->settings, st->header, st->pl); + ScreenManager_add(scr, (Panel*) panelCategories, 16); + CategoriesPanel_makeMetersPage(panelCategories); + Panel* panelFocus; + int ch; + ScreenManager_run(scr, &panelFocus, &ch); + ScreenManager_delete(scr); + if (st->settings->changed) { + Header_writeBackToSettings(st->header); + } +} + +static bool changePriority(MainPanel* panel, int delta) { + bool anyTagged; + bool ok = MainPanel_foreachProcess(panel, Process_changePriorityBy, (Arg) { .i = delta }, &anyTagged); + if (!ok) + beep(); + return anyTagged; +} + +static void addUserToVector(ht_key_t key, void* userCast, void* panelCast) { + const char* user = userCast; + Panel* panel = panelCast; + Panel_add(panel, (Object*) ListItem_new(user, key)); +} + +bool Action_setUserOnly(const char* userName, uid_t* userId) { + const struct passwd* user = getpwnam(userName); + if (user) { + *userId = user->pw_uid; + return true; + } + *userId = (uid_t)-1; + return false; +} + +static void tagAllChildren(Panel* panel, Process* parent) { + parent->tag = true; + pid_t ppid = parent->pid; + for (int i = 0; i < Panel_size(panel); i++) { + Process* p = (Process*) Panel_get(panel, i); + if (!p->tag && Process_isChildOf(p, ppid)) { + tagAllChildren(panel, p); + } + } +} + +static bool expandCollapse(Panel* panel) { + Process* p = (Process*) Panel_getSelected(panel); + if (!p) + return false; + + p->showChildren = !p->showChildren; + return true; +} + +static bool collapseIntoParent(Panel* panel) { + const Process* p = (Process*) Panel_getSelected(panel); + if (!p) + return false; + + pid_t ppid = Process_getParentPid(p); + for (int i = 0; i < Panel_size(panel); i++) { + Process* q = (Process*) Panel_get(panel, i); + if (q->pid == ppid) { + q->showChildren = false; + Panel_setSelected(panel, i); + return true; + } + } + return false; +} + +Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) { + Settings_setSortKey(settings, sortKey); + return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING; +} + +// ---------------------------------------- + +static Htop_Reaction actionSetSortColumn(State* st) { + Htop_Reaction reaction = HTOP_OK; + Panel* sortPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Sort ", "Cancel ")); + Panel_setHeader(sortPanel, "Sort by"); + const ProcessField* fields = st->settings->fields; + for (int i = 0; fields[i]; i++) { + char* name = String_trim(Process_fields[fields[i]].name); + Panel_add(sortPanel, (Object*) ListItem_new(name, fields[i])); + if (fields[i] == Settings_getActiveSortKey(st->settings)) + Panel_setSelected(sortPanel, i); + + free(name); + } + const ListItem* field = (const ListItem*) Action_pickFromVector(st, sortPanel, 15, false); + if (field) { + reaction |= Action_setSortKey(st->settings, field->key); + } + Object_delete(sortPanel); + + if (st->pauseProcessUpdate) + ProcessList_sort(st->pl); + + return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +static Htop_Reaction actionSortByPID(State* st) { + return Action_setSortKey(st->settings, PID); +} + +static Htop_Reaction actionSortByMemory(State* st) { + return Action_setSortKey(st->settings, PERCENT_MEM); +} + +static Htop_Reaction actionSortByCPU(State* st) { + return Action_setSortKey(st->settings, PERCENT_CPU); +} + +static Htop_Reaction actionSortByTime(State* st) { + return Action_setSortKey(st->settings, TIME); +} + +static Htop_Reaction actionToggleKernelThreads(State* st) { + st->settings->hideKernelThreads = !st->settings->hideKernelThreads; + return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionToggleUserlandThreads(State* st) { + st->settings->hideUserlandThreads = !st->settings->hideUserlandThreads; + return HTOP_RECALCULATE | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionToggleProgramPath(State* st) { + st->settings->showProgramPath = !st->settings->showProgramPath; + return HTOP_REFRESH | HTOP_SAVE_SETTINGS; +} + +static Htop_Reaction actionToggleMergedCommand(State* st) { + st->settings->showMergedCommand = !st->settings->showMergedCommand; + return HTOP_REFRESH | HTOP_SAVE_SETTINGS; +} + +static Htop_Reaction actionToggleTreeView(State* st) { + st->settings->treeView = !st->settings->treeView; + + if (!st->settings->allBranchesCollapsed) + ProcessList_expandTree(st->pl); + return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) { + st->settings->allBranchesCollapsed = !st->settings->allBranchesCollapsed; + if (st->settings->allBranchesCollapsed) + ProcessList_collapseAllBranches(st->pl); + else + ProcessList_expandTree(st->pl); + return HTOP_REFRESH | HTOP_SAVE_SETTINGS; +} + +static Htop_Reaction actionIncFilter(State* st) { + IncSet* inc = (st->mainPanel)->inc; + IncSet_activate(inc, INC_FILTER, (Panel*)st->mainPanel); + st->pl->incFilter = IncSet_filter(inc); + return HTOP_REFRESH | HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionIncSearch(State* st) { + IncSet_reset(st->mainPanel->inc, INC_SEARCH); + IncSet_activate(st->mainPanel->inc, INC_SEARCH, (Panel*)st->mainPanel); + return HTOP_REFRESH | HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionHigherPriority(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + bool changed = changePriority(st->mainPanel, -1); + return changed ? HTOP_REFRESH : HTOP_OK; +} + +static Htop_Reaction actionLowerPriority(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + bool changed = changePriority(st->mainPanel, 1); + return changed ? HTOP_REFRESH : HTOP_OK; +} + +static Htop_Reaction actionInvertSortOrder(State* st) { + Settings_invertSortOrder(st->settings); + if (st->pauseProcessUpdate) + ProcessList_sort(st->pl); + return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionExpandOrCollapse(State* st) { + bool changed = expandCollapse((Panel*)st->mainPanel); + return changed ? HTOP_RECALCULATE : HTOP_OK; +} + +static Htop_Reaction actionCollapseIntoParent(State* st) { + if (!st->settings->treeView) { + return HTOP_OK; + } + bool changed = collapseIntoParent((Panel*)st->mainPanel); + return changed ? HTOP_RECALCULATE : HTOP_OK; +} + +static Htop_Reaction actionExpandCollapseOrSortColumn(State* st) { + return st->settings->treeView ? actionExpandOrCollapse(st) : actionSetSortColumn(st); +} + +static Htop_Reaction actionQuit(ATTR_UNUSED State* st) { + return HTOP_QUIT; +} + +static Htop_Reaction actionSetAffinity(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + if (st->pl->cpuCount == 1) + return HTOP_OK; + +#if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY)) + const Process* p = (const Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + Affinity* affinity1 = Affinity_get(p, st->pl); + if (!affinity1) + return HTOP_OK; + + int width; + Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width); + width += 1; /* we add a gap between the panels */ + Affinity_delete(affinity1); + + const void* set = Action_pickFromVector(st, affinityPanel, width, true); + if (set) { + Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, st->pl); + bool ok = MainPanel_foreachProcess(st->mainPanel, Affinity_set, (Arg) { .v = affinity2 }, NULL); + if (!ok) + beep(); + Affinity_delete(affinity2); + } + Object_delete(affinityPanel); +#endif + return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +static Htop_Reaction actionKill(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + Panel* signalsPanel = SignalsPanel_new(); + const ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 15, true); + if (sgn && sgn->key != 0) { + Panel_setHeader((Panel*)st->mainPanel, "Sending..."); + Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st)); + refresh(); + MainPanel_foreachProcess(st->mainPanel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL); + napms(500); + } + Panel_delete((Object*)signalsPanel); + return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +static Htop_Reaction actionFilterByUser(State* st) { + Panel* usersPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Show ", "Cancel ")); + Panel_setHeader(usersPanel, "Show processes of:"); + UsersTable_foreach(st->ut, addUserToVector, usersPanel); + Vector_insertionSort(usersPanel->items); + ListItem* allUsers = ListItem_new("All users", -1); + Panel_insert(usersPanel, 0, (Object*) allUsers); + const ListItem* picked = (ListItem*) Action_pickFromVector(st, usersPanel, 20, false); + if (picked) { + if (picked == allUsers) { + st->pl->userId = (uid_t)-1; + } else { + Action_setUserOnly(ListItem_getRef(picked), &(st->pl->userId)); + } + } + Panel_delete((Object*)usersPanel); + return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +Htop_Reaction Action_follow(State* st) { + st->pl->following = MainPanel_selectedPid(st->mainPanel); + Panel_setSelectionColor((Panel*)st->mainPanel, PANEL_SELECTION_FOLLOW); + return HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionSetup(State* st) { + Action_runSetup(st); + int headerHeight = Header_calculateHeight(st->header); + Panel_move((Panel*)st->mainPanel, 0, headerHeight); + Panel_resize((Panel*)st->mainPanel, COLS, LINES - headerHeight - 1); + return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +static Htop_Reaction actionLsof(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + OpenFilesScreen* ofs = OpenFilesScreen_new(p); + InfoScreen_run((InfoScreen*)ofs); + OpenFilesScreen_delete((Object*)ofs); + clear(); + CRT_enableDelay(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +static Htop_Reaction actionShowLocks(State* st) { + const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + ProcessLocksScreen* pls = ProcessLocksScreen_new(p); + InfoScreen_run((InfoScreen*)pls); + ProcessLocksScreen_delete((Object*)pls); + clear(); + CRT_enableDelay(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +static Htop_Reaction actionStrace(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + TraceScreen* ts = TraceScreen_new(p); + bool ok = TraceScreen_forkTracer(ts); + if (ok) { + InfoScreen_run((InfoScreen*)ts); + } + TraceScreen_delete((Object*)ts); + clear(); + CRT_enableDelay(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +static Htop_Reaction actionTag(State* st) { + Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + Process_toggleTag(p); + Panel_onKey((Panel*)st->mainPanel, KEY_DOWN); + return HTOP_OK; +} + +static Htop_Reaction actionRedraw(ATTR_UNUSED State* st) { + clear(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +static Htop_Reaction actionTogglePauseProcessUpdate(State* st) { + st->pauseProcessUpdate = !st->pauseProcessUpdate; + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +static const struct { + const char* key; + bool roInactive; + const char* info; +} helpLeft[] = { + { .key = " Arrows: ", .roInactive = false, .info = "scroll process list" }, + { .key = " Digits: ", .roInactive = false, .info = "incremental PID search" }, + { .key = " F3 /: ", .roInactive = false, .info = "incremental name search" }, + { .key = " F4 \\: ", .roInactive = false, .info = "incremental name filtering" }, + { .key = " F5 t: ", .roInactive = false, .info = "tree view" }, + { .key = " p: ", .roInactive = false, .info = "toggle program path" }, + { .key = " m: ", .roInactive = false, .info = "toggle merged command" }, + { .key = " Z: ", .roInactive = false, .info = "pause/resume process updates" }, + { .key = " u: ", .roInactive = false, .info = "show processes of a single user" }, + { .key = " H: ", .roInactive = false, .info = "hide/show user process threads" }, + { .key = " K: ", .roInactive = false, .info = "hide/show kernel threads" }, + { .key = " F: ", .roInactive = false, .info = "cursor follows process" }, + { .key = " + - *: ", .roInactive = false, .info = "expand/collapse tree/toggle all" }, + { .key = "N P M T: ", .roInactive = false, .info = "sort by PID, CPU%, MEM% or TIME" }, + { .key = " I: ", .roInactive = false, .info = "invert sort order" }, + { .key = " F6 > .: ", .roInactive = false, .info = "select sort column" }, + { .key = NULL, .info = NULL } +}; + +static const struct { + const char* key; + bool roInactive; + const char* info; +} helpRight[] = { + { .key = " Space: ", .roInactive = false, .info = "tag process" }, + { .key = " c: ", .roInactive = false, .info = "tag process and its children" }, + { .key = " U: ", .roInactive = false, .info = "untag all processes" }, + { .key = " F9 k: ", .roInactive = true, .info = "kill process/tagged processes" }, + { .key = " F7 ]: ", .roInactive = true, .info = "higher priority (root only)" }, + { .key = " F8 [: ", .roInactive = false, .info = "lower priority (+ nice)" }, +#if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY)) + { .key = " a: ", .roInactive = true, .info = "set CPU affinity" }, +#endif + { .key = " e: ", .roInactive = false, .info = "show process environment" }, + { .key = " i: ", .roInactive = true, .info = "set IO priority" }, + { .key = " l: ", .roInactive = true, .info = "list open files with lsof" }, + { .key = " x: ", .roInactive = false, .info = "list file locks of process" }, + { .key = " s: ", .roInactive = true, .info = "trace syscalls with strace" }, + { .key = " w: ", .roInactive = false, .info = "wrap process command in multiple lines" }, + { .key = " F2 C S: ", .roInactive = false, .info = "setup" }, + { .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" }, + { .key = " F10 q: ", .roInactive = false, .info = "quit" }, + { .key = NULL, .info = NULL } +}; + +static inline void addattrstr( int attr, const char* str) { + attrset(attr); + addstr(str); +} + +static Htop_Reaction actionHelp(State* st) { + clear(); + attrset(CRT_colors[HELP_BOLD]); + + for (int i = 0; i < LINES - 1; i++) + mvhline(i, 0, ' ', COLS); + + int line = 0; + + mvaddstr(line++, 0, "htop " VERSION " - " COPYRIGHT); + mvaddstr(line++, 0, "Released under the GNU GPLv2. See 'man' page for more info."); + + attrset(CRT_colors[DEFAULT_COLOR]); + line++; + mvaddstr(line++, 0, "CPU usage bar: "); + + addattrstr(CRT_colors[BAR_BORDER], "["); + if (st->settings->detailedCPUTime) { + addattrstr(CRT_colors[CPU_NICE_TEXT], "low"); addstr("/"); + addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/"); + addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/"); + addattrstr(CRT_colors[CPU_IRQ], "irq"); addstr("/"); + addattrstr(CRT_colors[CPU_SOFTIRQ], "soft-irq"); addstr("/"); + addattrstr(CRT_colors[CPU_STEAL], "steal"); addstr("/"); + addattrstr(CRT_colors[CPU_GUEST], "guest"); addstr("/"); + addattrstr(CRT_colors[CPU_IOWAIT], "io-wait"); + addattrstr(CRT_colors[BAR_SHADOW], " used%"); + } else { + addattrstr(CRT_colors[CPU_NICE_TEXT], "low-priority"); addstr("/"); + addattrstr(CRT_colors[CPU_NORMAL], "normal"); addstr("/"); + addattrstr(CRT_colors[CPU_SYSTEM], "kernel"); addstr("/"); + addattrstr(CRT_colors[CPU_GUEST], "virtualiz"); + addattrstr(CRT_colors[BAR_SHADOW], " used%"); + } + addattrstr(CRT_colors[BAR_BORDER], "]"); + attrset(CRT_colors[DEFAULT_COLOR]); + mvaddstr(line++, 0, "Memory bar: "); + addattrstr(CRT_colors[BAR_BORDER], "["); + addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/"); + addattrstr(CRT_colors[MEMORY_BUFFERS_TEXT], "buffers"); addstr("/"); + addattrstr(CRT_colors[MEMORY_SHARED], "shared"); addstr("/"); + addattrstr(CRT_colors[MEMORY_CACHE], "cache"); + addattrstr(CRT_colors[BAR_SHADOW], " used/total"); + addattrstr(CRT_colors[BAR_BORDER], "]"); + attrset(CRT_colors[DEFAULT_COLOR]); + mvaddstr(line++, 0, "Swap bar: "); + addattrstr(CRT_colors[BAR_BORDER], "["); + addattrstr(CRT_colors[SWAP], "used"); +#ifdef HTOP_LINUX + addattrstr(CRT_colors[BAR_SHADOW], "/"); + addattrstr(CRT_colors[SWAP_CACHE], "cache"); + addattrstr(CRT_colors[BAR_SHADOW], " used/total"); +#else + addattrstr(CRT_colors[BAR_SHADOW], " used/total"); +#endif + addattrstr(CRT_colors[BAR_BORDER], "]"); + attrset(CRT_colors[DEFAULT_COLOR]); + mvaddstr(line++, 0, "Type and layout of header meters are configurable in the setup screen."); + if (CRT_colorScheme == COLORSCHEME_MONOCHROME) { + mvaddstr(line, 0, "In monochrome, meters display as different chars, in order: |#*@$%&."); + } + line++; + + mvaddstr(line++, 0, "Process state: R: running; S: sleeping; T: traced/stopped; Z: zombie; D: disk sleep"); + + line++; + + const bool readonly = Settings_isReadonly(); + + int item; + for (item = 0; helpLeft[item].key; item++) { + attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[DEFAULT_COLOR]); + mvaddstr(line + item, 10, helpLeft[item].info); + attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[HELP_BOLD]); + mvaddstr(line + item, 1, helpLeft[item].key); + if (String_eq(helpLeft[item].key, " H: ")) { + attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[PROCESS_THREAD]); + mvaddstr(line + item, 33, "threads"); + } else if (String_eq(helpLeft[item].key, " K: ")) { + attrset((helpLeft[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[PROCESS_THREAD]); + mvaddstr(line + item, 27, "threads"); + } + } + int leftHelpItems = item; + + for (item = 0; helpRight[item].key; item++) { + attrset((helpRight[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[HELP_BOLD]); + mvaddstr(line + item, 41, helpRight[item].key); + attrset((helpRight[item].roInactive && readonly) ? CRT_colors[HELP_SHADOW] : CRT_colors[DEFAULT_COLOR]); + mvaddstr(line + item, 50, helpRight[item].info); + } + line += MAXIMUM(leftHelpItems, item); + line++; + + attrset(CRT_colors[HELP_BOLD]); + mvaddstr(line++, 0, "Press any key to return."); + attrset(CRT_colors[DEFAULT_COLOR]); + refresh(); + CRT_readKey(); + clear(); + + return HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_KEEP_FOLLOWING; +} + +static Htop_Reaction actionUntagAll(State* st) { + for (int i = 0; i < Panel_size((Panel*)st->mainPanel); i++) { + Process* p = (Process*) Panel_get((Panel*)st->mainPanel, i); + p->tag = false; + } + return HTOP_REFRESH; +} + +static Htop_Reaction actionTagAllChildren(State* st) { + Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + tagAllChildren((Panel*)st->mainPanel, p); + return HTOP_OK; +} + +static Htop_Reaction actionShowEnvScreen(State* st) { + Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + EnvScreen* es = EnvScreen_new(p); + InfoScreen_run((InfoScreen*)es); + EnvScreen_delete((Object*)es); + clear(); + CRT_enableDelay(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +static Htop_Reaction actionShowCommandScreen(State* st) { + Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + CommandScreen* cmdScr = CommandScreen_new(p); + InfoScreen_run((InfoScreen*)cmdScr); + CommandScreen_delete((Object*)cmdScr); + clear(); + CRT_enableDelay(); + return HTOP_REFRESH | HTOP_REDRAW_BAR; +} + +void Action_setBindings(Htop_Action* keys) { + keys[' '] = actionTag; + keys['*'] = actionExpandOrCollapseAllBranches; + keys['+'] = actionExpandOrCollapse; + keys[','] = actionSetSortColumn; + keys['-'] = actionExpandOrCollapse; + keys['.'] = actionSetSortColumn; + keys['/'] = actionIncSearch; + keys['<'] = actionSetSortColumn; + keys['='] = actionExpandOrCollapse; + keys['>'] = actionSetSortColumn; + keys['?'] = actionHelp; + keys['C'] = actionSetup; + keys['F'] = Action_follow; + keys['H'] = actionToggleUserlandThreads; + keys['I'] = actionInvertSortOrder; + keys['K'] = actionToggleKernelThreads; + keys['M'] = actionSortByMemory; + keys['N'] = actionSortByPID; + keys['P'] = actionSortByCPU; + keys['S'] = actionSetup; + keys['T'] = actionSortByTime; + keys['U'] = actionUntagAll; + keys['Z'] = actionTogglePauseProcessUpdate; + keys['['] = actionLowerPriority; + keys['\014'] = actionRedraw; // Ctrl+L + keys['\177'] = actionCollapseIntoParent; + keys['\\'] = actionIncFilter; + keys[']'] = actionHigherPriority; + keys['a'] = actionSetAffinity; + keys['c'] = actionTagAllChildren; + keys['e'] = actionShowEnvScreen; + keys['h'] = actionHelp; + keys['k'] = actionKill; + keys['l'] = actionLsof; + keys['m'] = actionToggleMergedCommand; + keys['p'] = actionToggleProgramPath; + keys['q'] = actionQuit; + keys['s'] = actionStrace; + keys['t'] = actionToggleTreeView; + keys['u'] = actionFilterByUser; + keys['w'] = actionShowCommandScreen; + keys['x'] = actionShowLocks; + keys[KEY_F(1)] = actionHelp; + keys[KEY_F(2)] = actionSetup; + keys[KEY_F(3)] = actionIncSearch; + keys[KEY_F(4)] = actionIncFilter; + keys[KEY_F(5)] = actionToggleTreeView; + keys[KEY_F(6)] = actionSetSortColumn; + keys[KEY_F(7)] = actionHigherPriority; + keys[KEY_F(8)] = actionLowerPriority; + keys[KEY_F(9)] = actionKill; + keys[KEY_F(10)] = actionQuit; + keys[KEY_F(18)] = actionExpandCollapseOrSortColumn; + keys[KEY_RECLICK] = actionExpandOrCollapse; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Action.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Action.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Action.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Action.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,63 @@ +#ifndef HEADER_Action +#define HEADER_Action +/* +htop - Action.h +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +#include "Header.h" +#include "Object.h" +#include "Panel.h" +#include "Process.h" +#include "ProcessList.h" +#include "Settings.h" +#include "UsersTable.h" + + +typedef enum { + HTOP_OK = 0x00, + HTOP_REFRESH = 0x01, + HTOP_RECALCULATE = 0x03, // implies HTOP_REFRESH + HTOP_SAVE_SETTINGS = 0x04, + HTOP_KEEP_FOLLOWING = 0x08, + HTOP_QUIT = 0x10, + HTOP_REDRAW_BAR = 0x20, + HTOP_UPDATE_PANELHDR = 0x41, // implies HTOP_REFRESH +} Htop_Reaction; + +struct MainPanel_; + +typedef struct State_ { + Settings* settings; + UsersTable* ut; + ProcessList* pl; + struct MainPanel_* mainPanel; + Header* header; + bool pauseProcessUpdate; + bool hideProcessSelection; +} State; + +static inline bool State_hideFunctionBar(const State* st) { + return st->settings->hideFunctionBar == 2 || (st->settings->hideFunctionBar == 1 && st->hideProcessSelection); +} + +typedef Htop_Reaction (*Htop_Action)(State* st); + +Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess); + +bool Action_setUserOnly(const char* userName, uid_t* userId); + +Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey); + +Htop_Reaction Action_follow(State* st); + +void Action_setBindings(Htop_Action* keys); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Affinity.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Affinity.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Affinity.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Affinity.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,115 @@ +/* +htop - Affinity.c +(C) 2004-2011 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "Affinity.h" + +#include + +#include "XUtils.h" + +#if defined(HAVE_LIBHWLOC) +#include +#include +#ifdef __linux__ +#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD +#else +#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS +#endif +#elif defined(HAVE_LINUX_AFFINITY) +#include +#endif + + +Affinity* Affinity_new(ProcessList* pl) { + Affinity* this = xCalloc(1, sizeof(Affinity)); + this->size = 8; + this->cpus = xCalloc(this->size, sizeof(unsigned int)); + this->pl = pl; + return this; +} + +void Affinity_delete(Affinity* this) { + free(this->cpus); + free(this); +} + +void Affinity_add(Affinity* this, unsigned int id) { + if (this->used == this->size) { + this->size *= 2; + this->cpus = xRealloc(this->cpus, sizeof(unsigned int) * this->size); + } + this->cpus[this->used] = id; + this->used++; +} + + +#if defined(HAVE_LIBHWLOC) + +Affinity* Affinity_get(const Process* proc, ProcessList* pl) { + hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); + bool ok = (hwloc_get_proc_cpubind(pl->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0); + Affinity* affinity = NULL; + if (ok) { + affinity = Affinity_new(pl); + if (hwloc_bitmap_last(cpuset) == -1) { + for (unsigned int i = 0; i < pl->cpuCount; i++) { + Affinity_add(affinity, i); + } + } else { + unsigned int id; + hwloc_bitmap_foreach_begin(id, cpuset); + Affinity_add(affinity, id); + hwloc_bitmap_foreach_end(); + } + } + hwloc_bitmap_free(cpuset); + return affinity; +} + +bool Affinity_set(Process* proc, Arg arg) { + Affinity* this = arg.v; + hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); + for (unsigned int i = 0; i < this->used; i++) { + hwloc_bitmap_set(cpuset, this->cpus[i]); + } + bool ok = (hwloc_set_proc_cpubind(this->pl->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0); + hwloc_bitmap_free(cpuset); + return ok; +} + +#elif defined(HAVE_LINUX_AFFINITY) + +Affinity* Affinity_get(const Process* proc, ProcessList* pl) { + cpu_set_t cpuset; + bool ok = (sched_getaffinity(proc->pid, sizeof(cpu_set_t), &cpuset) == 0); + if (!ok) + return NULL; + + Affinity* affinity = Affinity_new(pl); + for (unsigned int i = 0; i < pl->cpuCount; i++) { + if (CPU_ISSET(i, &cpuset)) { + Affinity_add(affinity, i); + } + } + return affinity; +} + +bool Affinity_set(Process* proc, Arg arg) { + Affinity* this = arg.v; + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + for (unsigned int i = 0; i < this->used; i++) { + CPU_SET(this->cpus[i], &cpuset); + } + bool ok = (sched_setaffinity(proc->pid, sizeof(unsigned long), &cpuset) == 0); + return ok; +} + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Affinity.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Affinity.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Affinity.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Affinity.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,49 @@ +#ifndef HEADER_Affinity +#define HEADER_Affinity +/* +htop - Affinity.h +(C) 2004-2011 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "ProcessList.h" + +#if defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY) +#include + +#include "Object.h" +#include "Process.h" +#endif + + +#if defined(HAVE_LIBHWLOC) && defined(HAVE_LINUX_AFFINITY) +#error hwloc and linux affinity are mutual exclusive. +#endif + + +typedef struct Affinity_ { + ProcessList* pl; + unsigned int size; + unsigned int used; + unsigned int* cpus; +} Affinity; + +Affinity* Affinity_new(ProcessList* pl); + +void Affinity_delete(Affinity* this); + +void Affinity_add(Affinity* this, unsigned int id); + +#if defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY) + +Affinity* Affinity_get(const Process* proc, ProcessList* pl); + +bool Affinity_set(Process* proc, Arg arg); + +#endif /* HAVE_LIBHWLOC || HAVE_LINUX_AFFINITY */ + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AffinityPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/AffinityPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AffinityPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AffinityPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,439 @@ +/* +htop - AffinityPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "AffinityPanel.h" + +#include +#include +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Object.h" +#include "ProvideCurses.h" +#include "RichString.h" +#include "Settings.h" +#include "Vector.h" +#include "XUtils.h" + +#ifdef HAVE_LIBHWLOC +#include +#include +#endif + + +typedef struct MaskItem_ { + Object super; + char* text; + char* indent; /* used also as an condition whether this is a tree node */ + int value; /* tri-state: 0 - off, 1 - some set, 2 - all set */ + int sub_tree; /* tri-state: 0 - no sub-tree, 1 - open sub-tree, 2 - closed sub-tree */ + Vector* children; + #ifdef HAVE_LIBHWLOC + bool ownCpuset; + hwloc_bitmap_t cpuset; + #else + int cpu; + #endif +} MaskItem; + +static void MaskItem_delete(Object* cast) { + MaskItem* this = (MaskItem*) cast; + free(this->text); + free(this->indent); + Vector_delete(this->children); + #ifdef HAVE_LIBHWLOC + if (this->ownCpuset) + hwloc_bitmap_free(this->cpuset); + #endif + free(this); +} + +static void MaskItem_display(const Object* cast, RichString* out) { + const MaskItem* this = (const MaskItem*)cast; + assert (this != NULL); + RichString_appendAscii(out, CRT_colors[CHECK_BOX], "["); + if (this->value == 2) { + RichString_appendAscii(out, CRT_colors[CHECK_MARK], "x"); + } else if (this->value == 1) { + RichString_appendAscii(out, CRT_colors[CHECK_MARK], "o"); + } else { + RichString_appendAscii(out, CRT_colors[CHECK_MARK], " "); + } + RichString_appendAscii(out, CRT_colors[CHECK_BOX], "]"); + RichString_appendAscii(out, CRT_colors[CHECK_TEXT], " "); + if (this->indent) { + RichString_appendWide(out, CRT_colors[PROCESS_TREE], this->indent); + RichString_appendWide(out, CRT_colors[PROCESS_TREE], + this->sub_tree == 2 + ? CRT_treeStr[TREE_STR_OPEN] + : CRT_treeStr[TREE_STR_SHUT]); + RichString_appendAscii(out, CRT_colors[CHECK_TEXT], " "); + } + RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->text); +} + +static const ObjectClass MaskItem_class = { + .display = MaskItem_display, + .delete = MaskItem_delete +}; + +#ifdef HAVE_LIBHWLOC + +static MaskItem* MaskItem_newMask(const char* text, const char* indent, hwloc_bitmap_t cpuset, bool owner) { + MaskItem* this = AllocThis(MaskItem); + this->text = xStrdup(text); + this->indent = xStrdup(indent); /* nonnull for tree node */ + this->value = 0; + this->ownCpuset = owner; + this->cpuset = cpuset; + this->sub_tree = hwloc_bitmap_weight(cpuset) > 1 ? 1 : 0; + this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE); + return this; +} + +#endif + +static MaskItem* MaskItem_newSingleton(const char* text, int cpu, bool isSet) { + MaskItem* this = AllocThis(MaskItem); + this->text = xStrdup(text); + this->indent = NULL; /* not a tree node */ + this->sub_tree = 0; + this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE); + + #ifdef HAVE_LIBHWLOC + this->ownCpuset = true; + this->cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(this->cpuset, cpu); + #else + this->cpu = cpu; + #endif + this->value = isSet ? 2 : 0; + + return this; +} + +typedef struct AffinityPanel_ { + Panel super; + ProcessList* pl; + bool topoView; + Vector* cpuids; + unsigned width; + + #ifdef HAVE_LIBHWLOC + MaskItem* topoRoot; + hwloc_const_cpuset_t allCpuset; + hwloc_bitmap_t workCpuset; + #endif +} AffinityPanel; + +static void AffinityPanel_delete(Object* cast) { + AffinityPanel* this = (AffinityPanel*) cast; + Panel* super = (Panel*) this; + Panel_done(super); + Vector_delete(this->cpuids); + #ifdef HAVE_LIBHWLOC + hwloc_bitmap_free(this->workCpuset); + MaskItem_delete((Object*) this->topoRoot); + #endif + free(this); +} + +#ifdef HAVE_LIBHWLOC + +static void AffinityPanel_updateItem(AffinityPanel* this, MaskItem* item) { + Panel* super = (Panel*) this; + + item->value = hwloc_bitmap_isincluded(item->cpuset, this->workCpuset) ? 2 : + hwloc_bitmap_intersects(item->cpuset, this->workCpuset) ? 1 : 0; + + Panel_add(super, (Object*) item); +} + +static void AffinityPanel_updateTopo(AffinityPanel* this, MaskItem* item) { + AffinityPanel_updateItem(this, item); + + if (item->sub_tree == 2) + return; + + for (int i = 0; i < Vector_size(item->children); i++) + AffinityPanel_updateTopo(this, (MaskItem*) Vector_get(item->children, i)); +} + +#endif + +static void AffinityPanel_update(AffinityPanel* this, bool keepSelected) { + Panel* super = (Panel*) this; + + FunctionBar_setLabel(super->currentBar, KEY_F(3), this->topoView ? "Collapse/Expand" : ""); + + int oldSelected = Panel_getSelectedIndex(super); + Panel_prune(super); + + #ifdef HAVE_LIBHWLOC + if (this->topoView) { + AffinityPanel_updateTopo(this, this->topoRoot); + } else { + for (int i = 0; i < Vector_size(this->cpuids); i++) { + AffinityPanel_updateItem(this, (MaskItem*) Vector_get(this->cpuids, i)); + } + } + #else + Panel_splice(super, this->cpuids); + #endif + + if (keepSelected) + Panel_setSelected(super, oldSelected); + + super->needsRedraw = true; +} + +static HandlerResult AffinityPanel_eventHandler(Panel* super, int ch) { + AffinityPanel* this = (AffinityPanel*) super; + HandlerResult result = IGNORED; + MaskItem* selected = (MaskItem*) Panel_getSelected(super); + bool keepSelected = true; + + switch(ch) { + case KEY_MOUSE: + case KEY_RECLICK: + case ' ': + #ifdef HAVE_LIBHWLOC + if (selected->value == 2) { + /* Item was selected, so remove this mask from the top cpuset. */ + hwloc_bitmap_andnot(this->workCpuset, this->workCpuset, selected->cpuset); + selected->value = 0; + } else { + /* Item was not or only partial selected, so set all bits from this object + in the top cpuset. */ + hwloc_bitmap_or(this->workCpuset, this->workCpuset, selected->cpuset); + selected->value = 2; + } + #else + selected->value = selected->value ? 0 : 2; /* toggle between 0 and 2 */ + #endif + + result = HANDLED; + break; + + #ifdef HAVE_LIBHWLOC + + case KEY_F(1): + hwloc_bitmap_copy(this->workCpuset, this->allCpuset); + result = HANDLED; + break; + + case KEY_F(2): + this->topoView = !this->topoView; + keepSelected = false; + + result = HANDLED; + break; + + case KEY_F(3): + case '-': + case '+': + if (selected->sub_tree) + selected->sub_tree = 1 + !(selected->sub_tree - 1); /* toggle between 1 and 2 */ + + result = HANDLED; + break; + + #endif + + case 0x0a: + case 0x0d: + case KEY_ENTER: + result = BREAK_LOOP; + break; + } + + if (HANDLED == result) + AffinityPanel_update(this, keepSelected); + + return result; +} + +#ifdef HAVE_LIBHWLOC + +static MaskItem* AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem* parent) { + const char* type_name = hwloc_obj_type_string(obj->type); + const char* index_prefix = "#"; + unsigned depth = obj->depth; + unsigned index = obj->logical_index; + size_t off = 0, left = 10 * depth; + char buf[64], indent_buf[left + 1]; + + if (obj->type == HWLOC_OBJ_PU) { + index = Settings_cpuId(this->pl->settings, obj->os_index); + type_name = "CPU"; + index_prefix = ""; + } + + indent_buf[0] = '\0'; + if (depth > 0) { + for (unsigned i = 1; i < depth; i++) { + xSnprintf(&indent_buf[off], left, "%s ", (indent & (1U << i)) ? CRT_treeStr[TREE_STR_VERT] : " "); + size_t len = strlen(&indent_buf[off]); + off += len; + left -= len; + } + xSnprintf(&indent_buf[off], left, "%s", + obj->next_sibling ? CRT_treeStr[TREE_STR_RTEE] : CRT_treeStr[TREE_STR_BEND]); + // Uncomment when further appending to indent_buf + //size_t len = strlen(&indent_buf[off]); + //off += len; + //left -= len; + } + + xSnprintf(buf, sizeof(buf), "%s %s%u", type_name, index_prefix, index); + + MaskItem* item = MaskItem_newMask(buf, indent_buf, obj->complete_cpuset, false); + if (parent) + Vector_add(parent->children, item); + + if (item->sub_tree && parent && parent->sub_tree == 1) { + /* if obj is fully included or fully excluded, collapse the item */ + hwloc_bitmap_t result = hwloc_bitmap_alloc(); + hwloc_bitmap_and(result, obj->complete_cpuset, this->workCpuset); + int weight = hwloc_bitmap_weight(result); + hwloc_bitmap_free(result); + if (weight == 0 || weight == (hwloc_bitmap_weight(this->workCpuset) + hwloc_bitmap_weight(obj->complete_cpuset))) { + item->sub_tree = 2; + } + } + + /* "[x] " + "|- " * depth + ("- ")?(if root node) + name */ + unsigned width = 4 + 3 * depth + (2 * !depth) + strlen(buf); + if (width > this->width) { + this->width = width; + } + + return item; +} + +static MaskItem* AffinityPanel_buildTopology(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem* parent) { + MaskItem* item = AffinityPanel_addObject(this, obj, indent, parent); + if (obj->next_sibling) { + indent |= (1U << obj->depth); + } else { + indent &= ~(1U << obj->depth); + } + + for (unsigned i = 0; i < obj->arity; i++) { + AffinityPanel_buildTopology(this, obj->children[i], indent, item); + } + + return parent == NULL ? item : NULL; +} + +#endif + +const PanelClass AffinityPanel_class = { + .super = { + .extends = Class(Panel), + .delete = AffinityPanel_delete + }, + .eventHandler = AffinityPanel_eventHandler +}; + +static const char* const AffinityPanelFunctions[] = { + "Set ", + "Cancel ", + #ifdef HAVE_LIBHWLOC + "All", + "Topology", + " ", + #endif + NULL +}; +static const char* const AffinityPanelKeys[] = {"Enter", "Esc", "F1", "F2", "F3"}; +static const int AffinityPanelEvents[] = {13, 27, KEY_F(1), KEY_F(2), KEY_F(3)}; + +Panel* AffinityPanel_new(ProcessList* pl, const Affinity* affinity, int* width) { + AffinityPanel* this = AllocThis(AffinityPanel); + Panel* super = (Panel*) this; + Panel_init(super, 1, 1, 1, 1, Class(MaskItem), false, FunctionBar_new(AffinityPanelFunctions, AffinityPanelKeys, AffinityPanelEvents)); + + this->pl = pl; + /* defaults to 15, this also includes the gap between the panels, + * but this will be added by the caller */ + this->width = 14; + + this->cpuids = Vector_new(Class(MaskItem), true, DEFAULT_SIZE); + + #ifdef HAVE_LIBHWLOC + this->topoView = pl->settings->topologyAffinity; + #else + this->topoView = false; + #endif + + #ifdef HAVE_LIBHWLOC + this->allCpuset = hwloc_topology_get_complete_cpuset(pl->topology); + this->workCpuset = hwloc_bitmap_alloc(); + #endif + + Panel_setHeader(super, "Use CPUs:"); + + unsigned int curCpu = 0; + for (unsigned int i = 0; i < pl->cpuCount; i++) { + char number[16]; + xSnprintf(number, 9, "CPU %d", Settings_cpuId(pl->settings, i)); + unsigned cpu_width = 4 + strlen(number); + if (cpu_width > this->width) { + this->width = cpu_width; + } + + bool isSet = false; + if (curCpu < affinity->used && affinity->cpus[curCpu] == i) { + #ifdef HAVE_LIBHWLOC + hwloc_bitmap_set(this->workCpuset, i); + #endif + isSet = true; + curCpu++; + } + + MaskItem* cpuItem = MaskItem_newSingleton(number, i, isSet); + Vector_add(this->cpuids, (Object*) cpuItem); + } + + #ifdef HAVE_LIBHWLOC + this->topoRoot = AffinityPanel_buildTopology(this, hwloc_get_root_obj(pl->topology), 0, NULL); + #endif + + if (width) { + *width = this->width; + } + + AffinityPanel_update(this, false); + + return super; +} + +Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl) { + const AffinityPanel* this = (AffinityPanel*) super; + Affinity* affinity = Affinity_new(pl); + + #ifdef HAVE_LIBHWLOC + unsigned int i; + hwloc_bitmap_foreach_begin(i, this->workCpuset) + Affinity_add(affinity, i); + hwloc_bitmap_foreach_end(); + #else + for (unsigned int i = 0; i < this->pl->cpuCount; i++) { + const MaskItem* item = (const MaskItem*)Vector_get(this->cpuids, i); + if (item->value) { + Affinity_add(affinity, item->cpu); + } + } + #endif + + return affinity; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AffinityPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/AffinityPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AffinityPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AffinityPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,21 @@ +#ifndef HEADER_AffinityPanel +#define HEADER_AffinityPanel +/* +htop - AffinityPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Affinity.h" +#include "Panel.h" +#include "ProcessList.h" + + +extern const PanelClass AffinityPanel_class; + +Panel* AffinityPanel_new(ProcessList* pl, const Affinity* affinity, int* width); + +Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AUTHORS pcp-5.3.2/vendor/github.com/htop-dev/htop/AUTHORS --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AUTHORS 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AUTHORS 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,11 @@ +Originally authored by: + Hisham H. Muhammad + +Currently maintained by the htop dev team: + Benny Baumann + Christian Göttsche + Daniel Lange + Nathan Scott + +For the full list of contributors see: + git log --format="%aN" | sort -u diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/autogen.sh pcp-5.3.2/vendor/github.com/htop-dev/htop/autogen.sh --- pcp-5.3.1/vendor/github.com/htop-dev/htop/autogen.sh 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/autogen.sh 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf --force --install --verbose -Wall diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,88 @@ +/* +htop - AvailableColumnsPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "AvailableColumnsPanel.h" + +#include +#include +#include + +#include "ColumnsPanel.h" +#include "FunctionBar.h" +#include "ListItem.h" +#include "Object.h" +#include "Process.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static const char* const AvailableColumnsFunctions[] = {" ", " ", " ", " ", "Add ", " ", " ", " ", " ", "Done ", NULL}; + +static void AvailableColumnsPanel_delete(Object* object) { + Panel* super = (Panel*) object; + AvailableColumnsPanel* this = (AvailableColumnsPanel*) object; + Panel_done(super); + free(this); +} + +static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) { + AvailableColumnsPanel* this = (AvailableColumnsPanel*) super; + HandlerResult result = IGNORED; + + switch(ch) { + case 13: + case KEY_ENTER: + case KEY_F(5): + { + const ListItem* selected = (ListItem*) Panel_getSelected(super); + if (!selected) + break; + + int key = selected->key; + int at = Panel_getSelectedIndex(this->columns); + Panel_insert(this->columns, at, (Object*) ListItem_new(Process_fields[key].name, key)); + Panel_setSelected(this->columns, at+1); + ColumnsPanel_update(this->columns); + result = HANDLED; + break; + } + default: + { + if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) + result = Panel_selectByTyping(super, ch); + break; + } + } + return result; +} + +const PanelClass AvailableColumnsPanel_class = { + .super = { + .extends = Class(Panel), + .delete = AvailableColumnsPanel_delete + }, + .eventHandler = AvailableColumnsPanel_eventHandler +}; + +AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns) { + AvailableColumnsPanel* this = AllocThis(AvailableColumnsPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(AvailableColumnsFunctions, NULL, NULL); + Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); + + Panel_setHeader(super, "Available Columns"); + + for (int i = 1; i < LAST_PROCESSFIELD; i++) { + if (i != COMM && Process_fields[i].description) { + char description[256]; + xSnprintf(description, sizeof(description), "%s - %s", Process_fields[i].name, Process_fields[i].description); + Panel_add(super, (Object*) ListItem_new(description, i)); + } + } + this->columns = columns; + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableColumnsPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,22 @@ +#ifndef HEADER_AvailableColumnsPanel +#define HEADER_AvailableColumnsPanel +/* +htop - AvailableColumnsPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" + + +typedef struct AvailableColumnsPanel_ { + Panel super; + Panel* columns; +} AvailableColumnsPanel; + +extern const PanelClass AvailableColumnsPanel_class; + +AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableMetersPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableMetersPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableMetersPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableMetersPanel.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,167 @@ +/* +htop - AvailableMetersPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "AvailableMetersPanel.h" + +#include +#include +#include + +#include "CPUMeter.h" +#include "DynamicMeter.h" +#include "FunctionBar.h" +#include "Header.h" +#include "ListItem.h" +#include "Meter.h" +#include "MetersPanel.h" +#include "Object.h" +#include "Platform.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static void AvailableMetersPanel_delete(Object* object) { + Panel* super = (Panel*) object; + AvailableMetersPanel* this = (AvailableMetersPanel*) object; + Panel_done(super); + free(this); +} + +static inline void AvailableMetersPanel_addMeter(Header* header, Panel* panel, const MeterClass* type, unsigned int param, int column) { + const Meter* meter = Header_addMeterByClass(header, type, param, column); + Panel_add(panel, (Object*) Meter_toListItem(meter, false)); + Panel_setSelected(panel, Panel_size(panel) - 1); + MetersPanel_setMoving((MetersPanel*)panel, true); +} + +static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) { + AvailableMetersPanel* this = (AvailableMetersPanel*) super; + Header* header = this->header; + + const ListItem* selected = (ListItem*) Panel_getSelected(super); + if (!selected) + return IGNORED; + + unsigned int param = selected->key & 0xffff; + int type = selected->key >> 16; + HandlerResult result = IGNORED; + bool update = false; + + switch(ch) { + case KEY_F(5): + case 'l': + case 'L': + { + AvailableMetersPanel_addMeter(header, this->leftPanel, Platform_meterTypes[type], param, 0); + result = HANDLED; + update = true; + break; + } + case 0x0a: + case 0x0d: + case KEY_ENTER: + case KEY_F(6): + case 'r': + case 'R': + { + AvailableMetersPanel_addMeter(header, this->rightPanel, Platform_meterTypes[type], param, 1); + result = (KEY_LEFT << 16) | SYNTH_KEY; + update = true; + break; + } + } + if (update) { + this->settings->changed = true; + Header_calculateHeight(header); + Header_updateData(header); + Header_draw(header); + ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); + } + return result; +} + +const PanelClass AvailableMetersPanel_class = { + .super = { + .extends = Class(Panel), + .delete = AvailableMetersPanel_delete + }, + .eventHandler = AvailableMetersPanel_eventHandler +}; + +// Handle (&CPUMeter_class) entries in the AvailableMetersPanel +static void AvailableMetersPanel_addCPUMeters(Panel* super, const MeterClass* type, const ProcessList* pl) { + if (pl->cpuCount > 1) { + Panel_add(super, (Object*) ListItem_new("CPU average", 0)); + for (unsigned int i = 1; i <= pl->cpuCount; i++) { + char buffer[50]; + xSnprintf(buffer, sizeof(buffer), "%s %d", type->uiName, Settings_cpuId(pl->settings, i - 1)); + Panel_add(super, (Object*) ListItem_new(buffer, i)); + } + } else { + Panel_add(super, (Object*) ListItem_new(type->uiName, 1)); + } +} + +typedef struct { + Panel* super; + unsigned int id; + unsigned int offset; +} DynamicIterator; + +static void AvailableMetersPanel_addDynamicMeter(ATTR_UNUSED ht_key_t key, void* value, void* data) { + const DynamicMeter* meter = (const DynamicMeter*)value; + DynamicIterator* iter = (DynamicIterator*)data; + unsigned int identifier = (iter->offset << 16) | iter->id; + const char* label = meter->description ? meter->description : meter->caption; + if (!label) + label = meter->name; /* last fallback to name, guaranteed set */ + Panel_add(iter->super, (Object*) ListItem_new(label, identifier)); + iter->id++; +} + +// Handle (&DynamicMeter_class) entries in the AvailableMetersPanel +static void AvailableMetersPanel_addDynamicMeters(Panel* super, const ProcessList* pl, unsigned int offset) { + DynamicIterator iter = { .super = super, .id = 1, .offset = offset }; + assert(pl->dynamicMeters != NULL); + Hashtable_foreach(pl->dynamicMeters, AvailableMetersPanel_addDynamicMeter, &iter); +} + +// Handle remaining Platform Meter entries in the AvailableMetersPanel +static void AvailableMetersPanel_addPlatformMeter(Panel* super, const MeterClass* type, unsigned int offset) { + const char* label = type->description ? type->description : type->uiName; + Panel_add(super, (Object*) ListItem_new(label, offset << 16)); +} + +AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl) { + AvailableMetersPanel* this = AllocThis(AvailableMetersPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_newEnterEsc("Add ", "Done "); + Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); + + this->settings = settings; + this->header = header; + this->leftPanel = leftMeters; + this->rightPanel = rightMeters; + this->scr = scr; + + Panel_setHeader(super, "Available meters"); + // Platform_meterTypes[0] should be always (&CPUMeter_class) which we will + // handle separately in the code below. Likewise, identifiers for Dynamic + // Meters are handled separately - similar to CPUs, this allows generation + // of multiple different Meters (also using 'param' to distinguish them). + for (unsigned int i = 1; Platform_meterTypes[i]; i++) { + const MeterClass* type = Platform_meterTypes[i]; + assert(type != &CPUMeter_class); + if (type == &DynamicMeter_class) + AvailableMetersPanel_addDynamicMeters(super, pl, i); + else + AvailableMetersPanel_addPlatformMeter(super, type, i); + } + AvailableMetersPanel_addCPUMeters(super, &CPUMeter_class, pl); + + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableMetersPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableMetersPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/AvailableMetersPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/AvailableMetersPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,31 @@ +#ifndef HEADER_AvailableMetersPanel +#define HEADER_AvailableMetersPanel +/* +htop - AvailableMetersPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Header.h" +#include "Panel.h" +#include "ProcessList.h" +#include "ScreenManager.h" +#include "Settings.h" + + +typedef struct AvailableMetersPanel_ { + Panel super; + ScreenManager* scr; + + Settings* settings; + Header* header; + Panel* leftPanel; + Panel* rightPanel; +} AvailableMetersPanel; + +extern const PanelClass AvailableMetersPanel_class; + +AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/BatteryMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/BatteryMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/BatteryMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/BatteryMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,68 @@ +/* +htop - BatteryMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. + +This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). +*/ + +#include "BatteryMeter.h" + +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "XUtils.h" + + +static const int BatteryMeter_attributes[] = { + BATTERY +}; + +static void BatteryMeter_updateValues(Meter* this) { + ACPresence isOnAC; + double percent; + + Platform_getBattery(&percent, &isOnAC); + + if (isnan(percent)) { + this->values[0] = NAN; + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A"); + return; + } + + this->values[0] = percent; + + const char* text; + switch (isOnAC) { + case AC_PRESENT: + text = this->mode == TEXT_METERMODE ? " (Running on A/C)" : "(A/C)"; + break; + case AC_ABSENT: + text = this->mode == TEXT_METERMODE ? " (Running on battery)" : "(bat)"; + break; + case AC_ERROR: + default: + text = ""; + break; + } + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%%s", percent, text); +} + +const MeterClass BatteryMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = BatteryMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 100.0, + .attributes = BatteryMeter_attributes, + .name = "Battery", + .uiName = "Battery", + .caption = "Battery: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/BatteryMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/BatteryMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/BatteryMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/BatteryMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,23 @@ +#ifndef HEADER_BatteryMeter +#define HEADER_BatteryMeter +/* +htop - BatteryMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. + +This meter written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). +*/ + +#include "Meter.h" + + +typedef enum ACPresence_ { + AC_ABSENT, + AC_PRESENT, + AC_ERROR +} ACPresence; + +extern const MeterClass BatteryMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CategoriesPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/CategoriesPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CategoriesPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CategoriesPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,143 @@ +/* +htop - CategoriesPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "CategoriesPanel.h" + +#include +#include +#include + +#include "AvailableColumnsPanel.h" +#include "AvailableMetersPanel.h" +#include "ColorsPanel.h" +#include "ColumnsPanel.h" +#include "DisplayOptionsPanel.h" +#include "FunctionBar.h" +#include "ListItem.h" +#include "MetersPanel.h" +#include "Object.h" +#include "ProvideCurses.h" +#include "Vector.h" + + +static const char* const CategoriesFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; + +static void CategoriesPanel_delete(Object* object) { + Panel* super = (Panel*) object; + CategoriesPanel* this = (CategoriesPanel*) object; + Panel_done(super); + free(this); +} + +void CategoriesPanel_makeMetersPage(CategoriesPanel* this) { + MetersPanel* leftMeters = MetersPanel_new(this->settings, "Left column", this->header->columns[0], this->scr); + MetersPanel* rightMeters = MetersPanel_new(this->settings, "Right column", this->header->columns[1], this->scr); + leftMeters->rightNeighbor = rightMeters; + rightMeters->leftNeighbor = leftMeters; + Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, this->header, (Panel*) leftMeters, (Panel*) rightMeters, this->scr, this->pl); + ScreenManager_add(this->scr, (Panel*) leftMeters, 20); + ScreenManager_add(this->scr, (Panel*) rightMeters, 20); + ScreenManager_add(this->scr, availableMeters, -1); +} + +static void CategoriesPanel_makeDisplayOptionsPage(CategoriesPanel* this) { + Panel* displayOptions = (Panel*) DisplayOptionsPanel_new(this->settings, this->scr); + ScreenManager_add(this->scr, displayOptions, -1); +} + +static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) { + Panel* colors = (Panel*) ColorsPanel_new(this->settings, this->scr); + ScreenManager_add(this->scr, colors, -1); +} + +static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) { + Panel* columns = (Panel*) ColumnsPanel_new(this->settings); + Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns); + ScreenManager_add(this->scr, columns, 20); + ScreenManager_add(this->scr, availableColumns, -1); +} + +static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) { + CategoriesPanel* this = (CategoriesPanel*) super; + + HandlerResult result = IGNORED; + + int selected = Panel_getSelectedIndex(super); + switch (ch) { + case EVENT_SET_SELECTED: + result = HANDLED; + break; + case KEY_UP: + case KEY_CTRL('P'): + case KEY_DOWN: + case KEY_CTRL('N'): + case KEY_NPAGE: + case KEY_PPAGE: + case KEY_HOME: + case KEY_END: { + int previous = selected; + Panel_onKey(super, ch); + selected = Panel_getSelectedIndex(super); + if (previous != selected) + result = HANDLED; + break; + } + default: + if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) + result = Panel_selectByTyping(super, ch); + if (result == BREAK_LOOP) + result = IGNORED; + break; + } + if (result == HANDLED) { + int size = ScreenManager_size(this->scr); + for (int i = 1; i < size; i++) + ScreenManager_remove(this->scr, 1); + + switch (selected) { + case 0: + CategoriesPanel_makeMetersPage(this); + break; + case 1: + CategoriesPanel_makeDisplayOptionsPage(this); + break; + case 2: + CategoriesPanel_makeColorsPage(this); + break; + case 3: + CategoriesPanel_makeColumnsPage(this); + break; + } + } + return result; +} + +const PanelClass CategoriesPanel_class = { + .super = { + .extends = Class(Panel), + .delete = CategoriesPanel_delete + }, + .eventHandler = CategoriesPanel_eventHandler +}; + +CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Header* header, ProcessList* pl) { + CategoriesPanel* this = AllocThis(CategoriesPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(CategoriesFunctions, NULL, NULL); + Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); + + this->scr = scr; + this->settings = settings; + this->header = header; + this->pl = pl; + Panel_setHeader(super, "Setup"); + Panel_add(super, (Object*) ListItem_new("Meters", 0)); + Panel_add(super, (Object*) ListItem_new("Display options", 0)); + Panel_add(super, (Object*) ListItem_new("Colors", 0)); + Panel_add(super, (Object*) ListItem_new("Columns", 0)); + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CategoriesPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/CategoriesPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CategoriesPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CategoriesPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef HEADER_CategoriesPanel +#define HEADER_CategoriesPanel +/* +htop - CategoriesPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Header.h" +#include "Panel.h" +#include "ProcessList.h" +#include "ScreenManager.h" +#include "Settings.h" + + +typedef struct CategoriesPanel_ { + Panel super; + ScreenManager* scr; + + Settings* settings; + Header* header; + ProcessList* pl; +} CategoriesPanel; + +void CategoriesPanel_makeMetersPage(CategoriesPanel* this); + +extern const PanelClass CategoriesPanel_class; + +CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Header* header, ProcessList* pl); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ChangeLog pcp-5.3.2/vendor/github.com/htop-dev/htop/ChangeLog --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ChangeLog 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ChangeLog 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,831 @@ +What's new in version 3.1.0 (not released yet) + +* Change available / used memory reporting on Linux to be based on + MemAvailable (Kernel 3.14+) (thanks to Chris Cheney and Tomas Wido) +* Improved default sort ordering + Note for users: This may lead to an inverted sort order on startup of + htop 3.0.6 compared to previous versions. This is due to what is stored + in your htoprc file. Solution: Press I (to invert sort order). + This changed setting will be saved by htop on exit as long as it can + write to your htoprc file. +* The compile-time option to cater specifically for running htop as + setuid has been removed. + +What's new in version 3.0.5 + +* BUGFIX / SECURITY: InfoScreen: fix uncontrolled format string +* BUGFIX: Improve white text in the Light Terminal colour scheme + (both of the above thanks to V) +* Enable the function bar on the main screen to be hidden (see Setup -> Display options) +* BUGFIX: Reduce layout issues esp. around printing wide characters (not complete yet) +* BUGFIX: Make the follow function exit cleanly after followed process died +* Solaris: make Process callbacks static +* Update help and man page for improved -t / -s options +* Drop usage of formatted error messages from +* Show arrow indicating order of sorted process column +* Lots of plumbing around the internal Hashtable, hardening and code cleanups +* LibSensors: add support for Ryzen CPUs + (thanks to Matej Dian) +* BUGFIX: Fix CPU percentage on M1 silicon Macs + (thanks to Luke Groeninger) +* LoadMeter: dynamically adjust color and total of bar +* Find libsensors.so.4 for Fedora and friends +* Add support to display CPU frequencies on Solarish platforms + (thanks to Dominik Hassler) +* Enable going back to previous search matches (Shift-F3) +* Added keybind 'N' for sorting by PID (drops 'n'/'N' as not used before much) + (thanks to Jake Mannens) + +What's new in version 3.0.4 + +* Separate tree and list sort orders +* Invert Process_compare so that superclass matches run first + (thanks to Hisham Muhammad) +* Unhardcode Mac OS tick-to-milliseconds conversion + (thanks to Alexander Momchilov) +* Check if clock_gettime needs linking of librt +* Define O_PATH if not already defined + (thanks to Chris Burr) +* Add column on Mac for processes running under translation + (thanks to Dániel Bakai) +* Configure check for additional linker flags for keypad(3) +* PSI Meter: constant width and only print ten-duration as bar +* Sort in paused mode after inverting sort order +* Handle absence of package CPU temperature +* Meter: restore non-wide-character build +* LibSensors: restore temperature for Raspberry Pi +* MainPanel: do not reset hideProcessSelection on KEY_SHUFFLE +* BarMeter: rework text padding +* Panel: rework drawing of FunctionBar +* Meter: fix artifacts with very tiny width +* DragonFlyBSD updates +* BUGFIX: Fix dlopen issue for libsensors5 for some platforms +* BUGFIX: Fix broken tree display on inverted sort order +* BUGFIX: Fix pause mode ("Z") in tree view +* BUGFIX: Correct timebase for non-x86 CPUs on Darwin +* BUGFIX: Avoid NULL dereference on zombie processes +* Document dynamic bindings and assumed external configuration +* Update key mapping documentation for sorting + +What's new in version 3.0.3 + +* Process sorting in 'tree' mode + (thanks to Maxim Zhiburt) +* Improved command display/sort functionality + (thanks to Narendran Gopalakrishnan) +* Add screen for active file locks + (thanks to Fynn J. Wulf) +* Calculate library size (M_LRS column) from maps file + (thanks to Fynn J. Wulf) +* Add a Zram meter + (thanks to Murloc Knight) +* Add Linux cwd process column +* Dynamically load libsensors at runtime +* Improve PressureStall Meter display strings +* Hide process selection on ESC +* Fully support non-ascii characters in Meter-Bar +* Add support to change numeric options in settings screen +* Rename virtual memory column from M_SIZE to M_VIRT +* Add process column for normalized CPU usage +* Show CPU temperature in CPU meter +* Drop hideThreads Setting +* Add a systemd meter +* Add a network IO meter +* Add a SELinux meter +* Compress size of default FunctionBar +* Updates to the OpenFiles screen +* Continue updating header data in paused mode +* BUGFIX: Handle data wraparounds in IO meters +* BUGFIX: Update InfoScreen content on resize +* Add security attribute process column +* Add DiskIOMeter for IO read/write usage +* Read CPU frequency from sysfs by default +* Add Linux process column for context switches +* Several FreeBSD and Mac OS X platform updates + (thanks to Christian Göttsche) +* Add process environment for FreeBSD + (thanks to Ross Williams) +* Parse POWER_SUPPLY_CAPACITY for Linux Battery meter + (thanks to Jan Palus) +* Add octuple-column CPU meters. +* BUGFIX: On Linux consider ZFS ARC to be cache + (thanks to @multi) +* BUGFIX: Limit screen title length to window width +* Show selected command wrapped in a separate window + (thanks to @ryenus) +* Allow to pass '/' for item search +* Document implicit incremental search +* Handle 'q' as quit if first character +* Avoid expensive build of process tree when not using it +* Include documentation for COMM and EXE +* Distinguish display of no permissions for reading M_LRS +* Only calculate M_LRS size every 2 seconds +* Improvements to comm / cmdline display functionality +* Merged view for COMM, EXE and cmdline + (thanks to Narendran Gopalakrishnan and Benny Baumann) +* Consistent kernel thread display for COMM/EXE columns +* Central fault handling for all platforms +* Handle parsing envID & VPid from process status file +* Use threshold for display of guest/steal/irq meters +* Enhance highlighting of semi-large and large numbers +* Documentation on the repository style guide + (thanks to Benny Baumann) +* Align processor identifier to the right + (thanks to Christian Hesse) +* Document M_PSS, M_PSSWP, M_SWAP in man page +* Add Date and DateTime meters + (thanks to Michael F. Schönitzer) +* BUGFIX: Fix Solaris 11.4 due to missing ZFS ARC kstats + (thanks to @senjan) +* Code hardening, speedups, fd and memory leak fixes + (thanks to Christian Göttsche and Benny Baumann) +* Number CPUs from zero by default + (thanks to Zev Weiss) +* Remove residual python checks during the build process + (thanks to Stephen Gregoratto) + +What's new in version 3.0.2 + +* BUGFIX: Drop 'vim_mode' - several issues, needs rethink +* BUGFIX: fix regression in -u optional-argument handling +* Build system rework to remove python, header generation + (thanks to Zev Weiss and Hugo Musso Gualandi) +* BUGFIX: report nice level correctly on Solaris + (thanks to Dominik Hassler) +* CI, code quality improvements + (thanks to Tobias Kortkamp, Christian Hesse, Benny Baumann) + +What's new in version 3.0.1 + +* Coverity fixes, CI improvements, documentation updates +* BUGFIX: Fix early exit with longer sysfs battery paths +* BUGFIX: Improve OOM output, fix sorting + (thanks to Christian Göttsche) +* Rework check buttons and tree open/closed + (thanks to Bert Wesarg) +* Add -U/--no-unicode option to disable unicode + (thanks to Christian Hesse) +* Improvements to the affinity panel + (thanks to Bert Wesarg) + +What's new in version 3.0.0 + +* New maintainers - after a prolonged period of inactivity + from Hisham, the creator and original maintainer, a team + of community maintainers have volunteered to take over a + fork at https://htop.dev and https://github.com/htop-dev + to keep the project going. +* Support ZFS ARC statistics + (thanks to Ross Williams) +* Support more than 2 smaller CPU meter columns + (thanks to Christoph Budziszewski) +* Support Linux proportional set size metrics + (thanks to @linvinus, @ntninja and @himikof) +* Support Linux pressure stall information metrics + (thanks to Ran Benita) +* New display option to show CPU frequency in CPU meters + (thanks to Arnav Singh) +* Update Linux sysfs battery discovery for recent kernels + (thanks to @smattie) +* Add hardware topology information in the affinity panel + (thanks to Bert Wesarg) +* Add timestamp reporting to the strace screen + (thanks to Mario Harjac) +* Add simple, optional vim key mapping mode + (thanks to Daniel Flanagan) +* Added an option to disable the mouse + (thanks to MartinJM) +* Add Solaris11 compatibility + (thanks to Jan Senolt) +* Without an argument -u uses $USER value automatically + (thanks to @solanav) +* Support less(1) search navigation shortcuts + (thanks to @syrrim) +* Update the FreeBSD maximum PID to match FreeBSD change + (thanks to @multiplexd) +* Report values larger than 100 terabytes + (thanks to @adrien1018) +* Widen ST_UID (UID) column to allow for UIDs > 9999 + (thanks to DLange) +* BUGFIX: fix makefiles for building with clang + (thanks to Jorge Pereira) +* BUGFIX: fix major() usage + (thanks to @wataash and Kang-Che Sung) +* BUGFIX: fix the STARTTIME column on FreeBSD + (thanks to Rob Crowston) +* BUGFIX: truncate overwide jail names on FreeBSD + (thanks to Rob Crowston) +* BUGFIX: fix reported memory values on FreeBSD + (thanks to Tobias Kortkamp) +* BUGFIX: fix reported CPU meter values on OpenBSD + (thanks to @motet-a) +* BUGFIX: correctly identify other types of zombie process + (thanks to @joder) +* BUGFIX: improve follow-process handling in some situations + (thanks to @wangqr) +* BUGFIX: fix custom meters reverting to unexpected setting + (thanks to @wangqr) +* BUGFIX: close pipe after running lsof(1) + (thanks to Jesin) +* BUGFIX: meters honour setting of counting CPUs from 0/1 + (thanks to @rnsanchez) + +What's new in version 2.2.0 + +* Solaris/Illumos/OpenIndiana support + (thanks to Guy M. Broome) +* -t/--tree flag for starting in tree-view mode + (thanks to Daniel Flanagan) +* macOS: detects High Sierra version to avoid OS bug + (thanks to Pierre Malhaire) +* OpenBSD: read battery data + (thanks to @nerd972) +* Various automake and build improvements + (thanks to Kang-Che Sung) +* Check for pkg-config when building with --enable-delayacct + (thanks to @florian2833z for the report) +* Avoid some bashisms in configure script + (thanks to Jesin) +* Use CFLAGS from ncurses*-config if present + (thanks to Michael Klein) +* Header generator supports non-UTF-8 environments + (thanks to @volkov-am) +* Linux: changed detection of kernel threads +* Collapse current subtree pressing Backspace +* BUGFIX: fix behavior of SYSCR column + (thanks to Marc Kleine-Budde) +* BUGFIX: obtain exit code of lsof correctly + (thanks to @wangqr) +* BUGFIX: fix crash with particular keycodes + (thanks to Wellington Torrejais da Silva for the report) +* BUGFIX: fix issue with small terminals + (thanks to Daniel Elf for the report) +* BUGFIX: fix terminal color issues + (thanks to Kang-Che Sung for the report) +* BUGFIX: preserve LDFLAGS when building + (thanks to Lance Frederickson for the report) +* BUGFIX: fixed overflow for systems with >= 100 signals + +What's new in version 2.1.0 + +* Linux: Delay accounting metrics + (thanks to André Carvalho) +* DragonFlyBSD support + (thanks to Diederik de Groot) +* Support for real-time signals + (thanks to Kang-Che Sung) +* 'c' key now works with threads as well +* Session column renamed from SESN to SID + (thanks to Kamyar Rasta) +* Improved UI for meter style selection + (thanks to Kang-Che Sung) +* Improved code for constructing process tree + (thanks to wangqr) +* Compile-time option to disable setuid +* Error checking of various standard library operations +* Replacement of sprintf with snprintf + (thanks to Tomasz Kramkowski) +* Linux: performance improvements in battery meter +* Linux: update process TTY device +* Linux: add support for sorting TASK_IDLE + (thanks to Vladimir Panteleev) +* Linux: add upper-bound to running process counter + (thanks to Lucas Correia Villa Real) +* BUGFIX: avoid crash when battery is removed + (thanks to Jan Chren) +* BUGFIX: macOS: fix infinite loop in tree view + (thanks to Wataru Ashihara) + +What's new in version 2.0.2 + +* Mac OS X: stop trying when task_for_pid fails for a process, + stops spamming logs with errors. +* Add Ctrl+A and Ctrl+E to go to beginning and end of line +* FreeBSD: fixes for CPU calculation + (thanks to Tim Creech, Andy Pilate) +* Usability: auto-follow process after a search. +* Use Linux backend on GNU Hurd +* Improvement for reproducible builds. +* BUGFIX: Fix behavior of Alt-key combinations + (thanks to Kang-Che Sung) +* Various code tweaks and cleanups + (thanks to Kang-Che Sung) + +What's new in version 2.0.1 + +* OpenBSD: Various fixes and improvements + (thanks to Michael McConville and Juan Francisco Cantero Hurtado) +* FreeBSD: fix CPU and memory readings + (thanks to Tim Creech, Hung-Yi Chen, Bernard Spil, Greg V) +* FreeBSD: add battery support + (thanks to Greg V) +* Linux: Retain last-obtained name of a zombie process +* Mac OS X: Improve portability for OS X versions + (thanks to Michael Klein) +* Mac OS X: Fix reading command-line arguments and basename +* Mac OS X: Fix process state information +* Mac OS X: Fix tree view collapsing/expanding +* Mac OS X: Fix tree organization +* Mac OS X: Fix memory accounting +* Fix crash when emptying a column of meters +* Make Esc key more responsive + +What's new in version 2.0.0 + +* Platform abstraction layer +* Initial FreeBSD support +* Initial Mac OS X support + (thanks to David Hunt) +* Swap meter for Mac OSX + (thanks to Ștefan Rusu) +* OpenBSD port + (thanks to Michael McConville) +* FreeBSD support improvements + (thanks to Martin Misuth) +* Support for NCurses 6 ABI, including mouse wheel support +* Much improved mouse responsiveness +* Process environment variables screen + (thanks to Michael Klein) +* Higher-resolution UTF-8 based Graph mode + (Thanks to James Hall from vtop for the idea!) +* Show program path settings + (thanks to Tobias Geerinckx-Rice) +* BUGFIX: Fix crash when scrolling an empty filtered list. +* Use dynamic units for text display, and several fixes + (thanks to Christian Hesse) +* BUGFIX: fix error caused by overflow in usertime calculation. + (thanks to Patrick Marlier) +* Catch all memory allocation errors + (thanks to Michael McConville for the push) +* Several tweaks and bugfixes + (See the Git log for details and contributors!) + +What's new in version 1.0.3 + +* Tag all children ('c' key) +* Fixes in accounting of guest time when using virtualization + (thanks to Patrick Marlier) +* Performance improvements + (thanks to Jann Horn) +* Further performance improvements due to conditional parsing + of IO data depending on selected fields. +* Better consistency in coloring. +* Increase limit of buffer when tracing a deep nested process tree. +* Display pagefault stats. +* BUGFIX: Fix crash when adding meters and toggling detailed CPU time. + (thanks to Dawid Gajownik) +* Add column to track the OOM-killer score of processes + (thanks to Leigh Simpson) + +What's new in version 1.0.2 + +* Add IO priority support ('i' key) +* Avoid deleting .htoprc if it is a symlink +* Fail gracefully when /proc is not mounted + (thanks to Philipp Hagemeister) +* Option to update process names on every refresh + (thanks to Rob Hoelz) +* BUGFIX: Fix crashes when process list is empty + +What's new in version 1.0.1 + +* Move .htoprc to XDG-compliant path ~/.config/htop/htoprc, + respecting $XDG_CONFIG_HOME + (thanks to Hadzhimurad Ustarkhan for the suggestion.) +* Safer behavior on the kill screen, to make it harder to kill the wrong process. +* Fix for building in FreeBSD 8.2 + (thanks to Trond Endrestol) +* BUGFIX: behavior of 'F' (follow) key was broken, also affecting the + persistence of mouse selections. +* BUGFIX: keep main panel up-to-date when running the screen manager, + to fix crash when processes die while on the F9/Kill screen. + +What's new in version 1.0 + +* Performance improvements +* Support for splitting CPU meters into two or four columns + (thanks to Wim Heirman) +* Switch from PLPA, which is now deprecated, to HWLOC. +* Bring back support for native Linux sched_setaffinity, + so we don't have to use HWLOC where we don't need to. +* Support for typing in user names and column fields in selection panels. +* Support for UTF-8 tree drawing + (thanks to Bin Guo) +* Option for counting CPUs from zero + (thanks to Sean Noonan) +* Meters update in every screen (no longer halting while on Setup, etc.) +* Stricter checks for command-line options + (thanks to Sebastian Pipping) +* Incremental filtering + (thanks to Seth Heeren for the idea and initial implementation) +* Try harder to find the ncurses header + (thanks to Moritz Barsnick) +* Man page updates + (thanks to Vincent Launchbury) +* BUGFIX: Support larger numbers for process times. + (thanks to Tristan Nakagawa for the report.) +* BUGFIX: Segfault in BarMeterMode_draw() for small terminal widths + (patch by Sebastian Pipping) + +What's new in version 0.9 + +* Add support for "steal"/guest CPU time measurement + in virtualization environments +* Expand and collapse subtrees using '+' and '-' when in tree-view +* Support for cgroups + (thanks to Guillaume Zitta and Daniel Lezcano) +* Show custom thread names + (thanks to Anders Torger) +* Add support for STARTTIME field +* Upgrade PLPA to version 1.3.2 +* Fix license terms with regard to PLPA + (thanks to Tom Callaway) +* getopt-based long options and --no-color + (thanks to Vincent Launchbury) +* BUGFIX: Fix display of nan% in CPU meters + (thanks to Steven Hampson) +* BUGFIX: Fix memory leak + (thanks to Pavol Rusnak) +* Add Bash/emacs style navigation keys + (thanks to Daniel Schuler) +* Improve battery meter support + (thanks to Richard W.) +* BUGFIX: Fix IO-wait color in "Black on White" scheme +* BUGFIX: Fix search by process name when list is filtered by user. + (thanks to Sergej Pupykin for the report.) +* BUGFIX: Fix alignment for display of memory values above 100G (sign of the times!) + (thanks to Jan van Haarst for the report.) + +What's new in version 0.8.3 + +* BUGFIX: Fix crash on F6 key + (thanks to Rainer Suhm) +* BUGFIX: Fix a minor bug which affected the build process. + +What's new in version 0.8.2 + +* Integrated lsof (press 'l') +* Fix display of gigabyte-sized values + (thanks to Andika Triwidada) +* Option to display hostname in the meters area +* Rename VEID to CTID in OpenVZ systems + (thanks to Thorsten Schifferdecker) +* Corrections to the desktop entry file + (thanks by Samuli Suominen) +* BUGFIX: Correct page size calculation for FreeBSD systems + (thanks to Andrew Paulsen) +* Allow compilation without PLPA on systems that don't support it + (thanks to Timothy Redaelli) +* BUGFIX: Fix missing tree view when userland threads are hidden + (thanks to Josh Stone) +* BUGFIX: Fix for VPID on OpenVZ systems + (thanks to Wolfgang Frisch) + +What's new in version 0.8.1 + +* Linux-VServer support + (thanks to Jonathan Sambrook and Benedikt Bohm) +* Battery meter + (thanks to Ian Page Hands) +* BUGFIX: Fix collection of IO stats in multithreaded processes + (thanks to Gerhard Heift) +* Remove assertion that fails on hardened kernels + (thanks to Wolfram Schlich for the report) + +What's new in version 0.8 + +* Ability to change sort column with the mouse by + clicking column titles (click again to invert order) +* Add support for Linux per-process IO statistics, + enabled with the --enable-taskstats flag, which + requires a kernel compiled with taskstats support. + (thanks to Tobias Oetiker) +* Add Unicode support, enabled with the --enable-unicode + flag, which requires libncursesw. + (thanks to Sergej Pupykin) +* BUGFIX: Fix display of CPU count for threaded processes. + When user threads are hidden, process now shows the + sum of processor usage for all processors. When user + threads are displayed, each thread shows its own + processor usage, including the root thread. + (thanks to Bert Wesarg for the report) +* BUGFIX: avoid crashing when using many meters + (thanks to David Cho for the report) + +What's new in version 0.7 + +* CPU affinity configuration ('a' key) +* Improve display of tree view, properly nesting + threads of the same app based on TGID. +* IO-wait time now counts as idle time, which is a more + accurate description. It is still available in + split time, now called detailed CPU time. + (thanks to Samuel Thibault for the report) +* BUGFIX: Correct display of TPGID field +* Add TGID field +* BUGFIX: Don't crash with invalid command-line flags + (thanks to Nico Golde for the report) +* Fix GCC 4.3 compilation issues + (thanks to Martin Michlmayr for the report) +* OpenVZ support, enabled at compile-time with + the --enable-openvz flag. + (thanks to Sergey Lychko) + +What's new in version 0.6.6 + +* Add support of NLWP field + (thanks to Bert Wesarg) +* BUGFIX: Fix use of configurable /proc location + (thanks to Florent Thoumie) +* Fix memory percentage calculation and make it saner + (thanks to Olev Kartau for the report) +* Added display of DRS, DT, LRS and TRS + (thanks to Matthias Lederhofer) +* BUGFIX: LRS and DRS memory values were flipped + (thanks to Matthias Lederhofer) +* BUGFIX: Don't crash on very high UIDs + (thanks to Egmont Koblinger) + +What's new in version 0.6.5 + +* Add hardened-debug flags for debugging with Hardened GCC +* BUGFIX: Handle error condition when a directory vanishes + from /proc +* BUGFIX: Fix leak of process command line +* BUGFIX: Collect orphaned items when arranging the tree view. + (thanks to Wolfram Schlich for assistance with debugging) +* Separate proc and memory debugging into separate #defines. +* BUGFIX: Fix message when configure fails due to + missing libraries + (thanks to Jon) +* BUGFIX: Don't truncate value when displaying a very large + process + (thanks to Bo Liu) + +What's new in version 0.6.4 + +* Add an option to split the display of kernel time + in the CPU meter into system, IO-wait, IRQ and soft-IRQ. + (thanks to Philipp Richter) +* --sort-key flag in the command-line, overriding the + saved setting in .htoprc for the session. + (thanks to Rodolfo Borges) +* BUGFIX: Fixed string overflow on uptime display. + (thanks to Marc Cahalan) + +What's new in version 0.6.3 + +* Performance improvements: uses much less CPU than the + previous release with the default setup. +* Use 64-bit values when storing processor times to + avoid overflow. +* Memory consumption improvements, compensating storage + of 64-bit values. +* Internal change: rename TypedVector to Vector and + ListBox (and related classes) to Panel. +* Have configure actually fail when needed libraries or + headers are not found. +* Horizontally scroll in larger increments when on the + Linux console because of slow update of unaccelerated fb +* No longer untag processes after sending a signal + (useful for when SIGTERM fails and one wants to try again + with SIGKILL). All processes can be untagged at once with 'U'. + (thanks to A. Costa for the suggestion) + +What's new in version 0.6.2 + +* BUGFIX: Fixed crash when using some .htoprc files from 0.6 + (thanks to Wolfram Schlich and John Thomas for the reports) +* BUGFIX: Ensure changes to color scheme are saved +* BUGFIX: Make configure behave correctly with --with-proc +* Minor addition to .desktop file. + +What's new in version 0.6.1 + +* New meter type: "All CPUs", which dynamically adjusts + to the number of CPUs present in the machine. Note that + because of this, older versions of htop may crash when + using an .htoprc file modified my the newer version. +* Accept --with-proc= in configure, to specify + alternative procfs locations (making htop friendlier + to the Linux compatibility layer in FreeBSD) +* Included icon .desktop and desktop entry + (thanks to Peter Hyman) +* Added a check to make sure that a root-user htop closes + when its parent non-root terminal is closed. + (thanks to Ilya Evseev for the report) +* BUGFIX: does not crash anymore when $HOME is not set + (thanks to Henning Schild for the report) +* Wait for strace child process to die properly. + (thanks to Marcus Fritzsch) +* Support $HTOPRC + (thanks to Luis Limon) + +What's new in version 0.6 + +* Configuration of columns merged into the Setup screen +* Integrated strace (press 's') + (thanks to Marinho Barcellos for the help) +* BUGFIX: some fixes, aided by Valgrind + (thanks to Wolfram Schlich for the report) +* BUGFIX: fixed bug when switching meter modes + (thanks to Eduardo Righes for the report) +* Show processes of a single user +* "SortBy" function now menu-based +* Improved mouse handling +* ...and on top of that reduced memory consumption! + +What's new in version 0.5.4 + +* Color schemes +* -d flag, to configure delay between updates. + Note that the delay value is saved in ~/.htoprc. +* BUGFIX: Update of meters was halting after help screen. + (thanks to Matt Moore) +* BUGFIX: No longer display incorrect information + in first frame. +* BUGFIX: Fix auto-detection of /proc/stat, + correcting CPU usage information on multiprocessor + systems. + +What's new in version 0.5.3 + +* Read new field "steal" on newer /proc/stat files +* Auto-detects format of /proc/stat, to cope + with patched 2.4 kernels which display 2.6-style + information (most notably those on RHEL 3) + (thanks to Fernando Dotta for the report) +* Support $HOME_ETC initiative + (see http://www.pld-linux.org/Docs/home-etc) + (thanks to Roman Barczynski for the tip) +* The configure script now tests for /proc, so + that it fails early on unsupported platforms + instead of during compilation/execution. +* Made presentation of the function keys in the + status bar consistent across views + (thanks to David Mathog for the report) +* Minor changes to make the codebase more friendly + to possible future ports + (thanks to Jari Aalto and David Mathog for the reports) + +What's new in version 0.5.2 + +* BUGFIX: Correct display of user field + (thanks to Marcin Miroslaw for the report) +* Keyboard support improvements + (thanks to Aury Fink Filho for the report) + +What's new in version 0.5.1 + +* BUGFIX: Correctly displays NPTL threads from + /proc//task subdirectories + (thanks to Mike Pot for the report) +* BUGFIX: Fixes key handling on Signals listbox + (thanks to Ondrej Vlach) +* Renicing no longer displays temporary illegal values + (thanks to Ondrej Vlach) +* 'Hide userland threads' feature for NPTL threads + +What's new in version 0.5 + +* Tree view +* New column, TIME (user + system time, + like in top, 'T' switches to "sort by time") +* Major reorganization of the underlying code of the + setup screen, to manage setup pages +* New setup page: Display options +* Hide kernel threads ('K' key) +* Colorized memory numbers +* Vastly improved support for monochromatic terminals +* Shadow processes that do not belong to user ('U' key) +* Header margin configuration accessible via setup screen +* Visual feedback on failing incremental search +* BUGFIX: fixed keyboard input issues on 64-bit machines +* BUGFIX: hopefully fixed the incorrect values + that show on status bars in some systems +* BUGFIX: doesn't mess with fields list anymore when + canceling after changing the number of items +* Uptime meter no longer says "1 days" ;) + +What's new in version 0.4.1 + +* BUGFIX: compiles on 64-bit architectures again + (thanks to Bartosz Fenski for the report) +* BUGFIX: multi-processor support fixed on kernels 2.6 + (thanks to Wolfram Schlich for the report) + +What's new in version 0.4 + +* Support for multiple processors! +* Basic mouse support +* Modular header based on configurable meters; + supports 4 view modes: bar, text, LED, graph +* Uptime, load average meters + (thanks to Marc Calahan) +* Meters setup screen; should eventually evolve into a + general setup screen, with column setup, keybindings, etc. +* Thread hiding toggleable + (press 'T' to hide the nonstandard dotfiles in /proc) +* BUGFIX: Do not flicker screen on column configuration screen +* Clock and load average meters + (thanks to Marc Calahan) +* BUGFIX: numeric swap indicator was printing bogus value +* BUGFIX: internal fixes on Panel widget +* Clear the bottom line when exiting +* Press "F3" during search to walk through the results +* Improved navigation on column configuration screen +* BUGFIX: fix segfault on kernels with restricted /proc + enabled +* BUGFIX: a few last-minute bugfixes in the setup UI + (thanks to Gaspare Bruno for the reports) + + +What's new in version 0.3.3 + +* Saves column and sorting configuration in ~/.htoprc +* Displays "hidden" threads on RedHat 9 + (Thanks to Leonardo Godinho) +* BUGFIX: supports process names with spaces + (Thanks to Marc Calahan) +* BUGFIX: ...and parentheses :) +* BUGFIX: long process names overflowed RichString + (Thanks to Marc Calahan) + +What's new in version 0.3.2 + +* Performance and memory usage improvements, aided by gprof +* BUGFIX: quite a few fixes, aided by Valgrind +* Header preview on column configuration screen + (Thanks to Marc Calahan) + +What's new in version 0.3.1 + +* BUGFIX: crash fixes related to process list handling + (thanks to Marc Calahan) +* Man page + (thanks to Bartosz Fenski) +* Tag processes with the space bar +* Kill multiple process based on tag +* BUGFIX: corrected processing order of updates in list +* Screen refresh function on Ctrl-L +* Large numbers are shown in MB/GB notation in order to fit screen + (thanks to Marc Calahan) +* Realtime priority is correctly displayed + (thanks to Marc Calahan) +* Preliminary support for configurable columns, with 'C' + (thanks to Marc Calahan) + -- not all columns display properly yet + +What's new in version 0.3 + +* BUGFIX: no dirt left on screen on horizontal scrolling +* Signal selection on "kill" command +* Color-coding for users, nice and process status +* "Follow" function +* Fully selectable sort order +* Function bar on last line +* Build system now uses autotools + +What's new in version 0.2.1 + +* Sorting by process or memory usage ('P' and 'M', like top) +* Quicker default update (1.5 second, not yet configurable) +* Now the order of the elements in the process list stay + 'locked' for a while after you move the cursor to ease + selecting a process +* Corrected the installation instructions in README + (Thanks to Jeremy Eglen) +* Should now compile cleanly on Conectiva 9 and similar systems + (Thanks to Adriano Frare for the report) +* Friendlier Makefile +* Help screen ('h') + +What's new in version 0.2 + +* Memory indicators in header now show used and total, in MB +* Preliminary support for sorting (CPU% only) +* Memory percentage field (resident memory / used memory) +* BUGFIX: identified source of spurious crashes +* Can search names containing numbers + (Thanks to Rafael Jeffman) +* Correctly calculates memory page size + (Thanks to Rafael Jeffman) + +What's new in version 0.13 + +* Handles terminal resize +* Display all user names (not only those in /etc/passwd) + (Thanks to Julio Biason) + +What's new in version 0.12 + +* Support for 2.6 kernels +* Uses terminal default colors as a background + +What's new in version 0.11 + +* BUGFIX: does not crash when UID is not in /etc/passwd + +What's new in version 0.1 + +* Everything! diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ClockMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ClockMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ClockMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ClockMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,46 @@ +/* +htop - ClockMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "ClockMeter.h" + +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "ProcessList.h" + + +static const int ClockMeter_attributes[] = { + CLOCK +}; + +static void ClockMeter_updateValues(Meter* this) { + const ProcessList* pl = this->pl; + + struct tm result; + const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result); + this->values[0] = lt->tm_hour * 60 + lt->tm_min; + strftime(this->txtBuffer, sizeof(this->txtBuffer), "%H:%M:%S", lt); +} + +const MeterClass ClockMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = ClockMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 1440, /* 24*60 */ + .attributes = ClockMeter_attributes, + .name = "Clock", + .uiName = "Clock", + .caption = "Time: ", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ClockMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ClockMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ClockMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ClockMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_ClockMeter +#define HEADER_ClockMeter +/* +htop - ClockMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass ClockMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ColorsPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ColorsPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ColorsPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ColorsPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,104 @@ +/* +htop - ColorsPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "ColorsPanel.h" + +#include +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Object.h" +#include "OptionItem.h" +#include "ProvideCurses.h" + + +// TO ADD A NEW SCHEME: +// * Increment the size of bool check in ColorsPanel.h +// * Add the entry in the ColorSchemeNames array below in the file +// * Add a define in CRT.h that matches the order of the array +// * Add the colors in CRT_setColors + + +static const char* const ColorsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; + +static const char* const ColorSchemeNames[] = { + "Default", + "Monochromatic", + "Black on White", + "Light Terminal", + "MC", + "Black Night", + "Broken Gray", + NULL +}; + +static void ColorsPanel_delete(Object* object) { + Panel* super = (Panel*) object; + ColorsPanel* this = (ColorsPanel*) object; + Panel_done(super); + free(this); +} + +static HandlerResult ColorsPanel_eventHandler(Panel* super, int ch) { + ColorsPanel* this = (ColorsPanel*) super; + + HandlerResult result = IGNORED; + int mark = Panel_getSelectedIndex(super); + + switch(ch) { + case 0x0a: + case 0x0d: + case KEY_ENTER: + case KEY_MOUSE: + case KEY_RECLICK: + case ' ': + assert(mark >= 0); + assert(mark < LAST_COLORSCHEME); + for (int i = 0; ColorSchemeNames[i] != NULL; i++) + CheckItem_set((CheckItem*)Panel_get(super, i), false); + CheckItem_set((CheckItem*)Panel_get(super, mark), true); + + this->settings->colorScheme = mark; + this->settings->changed = true; + + CRT_setColors(mark); + clear(); + + result = HANDLED | REDRAW; + } + + return result; +} + +const PanelClass ColorsPanel_class = { + .super = { + .extends = Class(Panel), + .delete = ColorsPanel_delete + }, + .eventHandler = ColorsPanel_eventHandler +}; + +ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr) { + ColorsPanel* this = AllocThis(ColorsPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(ColorsFunctions, NULL, NULL); + Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true, fuBar); + + this->settings = settings; + this->scr = scr; + + assert(ARRAYSIZE(ColorSchemeNames) == LAST_COLORSCHEME + 1); + + Panel_setHeader(super, "Colors"); + for (int i = 0; ColorSchemeNames[i] != NULL; i++) { + Panel_add(super, (Object*) CheckItem_newByVal(ColorSchemeNames[i], false)); + } + CheckItem_set((CheckItem*)Panel_get(super, settings->colorScheme), true); + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ColorsPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ColorsPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ColorsPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ColorsPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,26 @@ +#ifndef HEADER_ColorsPanel +#define HEADER_ColorsPanel +/* +htop - ColorsPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" +#include "ScreenManager.h" +#include "Settings.h" + + +typedef struct ColorsPanel_ { + Panel super; + + Settings* settings; + ScreenManager* scr; +} ColorsPanel; + +extern const PanelClass ColorsPanel_class; + +ColorsPanel* ColorsPanel_new(Settings* settings, ScreenManager* scr); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ColumnsPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ColumnsPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ColumnsPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ColumnsPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,149 @@ +/* +htop - ColumnsPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "ColumnsPanel.h" + +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "ListItem.h" +#include "Object.h" +#include "Process.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static const char* const ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL}; + +static void ColumnsPanel_delete(Object* object) { + Panel* super = (Panel*) object; + ColumnsPanel* this = (ColumnsPanel*) object; + Panel_done(super); + free(this); +} + +static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) { + ColumnsPanel* const this = (ColumnsPanel*) super; + + int selected = Panel_getSelectedIndex(super); + HandlerResult result = IGNORED; + int size = Panel_size(super); + + switch(ch) { + case 0x0a: + case 0x0d: + case KEY_ENTER: + case KEY_MOUSE: + case KEY_RECLICK: + { + if (selected < size - 1) { + this->moving = !(this->moving); + Panel_setSelectionColor(super, this->moving ? PANEL_SELECTION_FOLLOW : PANEL_SELECTION_FOCUS); + ListItem* selectedItem = (ListItem*) Panel_getSelected(super); + if (selectedItem) + selectedItem->moving = this->moving; + result = HANDLED; + } + break; + } + case KEY_UP: + { + if (!this->moving) { + break; + } + } + /* else fallthrough */ + case KEY_F(7): + case '[': + case '-': + { + if (selected < size - 1) + Panel_moveSelectedUp(super); + result = HANDLED; + break; + } + case KEY_DOWN: + { + if (!this->moving) { + break; + } + } + /* else fallthrough */ + case KEY_F(8): + case ']': + case '+': + { + if (selected < size - 2) + Panel_moveSelectedDown(super); + result = HANDLED; + break; + } + case KEY_F(9): + case KEY_DC: + { + if (selected < size - 1) { + Panel_remove(super, selected); + } + result = HANDLED; + break; + } + default: + { + if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) + result = Panel_selectByTyping(super, ch); + if (result == BREAK_LOOP) + result = IGNORED; + break; + } + } + if (result == HANDLED) + ColumnsPanel_update(super); + return result; +} + +const PanelClass ColumnsPanel_class = { + .super = { + .extends = Class(Panel), + .delete = ColumnsPanel_delete + }, + .eventHandler = ColumnsPanel_eventHandler +}; + +ColumnsPanel* ColumnsPanel_new(Settings* settings) { + ColumnsPanel* this = AllocThis(ColumnsPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(ColumnsFunctions, NULL, NULL); + Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); + + this->settings = settings; + this->moving = false; + Panel_setHeader(super, "Active Columns"); + + const ProcessField* fields = this->settings->fields; + for (; *fields; fields++) { + if (Process_fields[*fields].name) { + Panel_add(super, (Object*) ListItem_new(Process_fields[*fields].name, *fields)); + } + } + return this; +} + +void ColumnsPanel_update(Panel* super) { + ColumnsPanel* this = (ColumnsPanel*) super; + int size = Panel_size(super); + this->settings->changed = true; + this->settings->fields = xRealloc(this->settings->fields, sizeof(ProcessField) * (size + 1)); + this->settings->flags = 0; + for (int i = 0; i < size; i++) { + int key = ((ListItem*) Panel_get(super, i))->key; + this->settings->fields[i] = key; + this->settings->flags |= Process_fields[key].flags; + } + this->settings->fields[size] = 0; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ColumnsPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ColumnsPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ColumnsPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ColumnsPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,29 @@ +#ifndef HEADER_ColumnsPanel +#define HEADER_ColumnsPanel +/* +htop - ColumnsPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Panel.h" +#include "Settings.h" + + +typedef struct ColumnsPanel_ { + Panel super; + + Settings* settings; + bool moving; +} ColumnsPanel; + +extern const PanelClass ColumnsPanel_class; + +ColumnsPanel* ColumnsPanel_new(Settings* settings); + +void ColumnsPanel_update(Panel* super); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandLine.c pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandLine.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandLine.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandLine.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,391 @@ +/* +htop - CommandLine.c +(C) 2004-2011 Hisham H. Muhammad +(C) 2020-2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "CommandLine.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Action.h" +#include "CRT.h" +#include "DynamicMeter.h" +#include "Hashtable.h" +#include "Header.h" +#include "IncSet.h" +#include "MainPanel.h" +#include "MetersPanel.h" +#include "Panel.h" +#include "Platform.h" +#include "Process.h" +#include "ProcessList.h" +#include "ProvideCurses.h" +#include "ScreenManager.h" +#include "Settings.h" +#include "UsersTable.h" +#include "XUtils.h" + + +static void printVersionFlag(const char* name) { + printf("%s " VERSION "\n", name); +} + +static void printHelpFlag(const char* name) { + printf("%s " VERSION "\n" + COPYRIGHT "\n" + "Released under the GNU GPLv2.\n\n" + "-C --no-color Use a monochrome color scheme\n" + "-d --delay=DELAY Set the delay between updates, in tenths of seconds\n" + "-F --filter=FILTER Show only the commands matching the given filter\n" + "-h --help Print this help screen\n" + "-H --highlight-changes[=DELAY] Highlight new and old processes\n" + "-M --no-mouse Disable the mouse\n" + "-p --pid=PID[,PID,PID...] Show only the given PIDs\n" + " --readonly Disable all system and process changing features\n" + "-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n" + "-t --tree Show the tree view (can be combined with -s)\n" + "-u --user[=USERNAME] Show only processes for a given user (or $USER)\n" + "-U --no-unicode Do not use unicode but plain ASCII\n" + "-V --version Print version info\n", name); + Platform_longOptionsUsage(name); + printf("\n" + "Long options may be passed with a single dash.\n\n" + "Press F1 inside %s for online help.\n" + "See 'man %s' for more information.\n", name, name); +} + +// ---------------------------------------- + +typedef struct CommandLineSettings_ { + Hashtable* pidMatchList; + char* commFilter; + uid_t userId; + int sortKey; + int delay; + bool useColors; + bool enableMouse; + bool treeView; + bool allowUnicode; + bool highlightChanges; + int highlightDelaySecs; + bool readonly; +} CommandLineSettings; + +static CommandLineSettings parseArguments(const char* program, int argc, char** argv) { + + CommandLineSettings flags = { + .pidMatchList = NULL, + .commFilter = NULL, + .userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2)) + .sortKey = 0, + .delay = -1, + .useColors = true, + .enableMouse = true, + .treeView = false, + .allowUnicode = true, + .highlightChanges = false, + .highlightDelaySecs = -1, + .readonly = false, + }; + + const struct option long_opts[] = + { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"delay", required_argument, 0, 'd'}, + {"sort-key", required_argument, 0, 's'}, + {"user", optional_argument, 0, 'u'}, + {"no-color", no_argument, 0, 'C'}, + {"no-colour", no_argument, 0, 'C'}, + {"no-mouse", no_argument, 0, 'M'}, + {"no-unicode", no_argument, 0, 'U'}, + {"tree", no_argument, 0, 't'}, + {"pid", required_argument, 0, 'p'}, + {"filter", required_argument, 0, 'F'}, + {"highlight-changes", optional_argument, 0, 'H'}, + {"readonly", no_argument, 0, 128}, + PLATFORM_LONG_OPTIONS + {0, 0, 0, 0} + }; + + int opt, opti = 0; + /* Parse arguments */ + while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) { + if (opt == EOF) + break; + switch (opt) { + case 'h': + printHelpFlag(program); + exit(0); + case 'V': + printVersionFlag(program); + exit(0); + case 's': + assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */ + if (String_eq(optarg, "help")) { + for (int j = 1; j < LAST_PROCESSFIELD; j++) { + const char* name = Process_fields[j].name; + const char* description = Process_fields[j].description; + if (name) printf("%19s %s\n", name, description); + } + exit(0); + } + flags.sortKey = 0; + for (int j = 1; j < LAST_PROCESSFIELD; j++) { + if (Process_fields[j].name == NULL) + continue; + if (String_eq(optarg, Process_fields[j].name)) { + flags.sortKey = j; + break; + } + } + if (flags.sortKey == 0) { + fprintf(stderr, "Error: invalid column \"%s\".\n", optarg); + exit(1); + } + break; + case 'd': + if (sscanf(optarg, "%16d", &(flags.delay)) == 1) { + if (flags.delay < 1) flags.delay = 1; + if (flags.delay > 100) flags.delay = 100; + } else { + fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg); + exit(1); + } + break; + case 'u': + { + const char *username = optarg; + if (!username && optind < argc && argv[optind] != NULL && + (argv[optind][0] != '\0' && argv[optind][0] != '-')) { + username = argv[optind++]; + } + + if (!username) { + flags.userId = geteuid(); + } else if (!Action_setUserOnly(username, &(flags.userId))) { + fprintf(stderr, "Error: invalid user \"%s\".\n", username); + exit(1); + } + break; + } + case 'C': + flags.useColors = false; + break; + case 'M': +#ifdef HAVE_GETMOUSE + flags.enableMouse = false; +#endif + break; + case 'U': + flags.allowUnicode = false; + break; + case 't': + flags.treeView = true; + break; + case 'p': { + assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */ + char* argCopy = xStrdup(optarg); + char* saveptr; + const char* pid = strtok_r(argCopy, ",", &saveptr); + + if (!flags.pidMatchList) { + flags.pidMatchList = Hashtable_new(8, false); + } + + while(pid) { + unsigned int num_pid = atoi(pid); + // deepcode ignore CastIntegerToAddress: we just want a non-NUll pointer here + Hashtable_put(flags.pidMatchList, num_pid, (void *) 1); + pid = strtok_r(NULL, ",", &saveptr); + } + free(argCopy); + + break; + } + case 'F': { + assert(optarg); + free_and_xStrdup(&flags.commFilter, optarg); + break; + } + case 'H': { + const char *delay = optarg; + if (!delay && optind < argc && argv[optind] != NULL && + (argv[optind][0] != '\0' && argv[optind][0] != '-')) { + delay = argv[optind++]; + } + if (delay) { + if (sscanf(delay, "%16d", &(flags.highlightDelaySecs)) == 1) { + if (flags.highlightDelaySecs < 1) + flags.highlightDelaySecs = 1; + } else { + fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay); + exit(1); + } + } + flags.highlightChanges = true; + break; + } + case 128: + flags.readonly = true; + break; + + default: + if (Platform_getLongOption(opt, argc, argv) == false) + exit(1); + break; + } + } + return flags; +} + +static void CommandLine_delay(ProcessList* pl, unsigned long millisec) { + struct timespec req = { + .tv_sec = 0, + .tv_nsec = millisec * 1000000L + }; + while (nanosleep(&req, &req) == -1) + continue; + Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs); +} + +static void setCommFilter(State* state, char** commFilter) { + ProcessList* pl = state->pl; + IncSet* inc = state->mainPanel->inc; + + IncSet_setFilter(inc, *commFilter); + pl->incFilter = IncSet_filter(inc); + + free(*commFilter); + *commFilter = NULL; +} + +int CommandLine_run(const char* name, int argc, char** argv) { + + /* initialize locale */ + const char* lc_ctype; + if ((lc_ctype = getenv("LC_CTYPE")) || (lc_ctype = getenv("LC_ALL"))) + setlocale(LC_CTYPE, lc_ctype); + else + setlocale(LC_CTYPE, ""); + + CommandLineSettings flags = parseArguments(name, argc, argv); + + if (flags.readonly) + Settings_enableReadonly(); + + Platform_init(); + + Process_setupColumnWidths(); + + UsersTable* ut = UsersTable_new(); + Hashtable* dm = DynamicMeters_new(); + ProcessList* pl = ProcessList_new(ut, dm, flags.pidMatchList, flags.userId); + + Settings* settings = Settings_new(pl->cpuCount); + pl->settings = settings; + + Header* header = Header_new(pl, settings, 2); + + Header_populateFromSettings(header); + + if (flags.delay != -1) + settings->delay = flags.delay; + if (!flags.useColors) + settings->colorScheme = COLORSCHEME_MONOCHROME; +#ifdef HAVE_GETMOUSE + if (!flags.enableMouse) + settings->enableMouse = false; +#endif + if (flags.treeView) + settings->treeView = true; + if (flags.highlightChanges) + settings->highlightChanges = true; + if (flags.highlightDelaySecs != -1) + settings->highlightDelaySecs = flags.highlightDelaySecs; + if (flags.sortKey > 0) { + // -t -s means "tree sorted by key" + // -s means "list sorted by key" (previous existing behavior) + if (!flags.treeView) { + settings->treeView = false; + } + Settings_setSortKey(settings, flags.sortKey); + } + + CRT_init(settings, flags.allowUnicode); + + MainPanel* panel = MainPanel_new(); + ProcessList_setPanel(pl, (Panel*) panel); + + MainPanel_updateTreeFunctions(panel, settings->treeView); + + State state = { + .settings = settings, + .ut = ut, + .pl = pl, + .mainPanel = panel, + .header = header, + .pauseProcessUpdate = false, + .hideProcessSelection = false, + }; + + MainPanel_setState(panel, &state); + if (flags.commFilter) + setCommFilter(&state, &(flags.commFilter)); + + ScreenManager* scr = ScreenManager_new(header, settings, &state, true); + ScreenManager_add(scr, (Panel*) panel, -1); + + ProcessList_scan(pl, false); + CommandLine_delay(pl, 75); + ProcessList_scan(pl, false); + + if (settings->allBranchesCollapsed) + ProcessList_collapseAllBranches(pl); + + ScreenManager_run(scr, NULL, NULL); + + attron(CRT_colors[RESET_COLOR]); + mvhline(LINES - 1, 0, ' ', COLS); + attroff(CRT_colors[RESET_COLOR]); + refresh(); + + Platform_done(); + + CRT_done(); + + if (settings->changed) { + int r = Settings_write(settings, false); + if (r < 0) + fprintf(stderr, "Can not save configuration to %s: %s\n", settings->filename, strerror(-r)); + } + + Header_delete(header); + ProcessList_delete(pl); + + ScreenManager_delete(scr); + MetersPanel_cleanup(); + + UsersTable_delete(ut); + + if (flags.pidMatchList) + Hashtable_delete(flags.pidMatchList); + + /* Delete Settings last, since it can get accessed in the crash handler */ + Settings_delete(settings); + + return 0; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandLine.h pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandLine.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandLine.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandLine.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,14 @@ +#ifndef HEADER_CommandLine +#define HEADER_CommandLine +/* +htop - CommandLine.h +(C) 2004-2011 Hisham H. Muhammad +(C) 2020-2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +int CommandLine_run(const char* name, int argc, char** argv); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandScreen.c pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandScreen.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandScreen.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandScreen.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,68 @@ +#include "config.h" // IWYU pragma: keep + +#include "CommandScreen.h" + +#include +#include +#include + +#include "Macros.h" +#include "Panel.h" +#include "ProvideCurses.h" + + +static void CommandScreen_scan(InfoScreen* this) { + Panel* panel = this->display; + int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0); + Panel_prune(panel); + + const char* p = Process_getCommand(this->process); + char line[COLS + 1]; + int line_offset = 0, last_spc = -1, len; + for (; *p != '\0'; p++, line_offset++) { + assert(line_offset >= 0 && (size_t)line_offset < sizeof(line)); + line[line_offset] = *p; + if (*p == ' ') { + last_spc = line_offset; + } + + if (line_offset == COLS) { + len = (last_spc == -1) ? line_offset : last_spc; + line[len] = '\0'; + InfoScreen_addLine(this, line); + + line_offset -= len; + last_spc = -1; + memcpy(line, p - line_offset, line_offset + 1); + } + } + + if (line_offset > 0) { + line[line_offset] = '\0'; + InfoScreen_addLine(this, line); + } + + Panel_setSelected(panel, idx); +} + +static void CommandScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Command of process %d - %s", this->process->pid, Process_getCommand(this->process)); +} + +const InfoScreenClass CommandScreen_class = { + .super = { + .extends = Class(Object), + .delete = CommandScreen_delete + }, + .scan = CommandScreen_scan, + .draw = CommandScreen_draw +}; + +CommandScreen* CommandScreen_new(Process* process) { + CommandScreen* this = AllocThis(CommandScreen); + return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " "); +} + +void CommandScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandScreen.h pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandScreen.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CommandScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CommandScreen.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_CommandScreen +#define HEADER_CommandScreen + +#include "InfoScreen.h" +#include "Object.h" +#include "Process.h" + + +typedef struct CommandScreen_ { + InfoScreen super; +} CommandScreen; + +extern const InfoScreenClass CommandScreen_class; + +CommandScreen* CommandScreen_new(Process* process); + +void CommandScreen_delete(Object* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Compat.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Compat.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Compat.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Compat.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,119 @@ +/* +htop - Compat.c +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "Compat.h" + +#include +#include // IWYU pragma: keep +#include +#include +#include // IWYU pragma: keep + +#include "XUtils.h" // IWYU pragma: keep + + +int Compat_faccessat(int dirfd, + const char* pathname, + int mode, + int flags) { + int ret; + +#ifdef HAVE_FACCESSAT + + // Implementation note: AT_SYMLINK_NOFOLLOW unsupported on FreeBSD, fallback to lstat in that case + + errno = 0; + + ret = faccessat(dirfd, pathname, mode, flags); + if (!ret || errno != EINVAL) + return ret; + +#endif + + // Error out on unsupported configurations + if (dirfd != (int)AT_FDCWD || mode != F_OK) { + errno = EINVAL; + return -1; + } + + // Fallback to stat(2)/lstat(2) depending on flags + struct stat statinfo; + if(flags) { + ret = lstat(pathname, &statinfo); + } else { + ret = stat(pathname, &statinfo); + } + + return ret; +} + +int Compat_fstatat(int dirfd, + const char* dirpath, + const char* pathname, + struct stat* statbuf, + int flags) { + +#ifdef HAVE_FSTATAT + + (void)dirpath; + + return fstatat(dirfd, pathname, statbuf, flags); + +#else + + (void)dirfd; + + char path[4096]; + xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); + + if (flags & AT_SYMLINK_NOFOLLOW) + return lstat(path, statbuf); + + return stat(path, statbuf); + +#endif +} + +#ifndef HAVE_OPENAT + +int Compat_openat(const char* dirpath, + const char* pathname, + int flags) { + + char path[4096]; + xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); + + return open(path, flags); +} + +#endif /* !HAVE_OPENAT */ + +ssize_t Compat_readlinkat(int dirfd, + const char* dirpath, + const char* pathname, + char* buf, + size_t bufsize) { + +#ifdef HAVE_READLINKAT + + (void)dirpath; + + return readlinkat(dirfd, pathname, buf, bufsize); + +#else + + (void)dirfd; + + char path[4096]; + xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); + + return readlink(path, buf, bufsize); + +#endif +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Compat.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Compat.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Compat.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Compat.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,59 @@ +#ifndef HEADER_Compat +#define HEADER_Compat +/* +htop - Compat.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include +#include +#include // IWYU pragma: keep + + +int Compat_faccessat(int dirfd, + const char* pathname, + int mode, + int flags); + +int Compat_fstatat(int dirfd, + const char* dirpath, + const char* pathname, + struct stat* statbuf, + int flags); + +#ifdef HAVE_OPENAT + +typedef int openat_arg_t; + +static inline void Compat_openatArgClose(openat_arg_t dirfd) { + close(dirfd); +} + +static inline int Compat_openat(openat_arg_t dirfd, const char* pathname, int flags) { + return openat(dirfd, pathname, flags); +} + +#else /* HAVE_OPENAT */ + +typedef const char* openat_arg_t; + +static inline void Compat_openatArgClose(openat_arg_t dirpath) { + (void)dirpath; +} + +int Compat_openat(openat_arg_t dirpath, const char* pathname, int flags); + +#endif /* HAVE_OPENAT */ + +ssize_t Compat_readlinkat(int dirfd, + const char* dirpath, + const char* pathname, + char* buf, + size_t bufsize); + +#endif /* HEADER_Compat */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/configure.ac pcp-5.3.2/vendor/github.com/htop-dev/htop/configure.ac --- pcp-5.3.1/vendor/github.com/htop-dev/htop/configure.ac 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/configure.ac 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,699 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +# ---------------------------------------------------------------------- +# Autoconf initialization. +# ---------------------------------------------------------------------- + +AC_PREREQ([2.69]) +AC_INIT([htop], [3.1.0-dev], [htop@groups.io], [], [https://htop.dev/]) + +AC_CONFIG_SRCDIR([htop.c]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_HEADERS([config.h]) + +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([-Wall std-options subdir-objects]) + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for platform. +# ---------------------------------------------------------------------- + +case "$target_os" in +linux*|gnu*) + my_htop_platform=linux + AC_DEFINE([HTOP_LINUX], [], [Building for Linux.]) + ;; +freebsd*|kfreebsd*) + my_htop_platform=freebsd + AC_DEFINE([HTOP_FREEBSD], [], [Building for FreeBSD.]) + ;; +netbsd*) + my_htop_platform=netbsd + AC_DEFINE([HTOP_NETBSD], [], [Building for NetBSD.]) + ;; +openbsd*) + my_htop_platform=openbsd + AC_DEFINE([HTOP_OPENBSD], [], [Building for OpenBSD.]) + ;; +dragonfly*) + my_htop_platform=dragonflybsd + AC_DEFINE([HTOP_DRAGONFLYBSD], [], [Building for DragonFlyBSD.]) + ;; +darwin*) + my_htop_platform=darwin + AC_DEFINE([HTOP_DARWIN], [], [Building for Darwin.]) + ;; +solaris*) + my_htop_platform=solaris + AC_DEFINE([HTOP_SOLARIS], [], [Building for Solaris.]) + ;; +*) + my_htop_platform=unsupported + AC_DEFINE([HTOP_UNSUPPORTED], [], [Building for an unsupported platform.]) + ;; +esac + +# Enable extensions, required by hwloc scripts +AC_USE_SYSTEM_EXTENSIONS + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for compiler. +# ---------------------------------------------------------------------- + +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_CC_C99 +AS_IF([test "x$ac_cv_prog_cc_c99" = xno], [AC_MSG_ERROR([htop is written in C99. A newer compiler is required.])]) + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for static build. +# ---------------------------------------------------------------------- + +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static], + [build a static htop binary @<:@default=no@:>@])], + [], + [enable_static=no]) +case "$enable_static" in + no) + ;; + yes) + AC_DEFINE([BUILD_STATIC], [1], [Define if building static binary.]) + CFLAGS="$CFLAGS -static" + LDFLAGS="$LDFLAGS -static" + ;; + *) + AC_MSG_ERROR([bad value '$enable_static' for --enable-static option]) + ;; +esac + +# ---------------------------------------------------------------------- + +# ---------------------------------------------------------------------- +# Checks for a PCP-based htop build. (https://pcp.io) +# ---------------------------------------------------------------------- + +AC_ARG_ENABLE([pcp], + [AS_HELP_STRING([--enable-pcp], + [build a pcp-htop binary @<:@default=no@:>@])], + [], + [enable_pcp=no]) +case "$enable_pcp" in + no) + ;; + yes) + AC_CHECK_HEADERS([pcp/pmapi.h], [my_htop_platform=pcp], + [AC_MSG_ERROR([can not find PCP header file])]) + AC_SEARCH_LIBS([pmNewContext], [pcp], [], [AC_MSG_ERROR([can not find PCP library])]) + AC_DEFINE([HTOP_PCP], [1], [Define if building pcp-htop binary.]) + ;; + *) + AC_MSG_ERROR([bad value '$enable_pcp' for --enable-pcp option]) + ;; +esac + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for generic header files. +# ---------------------------------------------------------------------- + +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS([ \ + stdlib.h \ + string.h \ + strings.h \ + sys/param.h \ + sys/time.h \ + sys/utsname.h \ + unistd.h + ], [], [AC_MSG_ERROR([can not find required generic header files])]) + +AC_HEADER_MAJOR +dnl glibc 2.25 deprecates 'major' and 'minor' in and requires to +dnl include . However the logic in AC_HEADER_MAJOR has not yet +dnl been updated in Autoconf 2.69, so use a workaround: +m4_version_prereq([2.70], [], +[if test "x$ac_cv_header_sys_mkdev_h" != xyes; then + AC_CHECK_HEADER([sys/sysmacros.h], [AC_DEFINE([MAJOR_IN_SYSMACROS], [1], + [Define to 1 if `major', `minor', and `makedev' are declared in .])]) +fi]) + +# Optional Section + +AC_CHECK_HEADERS([execinfo.h]) + +if test "$my_htop_platform" = darwin; then + AC_CHECK_HEADERS([mach/mach_time.h]) +fi + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for typedefs, structures, and compiler characteristics. +# ---------------------------------------------------------------------- + +AC_TYPE_PID_T +AC_TYPE_UID_T +AC_TYPE_UINT8_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T + +AC_MSG_CHECKING(for alloc_size) +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Wno-error -Werror=attributes" +AC_COMPILE_IFELSE([ + AC_LANG_SOURCE( + [ + __attribute__((alloc_size(1))) char* my_alloc(int size) { return 0; } + ],[] + )], + AC_DEFINE([HAVE_ATTR_ALLOC_SIZE], 1, [The alloc_size attribute is supported.]) + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) +CFLAGS="$old_CFLAGS" + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for generic library functions. +# ---------------------------------------------------------------------- + +AC_CHECK_LIB([m], [ceil], [], [AC_MSG_ERROR([can not find required function ceil()])]) + +if test "$my_htop_platform" = dragonflybsd; then + AC_SEARCH_LIBS([kvm_open], [kvm], [], [AC_MSG_ERROR([can not find required function kvm_open()])]) +fi + +if test "$my_htop_platform" = freebsd; then + if test "$enable_static" = yes; then + AC_SEARCH_LIBS([elf_version], [elf], [], [AC_MSG_ERROR([can not find required function elf_version()])]) + fi + AC_SEARCH_LIBS([kvm_open], [kvm], [], [AC_MSG_ERROR([can not find required function kvm_open()])]) + AC_SEARCH_LIBS([devstat_checkversion], [devstat], [], [AC_MSG_ERROR([can not find required function devstat_checkversion()])]) +fi + +if test "$my_htop_platform" = linux; then + if test "$enable_static" != yes; then + AC_SEARCH_LIBS([dlopen], [dl dld], [], [AC_MSG_ERROR([can not find required function dlopen()])]) + fi +fi + +if test "$my_htop_platform" = netbsd; then + AC_SEARCH_LIBS([kvm_open], [kvm], [], [AC_MSG_ERROR([can not find required function kvm_open()])]) +fi + +if test "$my_htop_platform" = openbsd; then + AC_SEARCH_LIBS([kvm_open], [kvm], [], [AC_MSG_ERROR([can not find required function kvm_open()])]) +fi + +if test "$my_htop_platform" = solaris; then + AC_SEARCH_LIBS([kstat_open], [kstat], [], [AC_MSG_ERROR([can not find required function kstat_open()])]) + AC_SEARCH_LIBS([Pgrab_error], [proc], [], [AC_MSG_ERROR([can not find required function Pgrab_error()])]) + AC_SEARCH_LIBS([free], [malloc], [], [AC_MSG_ERROR([can not find required function free()])]) +fi + +# Optional Section + +AC_SEARCH_LIBS([clock_gettime], [rt]) + +AC_CHECK_FUNCS([ \ + clock_gettime \ + faccessat \ + fstatat \ + host_get_clock_service \ + memfd_create\ + openat \ + readlinkat \ + ]) + +# Add -lexecinfo if needed +AC_SEARCH_LIBS([backtrace], [execinfo]) + +if test "$my_htop_platform" = darwin; then + AC_CHECK_FUNCS([mach_timebase_info]) +fi + +if test "$my_htop_platform" = linux && test "x$enable_static" = xyes; then + AC_CHECK_LIB([systemd], [sd_bus_open_system]) +fi + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for cross-platform features and flags. +# ---------------------------------------------------------------------- + +# HTOP_CHECK_SCRIPT(LIBNAME, FUNCTION, DEFINE, CONFIG_SCRIPT, ELSE_PART) +m4_define([HTOP_CHECK_SCRIPT], +[ + if test ! -z "m4_toupper($HTOP_[$1]_CONFIG_SCRIPT)"; then + # to be used to set the path to ncurses*-config when cross-compiling + htop_config_script_libs=$(m4_toupper($HTOP_[$1]_CONFIG_SCRIPT) --libs 2> /dev/null) + htop_config_script_cflags=$(m4_toupper($HTOP_[$1]_CONFIG_SCRIPT) --cflags 2> /dev/null) + else + htop_config_script_libs=$([$4] --libs 2> /dev/null) + htop_config_script_cflags=$([$4] --cflags 2> /dev/null) + fi + htop_script_success=no + htop_save_CFLAGS="$CFLAGS" + if test ! "x$htop_config_script_libs" = x; then + CFLAGS="$htop_config_script_cflags $CFLAGS" + AC_CHECK_LIB([$1], [$2], [ + AC_DEFINE([$3], 1, [The library is present.]) + LIBS="$htop_config_script_libs $LIBS " + htop_script_success=yes + ], [ + CFLAGS="$htop_save_CFLAGS" + ], [ + $htop_config_script_libs + ]) + fi + if test "x$htop_script_success" = xno; then + [$5] + fi +]) + +# HTOP_CHECK_LIB(LIBNAME, FUNCTION, DEFINE, ELSE_PART) +m4_define([HTOP_CHECK_LIB], +[ + AC_CHECK_LIB([$1], [$2], [ + AC_DEFINE([$3], [1], [The library is present.]) + LIBS="-l[$1] $LIBS " + ], [$4]) +]) + +AC_ARG_ENABLE([unicode], + [AS_HELP_STRING([--enable-unicode], + [enable Unicode support @<:@default=yes@:>@])], + [], + [enable_unicode=yes]) +if test "x$enable_unicode" = xyes; then + HTOP_CHECK_SCRIPT([ncursesw6], [waddwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", + HTOP_CHECK_SCRIPT([ncursesw], [waddwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", + HTOP_CHECK_SCRIPT([ncursesw], [wadd_wch], [HAVE_LIBNCURSESW], "ncursesw5-config", + HTOP_CHECK_SCRIPT([ncurses], [wadd_wch], [HAVE_LIBNCURSESW], "ncurses5-config", + HTOP_CHECK_LIB([ncursesw6], [addnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_LIB([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_LIB([ncurses], [addnwstr], [HAVE_LIBNCURSESW], + AC_MSG_ERROR([can not find required library libncursesw; you may want to use --disable-unicode]) + ))))))) + + AC_CHECK_HEADERS([ncursesw/curses.h], [], + [AC_CHECK_HEADERS([ncurses/ncurses.h], [], + [AC_CHECK_HEADERS([ncurses/curses.h], [], + [AC_CHECK_HEADERS([ncurses.h], [], + [AC_MSG_ERROR([can not find required ncurses header file])])])])]) + + # check if additional linker flags are needed for keypad(3) + # (at this point we already link against a working ncurses library with wide character support) + AC_SEARCH_LIBS([keypad], [tinfow tinfo]) +else + HTOP_CHECK_SCRIPT([ncurses6], [wnoutrefresh], [HAVE_LIBNCURSES], [ncurses6-config], + HTOP_CHECK_SCRIPT([ncurses], [wnoutrefresh], [HAVE_LIBNCURSES], [ncurses5-config], + HTOP_CHECK_LIB([ncurses6], [doupdate], [HAVE_LIBNCURSES], + HTOP_CHECK_LIB([ncurses], [doupdate], [HAVE_LIBNCURSES], + HTOP_CHECK_LIB([curses], [doupdate], [HAVE_LIBNCURSES], + AC_MSG_ERROR([can not find required curses/ncurses library]) + ))))) + + AC_CHECK_HEADERS([curses.h], [], + [AC_CHECK_HEADERS([ncurses/curses.h], [], + [AC_CHECK_HEADERS([ncurses/ncurses.h], [], + [AC_CHECK_HEADERS([ncurses.h] ,[], + [AC_MSG_ERROR([can not find required ncurses header file])])])])]) + + # check if additional linker flags are needed for keypad(3) + # (at this point we already link against a working ncurses library) + AC_SEARCH_LIBS([keypad], [tinfo]) +fi +if test "$enable_static" = yes; then + AC_SEARCH_LIBS([Gpm_GetEvent], [gpm]) +fi +if test "$my_htop_platform" = "solaris"; then + # On OmniOS /usr/include/sys/regset.h redefines ERR to 13 - \r, breaking the Enter key. + # Since ncruses macros use the ERR macro, we can not use another name. + AC_DEFINE([ERR], [(-1)], [Predefine ncurses macro.]) +fi +AC_CHECK_FUNCS( [set_escdelay] ) +AC_CHECK_FUNCS( [getmouse] ) + + +AC_ARG_ENABLE([hwloc], + [AS_HELP_STRING([--enable-hwloc], + [enable hwloc support for CPU affinity; disables Linux affinity; requires libhwloc @<:@default=no@:>@])], + [], + [enable_hwloc=no]) +case "$enable_hwloc" in + no) + ;; + yes) + AC_CHECK_LIB([hwloc], [hwloc_get_proc_cpubind], [], [AC_MSG_ERROR([can not find required library libhwloc])]) + AC_CHECK_HEADERS([hwloc.h], [], [AC_MSG_ERROR([can not find require header file hwloc.h])]) + ;; + *) + AC_MSG_ERROR([bad value '$enable_hwloc' for --enable-hwloc]) + ;; +esac + +AC_ARG_WITH([os-release], + [AS_HELP_STRING([--with-os-release=FILE], + [location of an os-release file @<:@default=/etc/os-release@:>@])], + [], + [with_os_release=/etc/os-release]) +if test -n "$with_os_release" && test ! -f "$with_os_release"; then + if test -f "/usr/lib/os-release"; then + with_os_release="/usr/lib/os-release" + fi +fi +AC_DEFINE_UNQUOTED([OSRELEASEFILE], ["$with_os_release"], [File with OS release details.]) + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for Linux features and flags. +# ---------------------------------------------------------------------- + +AC_ARG_WITH([proc], + [AS_HELP_STRING([--with-proc=DIR], + [location of a Linux-compatible proc filesystem @<:@default=/proc@:>@])], + [], + [with_proc=/proc]) +if test -z "$with_proc"; then + AC_MSG_ERROR([bad empty value for --with-proc option]) +fi +AC_DEFINE_UNQUOTED([PROCDIR], ["$with_proc"], [Path of proc filesystem.]) + + +AC_ARG_ENABLE([openvz], + [AS_HELP_STRING([--enable-openvz], + [enable OpenVZ support @<:@default=no@:>@])], + [], + [enable_openvz=no]) +if test "x$enable_openvz" = xyes; then + AC_DEFINE([HAVE_OPENVZ], [1], [Define if openvz support enabled.]) +fi + + +AC_ARG_ENABLE([vserver], + [AS_HELP_STRING([--enable-vserver], + [enable VServer support @<:@default=no@:>@])], + [], + [enable_vserver=no]) +if test "x$enable_vserver" = xyes; then + AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.]) +fi + + +AC_ARG_ENABLE([ancient_vserver], + [AS_HELP_STRING([--enable-ancient-vserver], + [enable ancient VServer support (implies --enable-vserver) @<:@default=no@:>@])], + [], + [enable_ancient_vserver=no]) +if test "x$enable_ancient_vserver" = xyes; then + AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.]) + AC_DEFINE([HAVE_ANCIENT_VSERVER], [1], [Define if ancient vserver support enabled.]) +fi + + +AC_ARG_ENABLE([linux_affinity], + [AS_HELP_STRING([--enable-linux-affinity], + [enable Linux sched_setaffinity and sched_getaffinity for affinity support, conflicts with hwloc @<:@default=check@:>@])], + [], + [enable_linux_affinity=check]) +if test "x$enable_linux_affinity" = xcheck; then + if test "x$enable_hwloc" = xyes; then + enable_linux_affinity=no + else + AC_MSG_CHECKING([for usable sched_setaffinity]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ + #include + #include + static cpu_set_t cpuset; + ]], [[ + CPU_ZERO(&cpuset); + sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); + if (errno == ENOSYS) return 1; + ]])], + [enable_linux_affinity=yes + AC_MSG_RESULT([yes])], + [enable_linux_affinity=no + AC_MSG_RESULT([no])], + [AC_MSG_RESULT([yes (assumed while cross compiling)])]) + fi +fi +if test "x$enable_linux_affinity" = xyes; then + if test "x$enable_hwloc" = xyes; then + AC_MSG_ERROR([--enable-hwloc and --enable-linux-affinity are mutual exclusive. Specify at most one of them.]) + fi + AC_DEFINE([HAVE_LINUX_AFFINITY], [1], [Define if Linux sched_setaffinity and sched_getaffinity are to be used.]) +fi + + +AC_ARG_ENABLE([capabilities], + [AS_HELP_STRING([--enable-capabilities], + [enable Linux capabilities support; requires libcap @<:@default=check@:>@])], + [], + [enable_capabilities=check]) +case "$enable_capabilities" in + no) + ;; + check) + enable_capabilities=yes + AC_CHECK_LIB([cap], [cap_init], [], [enable_capabilities=no]) + AC_CHECK_HEADERS([sys/capability.h], [], [enable_capabilities=no]) + ;; + yes) + AC_CHECK_LIB([cap], [cap_init], [], [AC_MSG_ERROR([can not find required library libcap])]) + AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([can not find required header file sys/capability.h])]) + ;; + *) + AC_MSG_ERROR([bad value '$enable_capabilities' for --enable-capabilities]) + ;; +esac + + +AC_ARG_ENABLE([delayacct], + [AS_HELP_STRING([--enable-delayacct], + [enable Linux delay accounting support; requires pkg-config, libnl-3 and libnl-genl-3 @<:@default=check@:>@])], + [], + [enable_delayacct=check]) +case "$enable_delayacct" in + no) + ;; + check) + if test "$my_htop_platform" != linux; then + enable_delayacct=no + elif test "$enable_static" = yes; then + enable_delayacct=no + else + m4_ifdef([PKG_PROG_PKG_CONFIG], [ + enable_delayacct=yes + PKG_PROG_PKG_CONFIG() + PKG_CHECK_MODULES(LIBNL3, libnl-3.0, [], [enable_delayacct=no]) + PKG_CHECK_MODULES(LIBNL3GENL, libnl-genl-3.0, [], [enable_delayacct=no]) + if test "$enable_delayacct" = yes; then + CFLAGS="$CFLAGS $LIBNL3_CFLAGS $LIBNL3GENL_CFLAGS" + LIBS="$LIBS $LIBNL3_LIBS $LIBNL3GENL_LIBS" + AC_DEFINE([HAVE_DELAYACCT], [1], [Define if delay accounting support should be enabled.]) + fi + ], [ + enable_delayacct=no + AC_MSG_NOTICE([Linux delay accounting support can not be enabled, cause pkg-config is required for checking its availability]) + ]) + fi + ;; + yes) + m4_ifdef([PKG_PROG_PKG_CONFIG], [ + PKG_PROG_PKG_CONFIG() + PKG_CHECK_MODULES(LIBNL3, libnl-3.0, [], [AC_MSG_ERROR([can not find required library libnl3])]) + PKG_CHECK_MODULES(LIBNL3GENL, libnl-genl-3.0, [], [AC_MSG_ERROR([can not find required library libnl3genl])]) + CFLAGS="$CFLAGS $LIBNL3_CFLAGS $LIBNL3GENL_CFLAGS" + LIBS="$LIBS $LIBNL3_LIBS $LIBNL3GENL_LIBS" + AC_DEFINE([HAVE_DELAYACCT], [1], [Define if delay accounting support should be enabled.]) + ], [ + pkg_m4_absent=1 + m4_warning([configure is generated without pkg.m4. 'make dist' target will be disabled.]) + AC_MSG_ERROR([htop on Linux requires pkg-config for checking delayacct requirements. Please install pkg-config and run ./autogen.sh to rebuild the configure script.]) + ]) + ;; + *) + AC_MSG_ERROR([bad value '$enable_delayacct' for --enable-delayacct]) + ;; +esac + + +AC_ARG_ENABLE([sensors], + [AS_HELP_STRING([--enable-sensors], + [enable libsensors support for reading temperature data; requires only libsensors headers at compile time, at runtime libsensors is loaded via dlopen @<:@default=check@:>@])], + [], + [enable_sensors=check]) +case "$enable_sensors" in + no) + ;; + check) + enable_sensors=yes + if test "$enable_static" = yes; then + AC_CHECK_LIB([sensors], [sensors_init], [], [enable_sensors=no]) + fi + AC_CHECK_HEADERS([sensors/sensors.h], [], [enable_sensors=no]) + ;; + yes) + if test "$enable_static" = yes; then + AC_CHECK_LIB([sensors], [sensors_init], [], [AC_MSG_ERROR([can not find required library libsensors])]) + fi + AC_CHECK_HEADERS([sensors/sensors.h], [], [AC_MSG_ERROR([can not find required header file sensors/sensors.h])]) + ;; + *) + AC_MSG_ERROR([bad value '$enable_sensors' for --enable-sensors]) + ;; +esac +if test "$enable_sensors" = yes || test "$my_htop_platform" = freebsd; then + AC_DEFINE([BUILD_WITH_CPU_TEMP], [1], [Define if CPU temperature option should be enabled.]) +fi + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# Checks for compiler warnings. +# ---------------------------------------------------------------------- + +AM_CFLAGS="\ + -Wall\ + -Wcast-align\ + -Wcast-qual\ + -Wextra\ + -Wfloat-equal\ + -Wformat=2\ + -Winit-self\ + -Wmissing-format-attribute\ + -Wmissing-noreturn\ + -Wmissing-prototypes\ + -Wpointer-arith\ + -Wshadow\ + -Wstrict-prototypes\ + -Wundef\ + -Wunused\ + -Wwrite-strings" + +# FreeBSD uses C11 _Generic in its isnan implementation, even with -std=c99 +if test "$my_htop_platform" = freebsd; then + AM_CFLAGS="$AM_CFLAGS -Wno-c11-extensions" +fi + +dnl https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[ +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS + +AX_CHECK_COMPILE_FLAG([-Wnull-dereference], [AM_CFLAGS="$AM_CFLAGS -Wnull-dereference"], , [-Werror]) + +AC_ARG_ENABLE([werror], + [AS_HELP_STRING([--enable-werror], + [Treat warnings as errors @<:@default=no@:>@])], + [], + [enable_werror=no]) +if test "x$enable_werror" = xyes; then + AM_CFLAGS="$AM_CFLAGS -Werror" +fi + +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug], + [Enable compiling with maximum debug info, asserts and internal sanity checks @<:@default=no@:>@])], + [], + [enable_debug=no]) +if test "x$enable_debug" != xyes; then + AM_CPPFLAGS="$AM_CPPFLAGS -DNDEBUG" +else + AM_CPPFLAGS="$AM_CPPFLAGS -ggdb3" +fi + + +AC_SUBST([AM_CFLAGS]) +AC_SUBST([AM_CPPFLAGS]) + +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# We're done, let's go! +# ---------------------------------------------------------------------- + +AC_DEFINE_UNQUOTED([COPYRIGHT], ["(C) 2004-2019 Hisham Muhammad. (C) 2020-2021 htop dev team."], [Copyright message.]) + +AM_CONDITIONAL([HTOP_LINUX], [test "$my_htop_platform" = linux]) +AM_CONDITIONAL([HTOP_FREEBSD], [test "$my_htop_platform" = freebsd]) +AM_CONDITIONAL([HTOP_DRAGONFLYBSD], [test "$my_htop_platform" = dragonflybsd]) +AM_CONDITIONAL([HTOP_NETBSD], [test "$my_htop_platform" = netbsd]) +AM_CONDITIONAL([HTOP_OPENBSD], [test "$my_htop_platform" = openbsd]) +AM_CONDITIONAL([HTOP_DARWIN], [test "$my_htop_platform" = darwin]) +AM_CONDITIONAL([HTOP_SOLARIS], [test "$my_htop_platform" = solaris]) +AM_CONDITIONAL([HTOP_PCP], [test "$my_htop_platform" = pcp]) +AM_CONDITIONAL([HTOP_UNSUPPORTED], [test "$my_htop_platform" = unsupported]) + +AC_SUBST(my_htop_platform) +AC_CONFIG_FILES([Makefile htop.1]) +AC_OUTPUT + +if test "$my_htop_platform" = unsupported; then + echo "" + echo "****************************************************************" + echo "WARNING! This platform is not currently supported by htop." + echo "" + echo "The code will build, but it will produce a dummy version of htop" + echo "which shows no processes, using the files from the unsupported/" + echo "directory. This is meant to be a skeleton, to be used as a" + echo "starting point if you are porting htop to a new platform." + echo "****************************************************************" + echo "" +fi + +AC_MSG_RESULT([ + ${PACKAGE_NAME} ${VERSION} + + platform: $my_htop_platform + os-release file: $with_os_release + (Linux) proc directory: $with_proc + (Linux) openvz: $enable_openvz + (Linux) vserver: $enable_vserver + (Linux) ancient vserver: $enable_ancient_vserver + (Linux) affinity: $enable_linux_affinity + (Linux) delay accounting: $enable_delayacct + (Linux) sensors: $enable_sensors + (Linux) capabilities: $enable_capabilities + unicode: $enable_unicode + hwloc: $enable_hwloc + debug: $enable_debug + static: $enable_static +]) diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CONTRIBUTING.md pcp-5.3.2/vendor/github.com/htop-dev/htop/CONTRIBUTING.md --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CONTRIBUTING.md 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,45 @@ +Contributing Guide +================== + +Thank you so much for taking the time to contribute in to htop! + +Bug Reports +----------- + +Bug reports should be posted in the [Github issue +tracker](https://github.com/htop-dev/htop/issues). +Bug reports are extremely important since it's impossible for us to test +htop in every possible system, distribution and scenario. Your feedback +is what keeps the tool stable and always improving! Thank you! + +Pull Requests +------------- + +Code contributions are most welcome! Just [fork the +repo](https://github.com/htop-dev/htop) and send a [pull +request](https://github.com/htop-dev/htop/pulls). Help is especially +appreciated for support of platforms other than Linux. If proposing new +features, please be mindful that htop is a system tool that needs to keep a +small footprint and perform well on systems under stress -- so unfortunately +we can't accept every new feature proposed, as we need to keep the tool slim +and maintainable. Great ideas backed by a PR are always carefully considered +for inclusion though! Also, PRs containing bug fixes and portability tweaks +are always included, please send those in! + +Feature Requests +---------------- + +Please label Github issues that are feature requests with one of the `feature request` +labels. If you can't do this yourself, don't worry. The friendly folks from the +core team will distribute and fixup Github labels as part of the regular reviews. + +Style Guide +----------- + +To make working with the code easier a set of guidelines have evolved in +the past that new contributions should try to follow. While they are not set +in stone and always up for changes should the need arise they still provide +a first orientation to go by when contributing to this repository. + +The details of the coding style as well as what to take care about with your +contributions can be found in our [style guide](docs/styleguide.md). diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/COPYING pcp-5.3.2/vendor/github.com/htop-dev/htop/COPYING --- pcp-5.3.1/vendor/github.com/htop-dev/htop/COPYING 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/COPYING 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,355 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + + Appendix 2: Special exception concerning PLPA + + In the following exception, "PLPA" means (i) code released by the + Portable Linux Processor Affinity Project, or (ii) derivative works of + such code, in both cases provided that the code is covered entirely by + free software licensing terms. + + As a special exception to the GNU GPL, the licensors of htop give you + permission to combine GNU GPL-licensed code in htop (and derivative + works of such code) with PLPA. You may copy and distribute such a + combined work following the terms of the GNU GPL for htop and the + applicable licenses of the version of PLPA used in your combined work, + provided that you include the source code of such version of PLPA when + and as the GNU GPL requires distribution of source code. diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CPUMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/CPUMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CPUMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CPUMeter.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,586 @@ +/* +htop - CPUMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "CPUMeter.h" + +#include +#include +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "Settings.h" +#include "XUtils.h" + + +static const int CPUMeter_attributes[] = { + CPU_NICE, + CPU_NORMAL, + CPU_SYSTEM, + CPU_IRQ, + CPU_SOFTIRQ, + CPU_STEAL, + CPU_GUEST, + CPU_IOWAIT +}; + +typedef struct CPUMeterData_ { + unsigned int cpus; + Meter** meters; +} CPUMeterData; + +static void CPUMeter_init(Meter* this) { + unsigned int cpu = this->param; + if (cpu == 0) { + Meter_setCaption(this, "Avg"); + } else if (this->pl->cpuCount > 1) { + char caption[10]; + xSnprintf(caption, sizeof(caption), "%3u", Settings_cpuId(this->pl->settings, cpu - 1)); + Meter_setCaption(this, caption); + } +} + +// Custom uiName runtime logic to include the param (processor) +static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) { + if (this->param > 0) + xSnprintf(buffer, sizeof(length), "%s %u", Meter_uiName(this), this->param); + else + xSnprintf(buffer, sizeof(length), "%s", Meter_uiName(this)); +} + +static void CPUMeter_updateValues(Meter* this) { + unsigned int cpu = this->param; + if (cpu > this->pl->cpuCount) { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "absent"); + for (uint8_t i = 0; i < this->curItems; i++) + this->values[i] = 0; + return; + } + memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT); + + char cpuUsageBuffer[8] = { 0 }; + char cpuFrequencyBuffer[16] = { 0 }; + char cpuTemperatureBuffer[16] = { 0 }; + + double percent = Platform_setCPUValues(this, cpu); + + if (this->pl->settings->showCPUUsage) { + xSnprintf(cpuUsageBuffer, sizeof(cpuUsageBuffer), "%.1f%%", percent); + } + + if (this->pl->settings->showCPUFrequency) { + double cpuFrequency = this->values[CPU_METER_FREQUENCY]; + if (isnan(cpuFrequency)) { + xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A"); + } else { + xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency); + } + } + + #ifdef BUILD_WITH_CPU_TEMP + if (this->pl->settings->showCPUTemperature) { + double cpuTemperature = this->values[CPU_METER_TEMPERATURE]; + if (isnan(cpuTemperature)) + xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A"); + else if (this->pl->settings->degreeFahrenheit) + xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%3d%sF", (int)(cpuTemperature * 9 / 5 + 32), CRT_degreeSign); + else + xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%d%sC", (int)cpuTemperature, CRT_degreeSign); + } + #endif + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%s%s%s%s", + cpuUsageBuffer, + (cpuUsageBuffer[0] && (cpuFrequencyBuffer[0] || cpuTemperatureBuffer[0])) ? " " : "", + cpuFrequencyBuffer, + (cpuFrequencyBuffer[0] && cpuTemperatureBuffer[0]) ? " " : "", + cpuTemperatureBuffer); +} + +static void CPUMeter_display(const Object* cast, RichString* out) { + char buffer[50]; + int len; + const Meter* this = (const Meter*)cast; + + if (this->param > this->pl->cpuCount) { + RichString_appendAscii(out, CRT_colors[METER_TEXT], "absent"); + return; + } + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NORMAL]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], ":"); + RichString_appendnAscii(out, CRT_colors[CPU_NORMAL], buffer, len); + if (this->pl->settings->detailedCPUTime) { + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "sy:"); + RichString_appendnAscii(out, CRT_colors[CPU_SYSTEM], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "ni:"); + RichString_appendnAscii(out, CRT_colors[CPU_NICE_TEXT], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "hi:"); + RichString_appendnAscii(out, CRT_colors[CPU_IRQ], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_SOFTIRQ]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "si:"); + RichString_appendnAscii(out, CRT_colors[CPU_SOFTIRQ], buffer, len); + if (!isnan(this->values[CPU_METER_STEAL])) { + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_STEAL]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "st:"); + RichString_appendnAscii(out, CRT_colors[CPU_STEAL], buffer, len); + } + if (!isnan(this->values[CPU_METER_GUEST])) { + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_GUEST]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "gu:"); + RichString_appendnAscii(out, CRT_colors[CPU_GUEST], buffer, len); + } + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IOWAIT]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "wa:"); + RichString_appendnAscii(out, CRT_colors[CPU_IOWAIT], buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "sys:"); + RichString_appendnAscii(out, CRT_colors[CPU_SYSTEM], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "low:"); + RichString_appendnAscii(out, CRT_colors[CPU_NICE_TEXT], buffer, len); + if (!isnan(this->values[CPU_METER_IRQ])) { + len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "vir:"); + RichString_appendnAscii(out, CRT_colors[CPU_GUEST], buffer, len); + } + } + + #ifdef BUILD_WITH_CPU_TEMP + if (this->pl->settings->showCPUTemperature) { + char cpuTemperatureBuffer[10]; + double cpuTemperature = this->values[CPU_METER_TEMPERATURE]; + if (isnan(cpuTemperature)) { + len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A"); + } else if (this->pl->settings->degreeFahrenheit) { + len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sF", cpuTemperature * 9 / 5 + 32, CRT_degreeSign); + } else { + len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sC", cpuTemperature, CRT_degreeSign); + } + RichString_appendAscii(out, CRT_colors[METER_TEXT], "temp:"); + RichString_appendnWide(out, CRT_colors[METER_VALUE], cpuTemperatureBuffer, len); + } + #endif +} + +static void AllCPUsMeter_getRange(const Meter* this, int* start, int* count) { + const CPUMeterData* data = this->meterData; + unsigned int cpus = data->cpus; + switch(Meter_name(this)[0]) { + default: + case 'A': // All + *start = 0; + *count = cpus; + break; + case 'L': // First Half + *start = 0; + *count = (cpus+1) / 2; + break; + case 'R': // Second Half + *start = (cpus+1) / 2; + *count = cpus / 2; + break; + } +} + +static void AllCPUsMeter_updateValues(Meter* this) { + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + for (int i = 0; i < count; i++) + Meter_updateValues(meters[i]); +} + +static void CPUMeterCommonInit(Meter* this, int ncol) { + unsigned int cpus = this->pl->cpuCount; + CPUMeterData* data = this->meterData; + if (!data) { + data = this->meterData = xMalloc(sizeof(CPUMeterData)); + data->cpus = cpus; + data->meters = xCalloc(cpus, sizeof(Meter*)); + } + Meter** meters = data->meters; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + for (int i = 0; i < count; i++) { + if (!meters[i]) + meters[i] = Meter_new(this->pl, start + i + 1, (const MeterClass*) Class(CPUMeter)); + + Meter_init(meters[i]); + } + + if (this->mode == 0) + this->mode = BAR_METERMODE; + + int h = Meter_modes[this->mode]->h; + this->h = h * ((count + ncol - 1) / ncol); +} + +static void CPUMeterCommonUpdateMode(Meter* this, int mode, int ncol) { + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; + this->mode = mode; + int h = Meter_modes[mode]->h; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + for (int i = 0; i < count; i++) { + Meter_setMode(meters[i], mode); + } + this->h = h * ((count + ncol - 1) / ncol); +} + +static void AllCPUsMeter_done(Meter* this) { + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + for (int i = 0; i < count; i++) + Meter_delete((Object*)meters[i]); + free(data->meters); + free(data); +} + +static void SingleColCPUsMeter_init(Meter* this) { + CPUMeterCommonInit(this, 1); +} + +static void SingleColCPUsMeter_updateMode(Meter* this, int mode) { + CPUMeterCommonUpdateMode(this, mode, 1); +} + +static void DualColCPUsMeter_init(Meter* this) { + CPUMeterCommonInit(this, 2); +} + +static void DualColCPUsMeter_updateMode(Meter* this, int mode) { + CPUMeterCommonUpdateMode(this, mode, 2); +} + +static void QuadColCPUsMeter_init(Meter* this) { + CPUMeterCommonInit(this, 4); +} + +static void QuadColCPUsMeter_updateMode(Meter* this, int mode) { + CPUMeterCommonUpdateMode(this, mode, 4); +} + +static void OctoColCPUsMeter_init(Meter* this) { + CPUMeterCommonInit(this, 8); +} + +static void OctoColCPUsMeter_updateMode(Meter* this, int mode) { + CPUMeterCommonUpdateMode(this, mode, 8); +} + +static void CPUMeterCommonDraw(Meter* this, int x, int y, int w, int ncol) { + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + int colwidth = (w - ncol) / ncol + 1; + int diff = (w - (colwidth * ncol)); + int nrows = (count + ncol - 1) / ncol; + for (int i = 0; i < count; i++) { + int d = (i / nrows) > diff ? diff : (i / nrows); // dynamic spacer + int xpos = x + ((i / nrows) * colwidth) + d; + int ypos = y + ((i % nrows) * meters[0]->h); + meters[i]->draw(meters[i], xpos, ypos, colwidth); + } +} + +static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) { + CPUMeterCommonDraw(this, x, y, w, 2); +} + +static void QuadColCPUsMeter_draw(Meter* this, int x, int y, int w) { + CPUMeterCommonDraw(this, x, y, w, 4); +} + +static void OctoColCPUsMeter_draw(Meter* this, int x, int y, int w) { + CPUMeterCommonDraw(this, x, y, w, 8); +} + + +static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) { + CPUMeterData* data = this->meterData; + Meter** meters = data->meters; + int start, count; + AllCPUsMeter_getRange(this, &start, &count); + for (int i = 0; i < count; i++) { + meters[i]->draw(meters[i], x, y, w); + y += meters[i]->h; + } +} + + +const MeterClass CPUMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = CPUMeter_updateValues, + .getUiName = CPUMeter_getUiName, + .defaultMode = BAR_METERMODE, + .maxItems = CPU_METER_ITEMCOUNT, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "CPU", + .uiName = "CPU", + .caption = "CPU", + .init = CPUMeter_init +}; + +const MeterClass AllCPUsMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "AllCPUs", + .uiName = "CPUs (1/1)", + .description = "CPUs (1/1): all CPUs", + .caption = "CPU", + .draw = SingleColCPUsMeter_draw, + .init = SingleColCPUsMeter_init, + .updateMode = SingleColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass AllCPUs2Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "AllCPUs2", + .uiName = "CPUs (1&2/2)", + .description = "CPUs (1&2/2): all CPUs in 2 shorter columns", + .caption = "CPU", + .draw = DualColCPUsMeter_draw, + .init = DualColCPUsMeter_init, + .updateMode = DualColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass LeftCPUsMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "LeftCPUs", + .uiName = "CPUs (1/2)", + .description = "CPUs (1/2): first half of list", + .caption = "CPU", + .draw = SingleColCPUsMeter_draw, + .init = SingleColCPUsMeter_init, + .updateMode = SingleColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass RightCPUsMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "RightCPUs", + .uiName = "CPUs (2/2)", + .description = "CPUs (2/2): second half of list", + .caption = "CPU", + .draw = SingleColCPUsMeter_draw, + .init = SingleColCPUsMeter_init, + .updateMode = SingleColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass LeftCPUs2Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "LeftCPUs2", + .uiName = "CPUs (1&2/4)", + .description = "CPUs (1&2/4): first half in 2 shorter columns", + .caption = "CPU", + .draw = DualColCPUsMeter_draw, + .init = DualColCPUsMeter_init, + .updateMode = DualColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass RightCPUs2Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "RightCPUs2", + .uiName = "CPUs (3&4/4)", + .description = "CPUs (3&4/4): second half in 2 shorter columns", + .caption = "CPU", + .draw = DualColCPUsMeter_draw, + .init = DualColCPUsMeter_init, + .updateMode = DualColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass AllCPUs4Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "AllCPUs4", + .uiName = "CPUs (1&2&3&4/4)", + .description = "CPUs (1&2&3&4/4): all CPUs in 4 shorter columns", + .caption = "CPU", + .draw = QuadColCPUsMeter_draw, + .init = QuadColCPUsMeter_init, + .updateMode = QuadColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass LeftCPUs4Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "LeftCPUs4", + .uiName = "CPUs (1-4/8)", + .description = "CPUs (1-4/8): first half in 4 shorter columns", + .caption = "CPU", + .draw = QuadColCPUsMeter_draw, + .init = QuadColCPUsMeter_init, + .updateMode = QuadColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass RightCPUs4Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "RightCPUs4", + .uiName = "CPUs (5-8/8)", + .description = "CPUs (5-8/8): second half in 4 shorter columns", + .caption = "CPU", + .draw = QuadColCPUsMeter_draw, + .init = QuadColCPUsMeter_init, + .updateMode = QuadColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass AllCPUs8Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "AllCPUs8", + .uiName = "CPUs (1-8/8)", + .description = "CPUs (1-8/8): all CPUs in 8 shorter columns", + .caption = "CPU", + .draw = OctoColCPUsMeter_draw, + .init = OctoColCPUsMeter_init, + .updateMode = OctoColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass LeftCPUs8Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "LeftCPUs8", + .uiName = "CPUs (1-8/16)", + .description = "CPUs (1-8/16): first half in 8 shorter columns", + .caption = "CPU", + .draw = OctoColCPUsMeter_draw, + .init = OctoColCPUsMeter_init, + .updateMode = OctoColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; + +const MeterClass RightCPUs8Meter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = CPUMeter_display + }, + .updateValues = AllCPUsMeter_updateValues, + .defaultMode = CUSTOM_METERMODE, + .total = 100.0, + .attributes = CPUMeter_attributes, + .name = "RightCPUs8", + .uiName = "CPUs (9-16/16)", + .description = "CPUs (9-16/16): second half in 8 shorter columns", + .caption = "CPU", + .draw = OctoColCPUsMeter_draw, + .init = OctoColCPUsMeter_init, + .updateMode = OctoColCPUsMeter_updateMode, + .done = AllCPUsMeter_done +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CPUMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/CPUMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CPUMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CPUMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,53 @@ +#ifndef HEADER_CPUMeter +#define HEADER_CPUMeter +/* +htop - CPUMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +typedef enum { + CPU_METER_NICE = 0, + CPU_METER_NORMAL = 1, + CPU_METER_KERNEL = 2, + CPU_METER_IRQ = 3, + CPU_METER_SOFTIRQ = 4, + CPU_METER_STEAL = 5, + CPU_METER_GUEST = 6, + CPU_METER_IOWAIT = 7, + CPU_METER_FREQUENCY = 8, + CPU_METER_TEMPERATURE = 9, + CPU_METER_ITEMCOUNT = 10, // number of entries in this enum +} CPUMeterValues; + +extern const MeterClass CPUMeter_class; + +extern const MeterClass AllCPUsMeter_class; + +extern const MeterClass AllCPUs2Meter_class; + +extern const MeterClass LeftCPUsMeter_class; + +extern const MeterClass RightCPUsMeter_class; + +extern const MeterClass LeftCPUs2Meter_class; + +extern const MeterClass RightCPUs2Meter_class; + +extern const MeterClass AllCPUs4Meter_class; + +extern const MeterClass LeftCPUs4Meter_class; + +extern const MeterClass RightCPUs4Meter_class; + +extern const MeterClass AllCPUs8Meter_class; + +extern const MeterClass LeftCPUs8Meter_class; + +extern const MeterClass RightCPUs8Meter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CRT.c pcp-5.3.2/vendor/github.com/htop-dev/htop/CRT.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CRT.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CRT.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,1083 @@ +/* +htop - CRT.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "CRT.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "ProvideCurses.h" +#include "XUtils.h" + +#ifdef HAVE_EXECINFO_H +#include +#endif + +#if !defined(NDEBUG) && defined(HAVE_MEMFD_CREATE) +#include +#endif + + +#define ColorIndex(i,j) ((7-(i))*8+(j)) + +#define ColorPair(i,j) COLOR_PAIR(ColorIndex(i,j)) + +#define Black COLOR_BLACK +#define Red COLOR_RED +#define Green COLOR_GREEN +#define Yellow COLOR_YELLOW +#define Blue COLOR_BLUE +#define Magenta COLOR_MAGENTA +#define Cyan COLOR_CYAN +#define White COLOR_WHITE + +#define ColorPairGrayBlack ColorPair(Magenta,Magenta) +#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta) + +#define ColorPairWhiteDefault ColorPair(Red, Red) +#define ColorIndexWhiteDefault ColorIndex(Red, Red) + +static const char* const CRT_treeStrAscii[LAST_TREE_STR] = { + [TREE_STR_VERT] = "|", + [TREE_STR_RTEE] = "`", + [TREE_STR_BEND] = "`", + [TREE_STR_TEND] = ",", + [TREE_STR_OPEN] = "+", + [TREE_STR_SHUT] = "-", + [TREE_STR_ASC] = "+", + [TREE_STR_DESC] = "-", +}; + +#ifdef HAVE_LIBNCURSESW + +static const char* const CRT_treeStrUtf8[LAST_TREE_STR] = { + [TREE_STR_VERT] = "\xe2\x94\x82", // │ + [TREE_STR_RTEE] = "\xe2\x94\x9c", // ├ + [TREE_STR_BEND] = "\xe2\x94\x94", // └ + [TREE_STR_TEND] = "\xe2\x94\x8c", // ┌ + [TREE_STR_OPEN] = "+", // +, TODO use 🮯 'BOX DRAWINGS LIGHT HORIZONTAL + // WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when + // Unicode 13 is common + [TREE_STR_SHUT] = "\xe2\x94\x80", // ─ + [TREE_STR_ASC] = "\xe2\x96\xb3", // △ + [TREE_STR_DESC] = "\xe2\x96\xbd", // ▽ +}; + +bool CRT_utf8 = false; + +#endif + +const char* const* CRT_treeStr = CRT_treeStrAscii; + +static const Settings* CRT_crashSettings; +static const int* CRT_delay; + +const char* CRT_degreeSign; + +static const char* initDegreeSign(void) { +#ifdef HAVE_LIBNCURSESW + if (CRT_utf8) + return "\xc2\xb0"; + + static char buffer[4]; + // this might fail if the current locale does not support wide characters + int r = snprintf(buffer, sizeof(buffer), "%lc", 176); + if (r > 0) + return buffer; +#endif + + return ""; +} + +const int* CRT_colors; + +static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [COLORSCHEME_DEFAULT] = { + [RESET_COLOR] = ColorPair(White, Black), + [DEFAULT_COLOR] = ColorPair(White, Black), + [FUNCTION_BAR] = ColorPair(Black, Cyan), + [FUNCTION_KEY] = ColorPair(White, Black), + [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), + [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), + [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), + [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), + [PANEL_SELECTION_UNFOCUS] = ColorPair(Black, White), + [FAILED_SEARCH] = ColorPair(Red, Cyan), + [FAILED_READ] = A_BOLD | ColorPair(Red, Black), + [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), + [UPTIME] = A_BOLD | ColorPair(Cyan, Black), + [BATTERY] = A_BOLD | ColorPair(Cyan, Black), + [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), + [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, + [METER_TEXT] = ColorPair(Cyan, Black), + [METER_VALUE] = A_BOLD | ColorPair(Cyan, Black), + [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black), + [METER_VALUE_IOREAD] = ColorPair(Green, Black), + [METER_VALUE_IOWRITE] = ColorPair(Blue, Black), + [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black), + [METER_VALUE_OK] = ColorPair(Green, Black), + [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), + [LED_COLOR] = ColorPair(Green, Black), + [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black), + [PROCESS] = A_NORMAL, + [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack, + [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Black), + [PROCESS_MEGABYTES] = ColorPair(Cyan, Black), + [PROCESS_GIGABYTES] = ColorPair(Green, Black), + [PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Black), + [PROCESS_TREE] = ColorPair(Cyan, Black), + [PROCESS_R_STATE] = ColorPair(Green, Black), + [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), + [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), + [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), + [PROCESS_NEW] = ColorPair(Black, Green), + [PROCESS_TOMB] = ColorPair(Black, Red), + [PROCESS_THREAD] = ColorPair(Green, Black), + [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Black), + [PROCESS_COMM] = ColorPair(Magenta, Black), + [PROCESS_THREAD_COMM] = ColorPair(Blue, Black), + [BAR_BORDER] = A_BOLD, + [BAR_SHADOW] = A_BOLD | ColorPairGrayBlack, + [SWAP] = ColorPair(Red, Black), + [SWAP_CACHE] = ColorPair(Yellow, Black), + [GRAPH_1] = A_BOLD | ColorPair(Cyan, Black), + [GRAPH_2] = ColorPair(Cyan, Black), + [MEMORY_USED] = ColorPair(Green, Black), + [MEMORY_BUFFERS] = ColorPair(Blue, Black), + [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black), + [MEMORY_CACHE] = ColorPair(Yellow, Black), + [MEMORY_SHARED] = ColorPair(Magenta, Black), + [HUGEPAGE_1] = ColorPair(Green, Black), + [HUGEPAGE_2] = ColorPair(Yellow, Black), + [HUGEPAGE_3] = ColorPair(Red, Black), + [HUGEPAGE_4] = ColorPair(Blue, Black), + [LOAD_AVERAGE_FIFTEEN] = ColorPair(Cyan, Black), + [LOAD_AVERAGE_FIVE] = A_BOLD | ColorPair(Cyan, Black), + [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Black), + [LOAD] = A_BOLD, + [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Black), + [HELP_SHADOW] = A_BOLD | ColorPairGrayBlack, + [CLOCK] = A_BOLD, + [DATE] = A_BOLD, + [DATETIME] = A_BOLD, + [CHECK_BOX] = ColorPair(Cyan, Black), + [CHECK_MARK] = A_BOLD, + [CHECK_TEXT] = A_NORMAL, + [HOSTNAME] = A_BOLD, + [CPU_NICE] = ColorPair(Blue, Black), + [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black), + [CPU_NORMAL] = ColorPair(Green, Black), + [CPU_SYSTEM] = ColorPair(Red, Black), + [CPU_IOWAIT] = A_BOLD | ColorPairGrayBlack, + [CPU_IRQ] = ColorPair(Yellow, Black), + [CPU_SOFTIRQ] = ColorPair(Magenta, Black), + [CPU_STEAL] = ColorPair(Cyan, Black), + [CPU_GUEST] = ColorPair(Cyan, Black), + [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Cyan, Black), + [PRESSURE_STALL_SIXTY] = A_BOLD | ColorPair(Cyan, Black), + [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Black), + [ZFS_MFU] = ColorPair(Blue, Black), + [ZFS_MRU] = ColorPair(Yellow, Black), + [ZFS_ANON] = ColorPair(Magenta, Black), + [ZFS_HEADER] = ColorPair(Cyan, Black), + [ZFS_OTHER] = ColorPair(Magenta, Black), + [ZFS_COMPRESSED] = ColorPair(Blue, Black), + [ZFS_RATIO] = ColorPair(Magenta, Black), + [ZRAM] = ColorPair(Yellow, Black), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Black), + [DYNAMIC_GREEN] = ColorPair(Green, Black), + [DYNAMIC_BLUE] = ColorPair(Blue, Black), + [DYNAMIC_CYAN] = ColorPair(Cyan, Black), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Black), + [DYNAMIC_WHITE] = ColorPair(White, Black), + }, + [COLORSCHEME_MONOCHROME] = { + [RESET_COLOR] = A_NORMAL, + [DEFAULT_COLOR] = A_NORMAL, + [FUNCTION_BAR] = A_REVERSE, + [FUNCTION_KEY] = A_NORMAL, + [PANEL_HEADER_FOCUS] = A_REVERSE, + [PANEL_HEADER_UNFOCUS] = A_REVERSE, + [PANEL_SELECTION_FOCUS] = A_REVERSE, + [PANEL_SELECTION_FOLLOW] = A_REVERSE, + [PANEL_SELECTION_UNFOCUS] = A_BOLD, + [FAILED_SEARCH] = A_REVERSE | A_BOLD, + [FAILED_READ] = A_BOLD, + [PAUSED] = A_BOLD | A_REVERSE, + [UPTIME] = A_BOLD, + [BATTERY] = A_BOLD, + [LARGE_NUMBER] = A_BOLD, + [METER_SHADOW] = A_DIM, + [METER_TEXT] = A_NORMAL, + [METER_VALUE] = A_BOLD, + [METER_VALUE_ERROR] = A_BOLD, + [METER_VALUE_IOREAD] = A_NORMAL, + [METER_VALUE_IOWRITE] = A_NORMAL, + [METER_VALUE_NOTICE] = A_BOLD, + [METER_VALUE_OK] = A_NORMAL, + [METER_VALUE_WARN] = A_BOLD, + [LED_COLOR] = A_NORMAL, + [TASKS_RUNNING] = A_BOLD, + [PROCESS] = A_NORMAL, + [PROCESS_SHADOW] = A_DIM, + [PROCESS_TAG] = A_BOLD, + [PROCESS_MEGABYTES] = A_BOLD, + [PROCESS_GIGABYTES] = A_BOLD, + [PROCESS_BASENAME] = A_BOLD, + [PROCESS_TREE] = A_BOLD, + [PROCESS_R_STATE] = A_BOLD, + [PROCESS_D_STATE] = A_BOLD, + [PROCESS_HIGH_PRIORITY] = A_BOLD, + [PROCESS_LOW_PRIORITY] = A_DIM, + [PROCESS_NEW] = A_BOLD, + [PROCESS_TOMB] = A_DIM, + [PROCESS_THREAD] = A_BOLD, + [PROCESS_THREAD_BASENAME] = A_REVERSE, + [PROCESS_COMM] = A_BOLD, + [PROCESS_THREAD_COMM] = A_REVERSE, + [BAR_BORDER] = A_BOLD, + [BAR_SHADOW] = A_DIM, + [SWAP] = A_BOLD, + [SWAP_CACHE] = A_NORMAL, + [GRAPH_1] = A_BOLD, + [GRAPH_2] = A_NORMAL, + [MEMORY_USED] = A_BOLD, + [MEMORY_BUFFERS] = A_NORMAL, + [MEMORY_BUFFERS_TEXT] = A_NORMAL, + [MEMORY_CACHE] = A_NORMAL, + [MEMORY_SHARED] = A_NORMAL, + [HUGEPAGE_1] = A_BOLD, + [HUGEPAGE_2] = A_NORMAL, + [HUGEPAGE_3] = A_REVERSE | A_BOLD, + [HUGEPAGE_4] = A_REVERSE, + [LOAD_AVERAGE_FIFTEEN] = A_DIM, + [LOAD_AVERAGE_FIVE] = A_NORMAL, + [LOAD_AVERAGE_ONE] = A_BOLD, + [LOAD] = A_BOLD, + [HELP_BOLD] = A_BOLD, + [HELP_SHADOW] = A_DIM, + [CLOCK] = A_BOLD, + [DATE] = A_BOLD, + [DATETIME] = A_BOLD, + [CHECK_BOX] = A_BOLD, + [CHECK_MARK] = A_NORMAL, + [CHECK_TEXT] = A_NORMAL, + [HOSTNAME] = A_BOLD, + [CPU_NICE] = A_NORMAL, + [CPU_NICE_TEXT] = A_NORMAL, + [CPU_NORMAL] = A_BOLD, + [CPU_SYSTEM] = A_BOLD, + [CPU_IOWAIT] = A_NORMAL, + [CPU_IRQ] = A_BOLD, + [CPU_SOFTIRQ] = A_BOLD, + [CPU_STEAL] = A_DIM, + [CPU_GUEST] = A_DIM, + [PRESSURE_STALL_THREEHUNDRED] = A_DIM, + [PRESSURE_STALL_SIXTY] = A_NORMAL, + [PRESSURE_STALL_TEN] = A_BOLD, + [ZFS_MFU] = A_NORMAL, + [ZFS_MRU] = A_NORMAL, + [ZFS_ANON] = A_DIM, + [ZFS_HEADER] = A_BOLD, + [ZFS_OTHER] = A_DIM, + [ZFS_COMPRESSED] = A_BOLD, + [ZFS_RATIO] = A_BOLD, + [ZRAM] = A_NORMAL, + [DYNAMIC_GRAY] = A_DIM, + [DYNAMIC_DARKGRAY] = A_DIM, + [DYNAMIC_RED] = A_BOLD, + [DYNAMIC_GREEN] = A_NORMAL, + [DYNAMIC_BLUE] = A_NORMAL, + [DYNAMIC_CYAN] = A_BOLD, + [DYNAMIC_MAGENTA] = A_NORMAL, + [DYNAMIC_YELLOW] = A_NORMAL, + [DYNAMIC_WHITE] = A_BOLD, + }, + [COLORSCHEME_BLACKONWHITE] = { + [RESET_COLOR] = ColorPair(Black, White), + [DEFAULT_COLOR] = ColorPair(Black, White), + [FUNCTION_BAR] = ColorPair(Black, Cyan), + [FUNCTION_KEY] = ColorPair(Black, White), + [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), + [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), + [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), + [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), + [PANEL_SELECTION_UNFOCUS] = ColorPair(Blue, White), + [FAILED_SEARCH] = ColorPair(Red, Cyan), + [FAILED_READ] = ColorPair(Red, White), + [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), + [UPTIME] = ColorPair(Yellow, White), + [BATTERY] = ColorPair(Yellow, White), + [LARGE_NUMBER] = ColorPair(Red, White), + [METER_SHADOW] = ColorPair(Blue, White), + [METER_TEXT] = ColorPair(Blue, White), + [METER_VALUE] = ColorPair(Black, White), + [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, White), + [METER_VALUE_IOREAD] = ColorPair(Green, White), + [METER_VALUE_IOWRITE] = ColorPair(Yellow, White), + [METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, White), + [METER_VALUE_OK] = ColorPair(Green, White), + [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, White), + [LED_COLOR] = ColorPair(Green, White), + [TASKS_RUNNING] = ColorPair(Green, White), + [PROCESS] = ColorPair(Black, White), + [PROCESS_SHADOW] = A_BOLD | ColorPair(Black, White), + [PROCESS_TAG] = ColorPair(White, Blue), + [PROCESS_MEGABYTES] = ColorPair(Blue, White), + [PROCESS_GIGABYTES] = ColorPair(Green, White), + [PROCESS_BASENAME] = ColorPair(Blue, White), + [PROCESS_TREE] = ColorPair(Green, White), + [PROCESS_R_STATE] = ColorPair(Green, White), + [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White), + [PROCESS_HIGH_PRIORITY] = ColorPair(Red, White), + [PROCESS_LOW_PRIORITY] = ColorPair(Green, White), + [PROCESS_NEW] = ColorPair(White, Green), + [PROCESS_TOMB] = ColorPair(White, Red), + [PROCESS_THREAD] = ColorPair(Blue, White), + [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, White), + [PROCESS_COMM] = ColorPair(Magenta, White), + [PROCESS_THREAD_COMM] = ColorPair(Green, White), + [BAR_BORDER] = ColorPair(Blue, White), + [BAR_SHADOW] = ColorPair(Black, White), + [SWAP] = ColorPair(Red, White), + [SWAP_CACHE] = ColorPair(Yellow, White), + [GRAPH_1] = A_BOLD | ColorPair(Blue, White), + [GRAPH_2] = ColorPair(Blue, White), + [MEMORY_USED] = ColorPair(Green, White), + [MEMORY_BUFFERS] = ColorPair(Cyan, White), + [MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, White), + [MEMORY_CACHE] = ColorPair(Yellow, White), + [MEMORY_SHARED] = ColorPair(Magenta, White), + [HUGEPAGE_1] = ColorPair(Green, White), + [HUGEPAGE_2] = ColorPair(Yellow, White), + [HUGEPAGE_3] = ColorPair(Red, White), + [HUGEPAGE_4] = ColorPair(Blue, White), + [LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, White), + [LOAD_AVERAGE_FIVE] = ColorPair(Black, White), + [LOAD_AVERAGE_ONE] = ColorPair(Black, White), + [LOAD] = ColorPair(Black, White), + [HELP_BOLD] = ColorPair(Blue, White), + [HELP_SHADOW] = A_BOLD | ColorPair(Black, White), + [CLOCK] = ColorPair(Black, White), + [DATE] = ColorPair(Black, White), + [DATETIME] = ColorPair(Black, White), + [CHECK_BOX] = ColorPair(Blue, White), + [CHECK_MARK] = ColorPair(Black, White), + [CHECK_TEXT] = ColorPair(Black, White), + [HOSTNAME] = ColorPair(Black, White), + [CPU_NICE] = ColorPair(Cyan, White), + [CPU_NICE_TEXT] = ColorPair(Cyan, White), + [CPU_NORMAL] = ColorPair(Green, White), + [CPU_SYSTEM] = ColorPair(Red, White), + [CPU_IOWAIT] = A_BOLD | ColorPair(Black, White), + [CPU_IRQ] = ColorPair(Blue, White), + [CPU_SOFTIRQ] = ColorPair(Blue, White), + [CPU_STEAL] = ColorPair(Cyan, White), + [CPU_GUEST] = ColorPair(Cyan, White), + [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, White), + [PRESSURE_STALL_SIXTY] = ColorPair(Black, White), + [PRESSURE_STALL_TEN] = ColorPair(Black, White), + [ZFS_MFU] = ColorPair(Cyan, White), + [ZFS_MRU] = ColorPair(Yellow, White), + [ZFS_ANON] = ColorPair(Magenta, White), + [ZFS_HEADER] = ColorPair(Yellow, White), + [ZFS_OTHER] = ColorPair(Magenta, White), + [ZFS_COMPRESSED] = ColorPair(Cyan, White), + [ZFS_RATIO] = ColorPair(Magenta, White), + [ZRAM] = ColorPair(Yellow, White), + [DYNAMIC_GRAY] = ColorPair(Black, White), + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPair(Black, White), + [DYNAMIC_RED] = ColorPair(Red, White), + [DYNAMIC_GREEN] = ColorPair(Green, White), + [DYNAMIC_BLUE] = ColorPair(Blue, White), + [DYNAMIC_CYAN] = ColorPair(Yellow, White), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, White), + [DYNAMIC_YELLOW] = ColorPair(Yellow, White), + [DYNAMIC_WHITE] = A_BOLD | ColorPair(Black, White), + }, + [COLORSCHEME_LIGHTTERMINAL] = { + [RESET_COLOR] = ColorPair(Black, Black), + [DEFAULT_COLOR] = ColorPair(Black, Black), + [FUNCTION_BAR] = ColorPair(Black, Cyan), + [FUNCTION_KEY] = ColorPair(Black, Black), + [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), + [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), + [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), + [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), + [PANEL_SELECTION_UNFOCUS] = ColorPair(Blue, Black), + [FAILED_SEARCH] = ColorPair(Red, Cyan), + [FAILED_READ] = ColorPair(Red, Black), + [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), + [UPTIME] = ColorPair(Yellow, Black), + [BATTERY] = ColorPair(Yellow, Black), + [LARGE_NUMBER] = ColorPair(Red, Black), + [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, + [METER_TEXT] = ColorPair(Blue, Black), + [METER_VALUE] = ColorPair(Black, Black), + [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black), + [METER_VALUE_IOREAD] = ColorPair(Green, Black), + [METER_VALUE_IOWRITE] = ColorPair(Yellow, Black), + [METER_VALUE_NOTICE] = A_BOLD | ColorPairWhiteDefault, + [METER_VALUE_OK] = ColorPair(Green, Black), + [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), + [LED_COLOR] = ColorPair(Green, Black), + [TASKS_RUNNING] = ColorPair(Green, Black), + [PROCESS] = ColorPair(Black, Black), + [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack, + [PROCESS_TAG] = ColorPair(White, Blue), + [PROCESS_MEGABYTES] = ColorPair(Blue, Black), + [PROCESS_GIGABYTES] = ColorPair(Green, Black), + [PROCESS_BASENAME] = ColorPair(Green, Black), + [PROCESS_TREE] = ColorPair(Blue, Black), + [PROCESS_R_STATE] = ColorPair(Green, Black), + [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), + [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), + [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), + [PROCESS_NEW] = ColorPair(Black, Green), + [PROCESS_TOMB] = ColorPair(Black, Red), + [PROCESS_THREAD] = ColorPair(Blue, Black), + [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black), + [PROCESS_COMM] = ColorPair(Magenta, Black), + [PROCESS_THREAD_COMM] = ColorPair(Yellow, Black), + [BAR_BORDER] = ColorPair(Blue, Black), + [BAR_SHADOW] = ColorPairGrayBlack, + [SWAP] = ColorPair(Red, Black), + [SWAP_CACHE] = ColorPair(Yellow, Black), + [GRAPH_1] = A_BOLD | ColorPair(Cyan, Black), + [GRAPH_2] = ColorPair(Cyan, Black), + [MEMORY_USED] = ColorPair(Green, Black), + [MEMORY_BUFFERS] = ColorPair(Cyan, Black), + [MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, Black), + [MEMORY_CACHE] = ColorPair(Yellow, Black), + [MEMORY_SHARED] = ColorPair(Magenta, Black), + [HUGEPAGE_1] = ColorPair(Green, Black), + [HUGEPAGE_2] = ColorPair(Yellow, Black), + [HUGEPAGE_3] = ColorPair(Red, Black), + [HUGEPAGE_4] = ColorPair(Blue, Black), + [LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, Black), + [LOAD_AVERAGE_FIVE] = ColorPair(Black, Black), + [LOAD_AVERAGE_ONE] = ColorPair(Black, Black), + [LOAD] = ColorPairWhiteDefault, + [HELP_BOLD] = ColorPair(Blue, Black), + [HELP_SHADOW] = A_BOLD | ColorPairGrayBlack, + [CLOCK] = ColorPairWhiteDefault, + [DATE] = ColorPairWhiteDefault, + [DATETIME] = ColorPairWhiteDefault, + [CHECK_BOX] = ColorPair(Blue, Black), + [CHECK_MARK] = ColorPair(Black, Black), + [CHECK_TEXT] = ColorPair(Black, Black), + [HOSTNAME] = ColorPairWhiteDefault, + [CPU_NICE] = ColorPair(Cyan, Black), + [CPU_NICE_TEXT] = ColorPair(Cyan, Black), + [CPU_NORMAL] = ColorPair(Green, Black), + [CPU_SYSTEM] = ColorPair(Red, Black), + [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black), + [CPU_IRQ] = A_BOLD | ColorPair(Blue, Black), + [CPU_SOFTIRQ] = ColorPair(Blue, Black), + [CPU_STEAL] = ColorPair(Black, Black), + [CPU_GUEST] = ColorPair(Black, Black), + [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black), + [PRESSURE_STALL_SIXTY] = ColorPair(Black, Black), + [PRESSURE_STALL_TEN] = ColorPair(Black, Black), + [ZFS_MFU] = ColorPair(Cyan, Black), + [ZFS_MRU] = ColorPair(Yellow, Black), + [ZFS_ANON] = A_BOLD | ColorPair(Magenta, Black), + [ZFS_HEADER] = ColorPair(Black, Black), + [ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Black), + [ZFS_COMPRESSED] = ColorPair(Cyan, Black), + [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black), + [ZRAM] = ColorPair(Yellow, Black), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Black), + [DYNAMIC_GREEN] = ColorPair(Green, Black), + [DYNAMIC_BLUE] = ColorPair(Blue, Black), + [DYNAMIC_CYAN] = ColorPair(Cyan, Black), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Black), + [DYNAMIC_WHITE] = ColorPairWhiteDefault, + }, + [COLORSCHEME_MIDNIGHT] = { + [RESET_COLOR] = ColorPair(White, Blue), + [DEFAULT_COLOR] = ColorPair(White, Blue), + [FUNCTION_BAR] = ColorPair(Black, Cyan), + [FUNCTION_KEY] = A_NORMAL, + [PANEL_HEADER_FOCUS] = ColorPair(Black, Cyan), + [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Cyan), + [PANEL_SELECTION_FOCUS] = ColorPair(Black, White), + [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), + [PANEL_SELECTION_UNFOCUS] = A_BOLD | ColorPair(Yellow, Blue), + [FAILED_SEARCH] = ColorPair(Red, Cyan), + [FAILED_READ] = A_BOLD | ColorPair(Red, Blue), + [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan), + [UPTIME] = A_BOLD | ColorPair(Yellow, Blue), + [BATTERY] = A_BOLD | ColorPair(Yellow, Blue), + [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Blue), + [METER_SHADOW] = ColorPair(Cyan, Blue), + [METER_TEXT] = ColorPair(Cyan, Blue), + [METER_VALUE] = A_BOLD | ColorPair(Cyan, Blue), + [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Blue), + [METER_VALUE_IOREAD] = ColorPair(Green, Blue), + [METER_VALUE_IOWRITE] = ColorPair(Black, Blue), + [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Blue), + [METER_VALUE_OK] = ColorPair(Green, Blue), + [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), + [LED_COLOR] = ColorPair(Green, Blue), + [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Blue), + [PROCESS] = ColorPair(White, Blue), + [PROCESS_SHADOW] = A_BOLD | ColorPair(Black, Blue), + [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Blue), + [PROCESS_MEGABYTES] = ColorPair(Cyan, Blue), + [PROCESS_GIGABYTES] = ColorPair(Green, Blue), + [PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Blue), + [PROCESS_TREE] = ColorPair(Cyan, Blue), + [PROCESS_R_STATE] = ColorPair(Green, Blue), + [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue), + [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue), + [PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue), + [PROCESS_NEW] = ColorPair(Blue, Green), + [PROCESS_TOMB] = ColorPair(Blue, Red), + [PROCESS_THREAD] = ColorPair(Green, Blue), + [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Blue), + [PROCESS_COMM] = ColorPair(Magenta, Blue), + [PROCESS_THREAD_COMM] = ColorPair(Black, Blue), + [BAR_BORDER] = A_BOLD | ColorPair(Yellow, Blue), + [BAR_SHADOW] = ColorPair(Cyan, Blue), + [SWAP] = ColorPair(Red, Blue), + [SWAP_CACHE] = A_BOLD | ColorPair(Yellow, Blue), + [GRAPH_1] = A_BOLD | ColorPair(Cyan, Blue), + [GRAPH_2] = ColorPair(Cyan, Blue), + [MEMORY_USED] = A_BOLD | ColorPair(Green, Blue), + [MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan, Blue), + [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Cyan, Blue), + [MEMORY_CACHE] = A_BOLD | ColorPair(Yellow, Blue), + [MEMORY_SHARED] = A_BOLD | ColorPair(Magenta, Blue), + [HUGEPAGE_1] = A_BOLD | ColorPair(Green, Blue), + [HUGEPAGE_2] = A_BOLD | ColorPair(Yellow, Blue), + [HUGEPAGE_3] = A_BOLD | ColorPair(Red, Blue), + [HUGEPAGE_4] = A_BOLD | ColorPair(White, Blue), + [LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black, Blue), + [LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White, Blue), + [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Blue), + [LOAD] = A_BOLD | ColorPair(White, Blue), + [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Blue), + [HELP_SHADOW] = A_BOLD | ColorPair(Black, Blue), + [CLOCK] = ColorPair(White, Blue), + [DATE] = ColorPair(White, Blue), + [DATETIME] = ColorPair(White, Blue), + [CHECK_BOX] = ColorPair(Cyan, Blue), + [CHECK_MARK] = A_BOLD | ColorPair(White, Blue), + [CHECK_TEXT] = A_NORMAL | ColorPair(White, Blue), + [HOSTNAME] = ColorPair(White, Blue), + [CPU_NICE] = A_BOLD | ColorPair(Cyan, Blue), + [CPU_NICE_TEXT] = A_BOLD | ColorPair(Cyan, Blue), + [CPU_NORMAL] = A_BOLD | ColorPair(Green, Blue), + [CPU_SYSTEM] = A_BOLD | ColorPair(Red, Blue), + [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Blue), + [CPU_IRQ] = A_BOLD | ColorPair(Black, Blue), + [CPU_SOFTIRQ] = ColorPair(Black, Blue), + [CPU_STEAL] = ColorPair(White, Blue), + [CPU_GUEST] = ColorPair(White, Blue), + [PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black, Blue), + [PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White, Blue), + [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Blue), + [ZFS_MFU] = A_BOLD | ColorPair(White, Blue), + [ZFS_MRU] = A_BOLD | ColorPair(Yellow, Blue), + [ZFS_ANON] = A_BOLD | ColorPair(Magenta, Blue), + [ZFS_HEADER] = A_BOLD | ColorPair(Yellow, Blue), + [ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Blue), + [ZFS_COMPRESSED] = A_BOLD | ColorPair(White, Blue), + [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Blue), + [ZRAM] = A_BOLD | ColorPair(Yellow, Blue), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Blue), + [DYNAMIC_GREEN] = ColorPair(Green, Blue), + [DYNAMIC_BLUE] = ColorPair(Black, Blue), + [DYNAMIC_CYAN] = ColorPair(Cyan, Blue), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Blue), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Blue), + [DYNAMIC_WHITE] = ColorPair(White, Blue), + }, + [COLORSCHEME_BLACKNIGHT] = { + [RESET_COLOR] = ColorPair(Cyan, Black), + [DEFAULT_COLOR] = ColorPair(Cyan, Black), + [FUNCTION_BAR] = ColorPair(Black, Green), + [FUNCTION_KEY] = ColorPair(Cyan, Black), + [PANEL_HEADER_FOCUS] = ColorPair(Black, Green), + [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green), + [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan), + [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow), + [PANEL_SELECTION_UNFOCUS] = ColorPair(Black, White), + [FAILED_SEARCH] = ColorPair(Red, Green), + [FAILED_READ] = A_BOLD | ColorPair(Red, Black), + [PAUSED] = A_BOLD | ColorPair(Yellow, Green), + [UPTIME] = ColorPair(Green, Black), + [BATTERY] = ColorPair(Green, Black), + [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black), + [METER_SHADOW] = A_BOLD | ColorPairGrayBlack, + [METER_TEXT] = ColorPair(Cyan, Black), + [METER_VALUE] = ColorPair(Green, Black), + [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black), + [METER_VALUE_IOREAD] = ColorPair(Green, Black), + [METER_VALUE_IOWRITE] = ColorPair(Blue, Black), + [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black), + [METER_VALUE_OK] = ColorPair(Green, Black), + [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black), + [LED_COLOR] = ColorPair(Green, Black), + [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black), + [PROCESS] = ColorPair(Cyan, Black), + [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack, + [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Black), + [PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green, Black), + [PROCESS_GIGABYTES] = A_BOLD | ColorPair(Yellow, Black), + [PROCESS_BASENAME] = A_BOLD | ColorPair(Green, Black), + [PROCESS_TREE] = ColorPair(Cyan, Black), + [PROCESS_THREAD] = ColorPair(Green, Black), + [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black), + [PROCESS_COMM] = ColorPair(Magenta, Black), + [PROCESS_THREAD_COMM] = ColorPair(Yellow, Black), + [PROCESS_R_STATE] = ColorPair(Green, Black), + [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black), + [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black), + [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black), + [PROCESS_NEW] = ColorPair(Black, Green), + [PROCESS_TOMB] = ColorPair(Black, Red), + [BAR_BORDER] = A_BOLD | ColorPair(Green, Black), + [BAR_SHADOW] = ColorPair(Cyan, Black), + [SWAP] = ColorPair(Red, Black), + [SWAP_CACHE] = ColorPair(Yellow, Black), + [GRAPH_1] = A_BOLD | ColorPair(Green, Black), + [GRAPH_2] = ColorPair(Green, Black), + [MEMORY_USED] = ColorPair(Green, Black), + [MEMORY_BUFFERS] = ColorPair(Blue, Black), + [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black), + [MEMORY_CACHE] = ColorPair(Yellow, Black), + [MEMORY_SHARED] = ColorPair(Magenta, Black), + [HUGEPAGE_1] = ColorPair(Green, Black), + [HUGEPAGE_2] = ColorPair(Yellow, Black), + [HUGEPAGE_3] = ColorPair(Red, Black), + [HUGEPAGE_4] = ColorPair(Blue, Black), + [LOAD_AVERAGE_FIFTEEN] = ColorPair(Green, Black), + [LOAD_AVERAGE_FIVE] = ColorPair(Green, Black), + [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(Green, Black), + [LOAD] = A_BOLD, + [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Black), + [HELP_SHADOW] = A_BOLD | ColorPairGrayBlack, + [CLOCK] = ColorPair(Green, Black), + [CHECK_BOX] = ColorPair(Green, Black), + [CHECK_MARK] = A_BOLD | ColorPair(Green, Black), + [CHECK_TEXT] = ColorPair(Cyan, Black), + [HOSTNAME] = ColorPair(Green, Black), + [CPU_NICE] = ColorPair(Blue, Black), + [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black), + [CPU_NORMAL] = ColorPair(Green, Black), + [CPU_SYSTEM] = ColorPair(Red, Black), + [CPU_IOWAIT] = ColorPair(Yellow, Black), + [CPU_IRQ] = A_BOLD | ColorPair(Blue, Black), + [CPU_SOFTIRQ] = ColorPair(Blue, Black), + [CPU_STEAL] = ColorPair(Cyan, Black), + [CPU_GUEST] = ColorPair(Cyan, Black), + [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green, Black), + [PRESSURE_STALL_SIXTY] = ColorPair(Green, Black), + [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green, Black), + [ZFS_MFU] = ColorPair(Blue, Black), + [ZFS_MRU] = ColorPair(Yellow, Black), + [ZFS_ANON] = ColorPair(Magenta, Black), + [ZFS_HEADER] = ColorPair(Yellow, Black), + [ZFS_OTHER] = ColorPair(Magenta, Black), + [ZFS_COMPRESSED] = ColorPair(Blue, Black), + [ZFS_RATIO] = ColorPair(Magenta, Black), + [ZRAM] = ColorPair(Yellow, Black), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Black), + [DYNAMIC_GREEN] = ColorPair(Green, Black), + [DYNAMIC_BLUE] = ColorPair(Blue, Black), + [DYNAMIC_CYAN] = ColorPair(Cyan, Black), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Black), + [DYNAMIC_WHITE] = ColorPair(White, Black), + }, + [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. +}; + +int CRT_cursorX = 0; + +int CRT_scrollHAmount = 5; + +int CRT_scrollWheelVAmount = 10; + +ColorScheme CRT_colorScheme = COLORSCHEME_DEFAULT; + +ATTR_NORETURN +static void CRT_handleSIGTERM(ATTR_UNUSED int sgn) { + CRT_done(); + _exit(0); +} + +#ifndef NDEBUG + +static int stderrRedirectNewFd = -1; +static int stderrRedirectBackupFd = -1; + +static int createStderrCacheFile(void) { +#if defined(HAVE_MEMFD_CREATE) + return memfd_create("htop.stderr-redirect", 0); +#elif defined(O_TMPFILE) + return open("/tmp", O_TMPFILE | O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); +#else + char tmpName[] = "htop.stderr-redirectXXXXXX"; + mode_t curUmask = umask(S_IXUSR | S_IRWXG | S_IRWXO); + int r = mkstemp(tmpName); + umask(curUmask); + if (r < 0) + return r; + + (void) unlink(tmpName); + + return r; +#endif /* HAVE_MEMFD_CREATE */ +} + +static void redirectStderr(void) { + stderrRedirectNewFd = createStderrCacheFile(); + if (stderrRedirectNewFd < 0) { + /* ignore failure */ + return; + } + + stderrRedirectBackupFd = dup(STDERR_FILENO); + dup2(stderrRedirectNewFd, STDERR_FILENO); +} + +static void dumpStderr(void) { + if (stderrRedirectNewFd < 0) + return; + + fsync(STDERR_FILENO); + dup2(stderrRedirectBackupFd, STDERR_FILENO); + lseek(stderrRedirectNewFd, 0, SEEK_SET); + + bool header = false; + char buffer[8192]; + for (;;) { + errno = 0; + ssize_t res = read(stderrRedirectNewFd, buffer, sizeof(buffer)); + if (res < 0) { + if (errno == EINTR) + continue; + + break; + } + + if (res == 0) { + break; + } + + if (res > 0) { + if (!header) { + fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n\n"); + header = true; + } + (void)! write(STDERR_FILENO, buffer, res); + } + } + + if (header) + fprintf(stderr, "\n<<<<<<<<<< stderr output <<<<<<<<<<\n"); + + close(stderrRedirectNewFd); + stderrRedirectNewFd = -1; +} + +#else /* !NDEBUG */ + +static void redirectStderr(void) { +} + +static void dumpStderr(void) { +} + +#endif /* !NDEBUG */ + +static struct sigaction old_sig_handler[32]; + +void CRT_init(const Settings* settings, bool allowUnicode) { + redirectStderr(); + + initscr(); + noecho(); + CRT_crashSettings = settings; + CRT_delay = &(settings->delay); + CRT_colors = CRT_colorSchemes[settings->colorScheme]; + CRT_colorScheme = settings->colorScheme; + + for (int i = 0; i < LAST_COLORELEMENT; i++) { + unsigned int color = CRT_colorSchemes[COLORSCHEME_DEFAULT][i]; + CRT_colorSchemes[COLORSCHEME_BROKENGRAY][i] = color == (A_BOLD | ColorPairGrayBlack) ? ColorPair(White, Black) : color; + } + + halfdelay(*CRT_delay); + nonl(); + intrflush(stdscr, false); + keypad(stdscr, true); +#ifdef HAVE_GETMOUSE + mouseinterval(0); +#endif + curs_set(0); + + if (has_colors()) { + start_color(); + } + + const char* termType = getenv("TERM"); + if (termType && String_eq(termType, "linux")) { + CRT_scrollHAmount = 20; + } else { + CRT_scrollHAmount = 5; + } + + if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220"))) { + define_key("\033[H", KEY_HOME); + define_key("\033[F", KEY_END); + define_key("\033[7~", KEY_HOME); + define_key("\033[8~", KEY_END); + define_key("\033OP", KEY_F(1)); + define_key("\033OQ", KEY_F(2)); + define_key("\033OR", KEY_F(3)); + define_key("\033OS", KEY_F(4)); + define_key("\033O2R", KEY_F(15)); + define_key("\033[11~", KEY_F(1)); + define_key("\033[12~", KEY_F(2)); + define_key("\033[13~", KEY_F(3)); + define_key("\033[14~", KEY_F(4)); + define_key("\033[14;2~", KEY_F(15)); + define_key("\033[17;2~", KEY_F(18)); + char sequence[3] = "\033a"; + for (char c = 'a'; c <= 'z'; c++) { + sequence[1] = c; + define_key(sequence, KEY_ALT('A' + (c - 'a'))); + } + } + + struct sigaction act; + sigemptyset (&act.sa_mask); + act.sa_flags = (int)SA_RESETHAND | SA_NODEFER; + act.sa_handler = CRT_handleSIGSEGV; + sigaction (SIGSEGV, &act, &old_sig_handler[SIGSEGV]); + sigaction (SIGFPE, &act, &old_sig_handler[SIGFPE]); + sigaction (SIGILL, &act, &old_sig_handler[SIGILL]); + sigaction (SIGBUS, &act, &old_sig_handler[SIGBUS]); + sigaction (SIGPIPE, &act, &old_sig_handler[SIGPIPE]); + sigaction (SIGSYS, &act, &old_sig_handler[SIGSYS]); + sigaction (SIGABRT, &act, &old_sig_handler[SIGABRT]); + + signal(SIGINT, CRT_handleSIGTERM); + signal(SIGTERM, CRT_handleSIGTERM); + signal(SIGQUIT, CRT_handleSIGTERM); + + use_default_colors(); + if (!has_colors()) + CRT_colorScheme = COLORSCHEME_MONOCHROME; + CRT_setColors(CRT_colorScheme); + +#ifdef HAVE_LIBNCURSESW + if (allowUnicode && String_eq(nl_langinfo(CODESET), "UTF-8")) { + CRT_utf8 = true; + } else { + CRT_utf8 = false; + } +#else + (void) allowUnicode; +#endif + + CRT_treeStr = +#ifdef HAVE_LIBNCURSESW + CRT_utf8 ? CRT_treeStrUtf8 : +#endif + CRT_treeStrAscii; + +#ifdef HAVE_GETMOUSE +#if NCURSES_MOUSE_VERSION > 1 + mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL); +#else + mousemask(BUTTON1_RELEASED, NULL); +#endif +#endif + + CRT_degreeSign = initDegreeSign(); +} + +void CRT_done() { + curs_set(1); + endwin(); + + dumpStderr(); +} + +void CRT_fatalError(const char* note) { + const char* sysMsg = strerror(errno); + CRT_done(); + fprintf(stderr, "%s: %s\n", note, sysMsg); + exit(2); +} + +int CRT_readKey() { + nocbreak(); + cbreak(); + nodelay(stdscr, FALSE); + int ret = getch(); + halfdelay(*CRT_delay); + return ret; +} + +void CRT_disableDelay() { + nocbreak(); + cbreak(); + nodelay(stdscr, TRUE); +} + +void CRT_enableDelay() { + halfdelay(*CRT_delay); +} + +void CRT_setColors(int colorScheme) { + CRT_colorScheme = colorScheme; + + for (short int i = 0; i < 8; i++) { + for (short int j = 0; j < 8; j++) { + if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault) { + short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT) + ? (j == 0 ? -1 : j) + : j; + init_pair(ColorIndex(i, j), i, bg); + } + } + } + + short int grayBlackFg = COLORS > 8 ? 8 : 0; + short int grayBlackBg = (colorScheme != COLORSCHEME_BLACKNIGHT) ? -1 : 0; + init_pair(ColorIndexGrayBlack, grayBlackFg, grayBlackBg); + + init_pair(ColorIndexWhiteDefault, White, -1); + + CRT_colors = CRT_colorSchemes[colorScheme]; +} + +void CRT_handleSIGSEGV(int signal) { + CRT_done(); + + fprintf(stderr, "\n\n" + "FATAL PROGRAM ERROR DETECTED\n" + "============================\n" + "Please check at https://htop.dev/issues whether this issue has already been reported.\n" + "If no similar issue has been reported before, please create a new issue with the following information:\n" + "\n" + "- Your "PACKAGE" version ("PACKAGE" --version)\n" + "- Your OS and kernel version (uname -a)\n" + "- Your distribution and release (lsb_release -a)\n" + "- Likely steps to reproduce (How did it happened?)\n" + ); + +#ifdef HAVE_EXECINFO_H + fprintf(stderr, "- Backtrace of the issue (see below)\n"); +#endif + + fprintf(stderr, + "\n" + ); + + const char* signal_str = strsignal(signal); + if (!signal_str) { + signal_str = "unknown reason"; + } + fprintf(stderr, + "Error information:\n" + "------------------\n" + "A signal %d (%s) was received.\n" + "\n", + signal, signal_str + ); + + fprintf(stderr, + "Setting information:\n" + "--------------------\n"); + Settings_write(CRT_crashSettings, true); + fprintf(stderr, "\n"); + +#ifdef HAVE_EXECINFO_H + fprintf(stderr, + "Backtrace information:\n" + "----------------------\n" + "The following function calls were active when the issue was detected:\n" + "---\n" + ); + + void* backtraceArray[256]; + + size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray)); + backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO); + fprintf(stderr, + "---\n" + "\n" + "To make the above information more practical to work with,\n" + "please also provide a disassembly of your "PACKAGE" binary.\n" + "This can usually be done by running the following command:\n" + "\n" + ); + +#ifdef HTOP_DARWIN + fprintf(stderr, " otool -tvV `which "PACKAGE"` > ~/htop.otool\n"); +#else + fprintf(stderr, " objdump -d -S -w `which "PACKAGE"` > ~/htop.objdump\n"); +#endif + + fprintf(stderr, + "\n" + "Please include the generated file in your report.\n" + "\n" + ); +#endif + + fprintf(stderr, + "Running this program with debug symbols or inside a debugger may provide further insights.\n" + "\n" + "Thank you for helping to improve "PACKAGE"!\n" + "\n" + PACKAGE " " VERSION " aborting.\n" + "\n" + ); + + /* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */ + if (sigaction (signal, &old_sig_handler[signal], NULL) < 0) { + /* This avoids an infinite loop in case the handler could not be reset. */ + fprintf(stderr, + "!!! Chained handler could not be restored. Forcing exit.\n" + ); + _exit(1); + } + + /* Trigger the previous signal handler. */ + raise(signal); + + // Always terminate, even if installed handler returns + fprintf(stderr, + "!!! Chained handler did not exit. Forcing exit.\n" + ); + _exit(1); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/CRT.h pcp-5.3.2/vendor/github.com/htop-dev/htop/CRT.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/CRT.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/CRT.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,187 @@ +#ifndef HEADER_CRT +#define HEADER_CRT +/* +htop - CRT.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" + +#include + +#include "Macros.h" +#include "ProvideCurses.h" +#include "Settings.h" + + +typedef enum TreeStr_ { + TREE_STR_VERT, + TREE_STR_RTEE, + TREE_STR_BEND, + TREE_STR_TEND, + TREE_STR_OPEN, + TREE_STR_SHUT, + TREE_STR_ASC, + TREE_STR_DESC, + LAST_TREE_STR +} TreeStr; + +typedef enum ColorScheme_ { + COLORSCHEME_DEFAULT, + COLORSCHEME_MONOCHROME, + COLORSCHEME_BLACKONWHITE, + COLORSCHEME_LIGHTTERMINAL, + COLORSCHEME_MIDNIGHT, + COLORSCHEME_BLACKNIGHT, + COLORSCHEME_BROKENGRAY, + LAST_COLORSCHEME +} ColorScheme; + +typedef enum ColorElements_ { + RESET_COLOR, + DEFAULT_COLOR, + FUNCTION_BAR, + FUNCTION_KEY, + FAILED_SEARCH, + FAILED_READ, + PAUSED, + PANEL_HEADER_FOCUS, + PANEL_HEADER_UNFOCUS, + PANEL_SELECTION_FOCUS, + PANEL_SELECTION_FOLLOW, + PANEL_SELECTION_UNFOCUS, + LARGE_NUMBER, + METER_SHADOW, + METER_TEXT, + METER_VALUE, + METER_VALUE_ERROR, + METER_VALUE_IOREAD, + METER_VALUE_IOWRITE, + METER_VALUE_NOTICE, + METER_VALUE_OK, + METER_VALUE_WARN, + LED_COLOR, + UPTIME, + BATTERY, + TASKS_RUNNING, + SWAP, + SWAP_CACHE, + PROCESS, + PROCESS_SHADOW, + PROCESS_TAG, + PROCESS_MEGABYTES, + PROCESS_GIGABYTES, + PROCESS_TREE, + PROCESS_R_STATE, + PROCESS_D_STATE, + PROCESS_BASENAME, + PROCESS_HIGH_PRIORITY, + PROCESS_LOW_PRIORITY, + PROCESS_NEW, + PROCESS_TOMB, + PROCESS_THREAD, + PROCESS_THREAD_BASENAME, + PROCESS_COMM, + PROCESS_THREAD_COMM, + BAR_BORDER, + BAR_SHADOW, + GRAPH_1, + GRAPH_2, + MEMORY_USED, + MEMORY_BUFFERS, + MEMORY_BUFFERS_TEXT, + MEMORY_CACHE, + MEMORY_SHARED, + HUGEPAGE_1, + HUGEPAGE_2, + HUGEPAGE_3, + HUGEPAGE_4, + LOAD, + LOAD_AVERAGE_FIFTEEN, + LOAD_AVERAGE_FIVE, + LOAD_AVERAGE_ONE, + CHECK_BOX, + CHECK_MARK, + CHECK_TEXT, + CLOCK, + DATE, + DATETIME, + HELP_BOLD, + HELP_SHADOW, + HOSTNAME, + CPU_NICE, + CPU_NICE_TEXT, + CPU_NORMAL, + CPU_SYSTEM, + CPU_IOWAIT, + CPU_IRQ, + CPU_SOFTIRQ, + CPU_STEAL, + CPU_GUEST, + PRESSURE_STALL_TEN, + PRESSURE_STALL_SIXTY, + PRESSURE_STALL_THREEHUNDRED, + ZFS_MFU, + ZFS_MRU, + ZFS_ANON, + ZFS_HEADER, + ZFS_OTHER, + ZFS_COMPRESSED, + ZFS_RATIO, + ZRAM, + DYNAMIC_GRAY, + DYNAMIC_DARKGRAY, + DYNAMIC_RED, + DYNAMIC_GREEN, + DYNAMIC_BLUE, + DYNAMIC_CYAN, + DYNAMIC_MAGENTA, + DYNAMIC_YELLOW, + DYNAMIC_WHITE, + LAST_COLORELEMENT +} ColorElements; + +void CRT_fatalError(const char* note) ATTR_NORETURN; + +void CRT_handleSIGSEGV(int signal) ATTR_NORETURN; + +#define KEY_WHEELUP KEY_F(20) +#define KEY_WHEELDOWN KEY_F(21) +#define KEY_RECLICK KEY_F(22) +#define KEY_ALT(x) (KEY_F(64 - 26) + ((x) - 'A')) + +extern const char* CRT_degreeSign; + +#ifdef HAVE_LIBNCURSESW + +extern bool CRT_utf8; + +#endif + +extern const char* const* CRT_treeStr; + +extern const int* CRT_colors; + +extern int CRT_cursorX; + +extern int CRT_scrollHAmount; + +extern int CRT_scrollWheelVAmount; + +extern ColorScheme CRT_colorScheme; + +void CRT_init(const Settings* settings, bool allowUnicode); + +void CRT_done(void); + +int CRT_readKey(void); + +void CRT_disableDelay(void); + +void CRT_enableDelay(void); + +void CRT_setColors(int colorScheme); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,443 @@ +/* +htop - DarwinProcess.c +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "darwin/DarwinProcess.h" + +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Process.h" +#include "darwin/Platform.h" + + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, + [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, + [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process from /proc/[pid]/exe", .flags = 0, }, + [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, + [TRANSLATED] = { .name = "TRANSLATED", .title = "T ", .description = "Translation info (T translated, N native)", .flags = 0, }, +}; + +Process* DarwinProcess_new(const Settings* settings) { + DarwinProcess* this = xCalloc(1, sizeof(DarwinProcess)); + Object_setClass(this, Class(DarwinProcess)); + Process_init(&this->super, settings); + + this->utime = 0; + this->stime = 0; + this->taskAccess = true; + this->translated = false; + + return &this->super; +} + +void Process_delete(Object* cast) { + DarwinProcess* this = (DarwinProcess*) cast; + Process_done(&this->super); + // free platform-specific fields here + free(this); +} + +static void DarwinProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const DarwinProcess* dp = (const DarwinProcess*) this; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + int n = sizeof(buffer) - 1; + switch (field) { + // add Platform-specific fields here + case TRANSLATED: xSnprintf(buffer, n, "%c ", dp->translated ? 'T' : 'N'); break; + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int DarwinProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const DarwinProcess* p1 = (const DarwinProcess*)v1; + const DarwinProcess* p2 = (const DarwinProcess*)v2; + + switch (key) { + // add Platform-specific fields here + case TRANSLATED: + return SPACESHIP_NUMBER(p1->translated, p2->translated); + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +static void DarwinProcess_updateExe(pid_t pid, Process* proc) { + char path[PROC_PIDPATHINFO_MAXSIZE]; + + int r = proc_pidpath(pid, path, sizeof(path)); + if (r <= 0) + return; + + Process_updateExe(proc, path); +} + +static void DarwinProcess_updateCwd(pid_t pid, Process* proc) { + struct proc_vnodepathinfo vpi; + + int r = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)); + if (r <= 0) { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + if (!vpi.pvi_cdir.vip_path[0]) { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + free_and_xStrdup(&proc->procCwd, vpi.pvi_cdir.vip_path); +} + +static void DarwinProcess_updateCmdLine(const struct kinfo_proc* k, Process* proc) { + Process_updateComm(proc, k->kp_proc.p_comm); + + /* This function is from the old Mac version of htop. Originally from ps? */ + int mib[3], argmax, nargs, c = 0; + size_t size; + char *procargs, *sp, *np, *cp; + + /* Get the maximum process arguments size. */ + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + + size = sizeof( argmax ); + if ( sysctl( mib, 2, &argmax, &size, NULL, 0 ) == -1 ) { + goto ERROR_A; + } + + /* Allocate space for the arguments. */ + procargs = (char*)xMalloc(argmax); + if ( procargs == NULL ) { + goto ERROR_A; + } + + /* + * Make a sysctl() call to get the raw argument space of the process. + * The layout is documented in start.s, which is part of the Csu + * project. In summary, it looks like: + * + * /---------------\ 0x00000000 + * : : + * : : + * |---------------| + * | argc | + * |---------------| + * | arg[0] | + * |---------------| + * : : + * : : + * |---------------| + * | arg[argc - 1] | + * |---------------| + * | 0 | + * |---------------| + * | env[0] | + * |---------------| + * : : + * : : + * |---------------| + * | env[n] | + * |---------------| + * | 0 | + * |---------------| <-- Beginning of data returned by sysctl() is here. + * | argc | + * |---------------| + * | exec_path | + * |:::::::::::::::| + * | | + * | String area. | + * | | + * |---------------| <-- Top of stack. + * : : + * : : + * \---------------/ 0xffffffff + */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = k->kp_proc.p_pid; + + size = ( size_t ) argmax; + if ( sysctl( mib, 3, procargs, &size, NULL, 0 ) == -1 ) { + goto ERROR_B; + } + + memcpy( &nargs, procargs, sizeof( nargs ) ); + cp = procargs + sizeof( nargs ); + + /* Skip the saved exec_path. */ + for ( ; cp < &procargs[size]; cp++ ) { + if ( *cp == '\0' ) { + /* End of exec_path reached. */ + break; + } + } + if ( cp == &procargs[size] ) { + goto ERROR_B; + } + + /* Skip trailing '\0' characters. */ + for ( ; cp < &procargs[size]; cp++ ) { + if ( *cp != '\0' ) { + /* Beginning of first argument reached. */ + break; + } + } + if ( cp == &procargs[size] ) { + goto ERROR_B; + } + /* Save where the argv[0] string starts. */ + sp = cp; + + int end = 0; + for ( np = NULL; c < nargs && cp < &procargs[size]; cp++ ) { + if ( *cp == '\0' ) { + c++; + if ( np != NULL ) { + /* Convert previous '\0'. */ + *np = ' '; + } + /* Note location of current '\0'. */ + np = cp; + if (end == 0) { + end = cp - sp; + } + } + } + + /* + * sp points to the beginning of the arguments/environment string, and + * np should point to the '\0' terminator for the string. + */ + if ( np == NULL || np == sp ) { + /* Empty or unterminated string. */ + goto ERROR_B; + } + if (end == 0) { + end = np - sp; + } + + Process_updateCmdline(proc, sp, 0, end); + + /* Clean up. */ + free( procargs ); + + return; + +ERROR_B: + free( procargs ); + +ERROR_A: + Process_updateCmdline(proc, k->kp_proc.p_comm, 0, strlen(k->kp_proc.p_comm)); +} + +void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps, bool exists) { + DarwinProcess* dp = (DarwinProcess*)proc; + + const struct extern_proc* ep = &ps->kp_proc; + + /* UNSET HERE : + * + * processor + * user (set at ProcessList level) + * nlwp + * percent_cpu + * percent_mem + * m_virt + * m_resident + * minflt + * majflt + */ + + /* First, the "immutable" parts */ + if (!exists) { + /* Set the PID/PGID/etc. */ + proc->pid = ep->p_pid; + proc->ppid = ps->kp_eproc.e_ppid; + proc->pgrp = ps->kp_eproc.e_pgid; + proc->session = 0; /* TODO Get the session id */ + proc->tpgid = ps->kp_eproc.e_tpgid; + proc->tgid = proc->pid; + proc->isKernelThread = false; + proc->isUserlandThread = false; + dp->translated = ps->kp_proc.p_flag & P_TRANSLATED; + + proc->tty_nr = ps->kp_eproc.e_tdev; + const char* name = (ps->kp_eproc.e_tdev != NODEV) ? devname(ps->kp_eproc.e_tdev, S_IFCHR) : NULL; + if (!name) { + free(proc->tty_name); + proc->tty_name = NULL; + } else { + free_and_xStrdup(&proc->tty_name, name); + } + + proc->starttime_ctime = ep->p_starttime.tv_sec; + Process_fillStarttimeBuffer(proc); + + DarwinProcess_updateExe(ep->p_pid, proc); + DarwinProcess_updateCmdLine(ps, proc); + + if (proc->settings->flags & PROCESS_FLAG_CWD) { + DarwinProcess_updateCwd(ep->p_pid, proc); + } + } + + /* Mutable information */ + proc->nice = ep->p_nice; + proc->priority = ep->p_priority; + + proc->state = (ep->p_stat == SZOMB) ? 'Z' : '?'; + + /* Make sure the updated flag is set */ + proc->updated = true; +} + +void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* dpl, double time_interval) { + struct proc_taskinfo pti; + + if (sizeof(pti) == proc_pidinfo(proc->super.pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti))) { + uint64_t total_existing_time = proc->stime + proc->utime; + uint64_t total_current_time = pti.pti_total_system + pti.pti_total_user; + + if (total_existing_time && 1E-6 < time_interval) { + uint64_t total_time_diff = total_current_time - total_existing_time; + proc->super.percent_cpu = ((double)total_time_diff / time_interval) * 100.0; + } else { + proc->super.percent_cpu = 0.0; + } + + proc->super.time = total_current_time / 10000000; + proc->super.nlwp = pti.pti_threadnum; + proc->super.m_virt = pti.pti_virtual_size / ONE_K; + proc->super.m_resident = pti.pti_resident_size / ONE_K; + proc->super.majflt = pti.pti_faults; + proc->super.percent_mem = (double)pti.pti_resident_size * 100.0 + / (double)dpl->host_info.max_mem; + + proc->stime = pti.pti_total_system; + proc->utime = pti.pti_total_user; + + dpl->super.kernelThreads += 0; /*pti.pti_threads_system;*/ + dpl->super.userlandThreads += pti.pti_threadnum; /*pti.pti_threads_user;*/ + dpl->super.totalTasks += pti.pti_threadnum; + dpl->super.runningTasks += pti.pti_numrunning; + } +} + +/* + * Scan threads for process state information. + * Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread + * and https://github.com/max-horvath/htop-osx/blob/e86692e869e30b0bc7264b3675d2a4014866ef46/ProcessList.c + */ +void DarwinProcess_scanThreads(DarwinProcess* dp) { + Process* proc = (Process*) dp; + kern_return_t ret; + + if (!dp->taskAccess) { + return; + } + + if (proc->state == 'Z') { + return; + } + + task_t port; + ret = task_for_pid(mach_task_self(), proc->pid, &port); + if (ret != KERN_SUCCESS) { + dp->taskAccess = false; + return; + } + + task_info_data_t tinfo; + mach_msg_type_number_t task_info_count = TASK_INFO_MAX; + ret = task_info(port, TASK_BASIC_INFO, (task_info_t) tinfo, &task_info_count); + if (ret != KERN_SUCCESS) { + dp->taskAccess = false; + return; + } + + thread_array_t thread_list; + mach_msg_type_number_t thread_count; + ret = task_threads(port, &thread_list, &thread_count); + if (ret != KERN_SUCCESS) { + dp->taskAccess = false; + mach_port_deallocate(mach_task_self(), port); + return; + } + + integer_t run_state = 999; + for (unsigned int i = 0; i < thread_count; i++) { + thread_info_data_t thinfo; + mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT; + ret = thread_info(thread_list[i], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count); + if (ret == KERN_SUCCESS) { + thread_basic_info_t basic_info_th = (thread_basic_info_t) thinfo; + if (basic_info_th->run_state < run_state) { + run_state = basic_info_th->run_state; + } + mach_port_deallocate(mach_task_self(), thread_list[i]); + } + } + vm_deallocate(mach_task_self(), (vm_address_t) thread_list, sizeof(thread_port_array_t) * thread_count); + mach_port_deallocate(mach_task_self(), port); + + char state = '?'; + switch (run_state) { + case TH_STATE_RUNNING: state = 'R'; break; + case TH_STATE_STOPPED: state = 'S'; break; + case TH_STATE_WAITING: state = 'W'; break; + case TH_STATE_UNINTERRUPTIBLE: state = 'U'; break; + case TH_STATE_HALTED: state = 'H'; break; + } + proc->state = state; +} + + +const ProcessClass DarwinProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = DarwinProcess_writeField, + .compareByKey = DarwinProcess_compareByKey, +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,43 @@ +#ifndef HEADER_DarwinProcess +#define HEADER_DarwinProcess +/* +htop - DarwinProcess.h +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Settings.h" +#include "darwin/DarwinProcessList.h" + +typedef struct DarwinProcess_ { + Process super; + + uint64_t utime; + uint64_t stime; + bool taskAccess; + bool translated; +} DarwinProcess; + +extern const ProcessClass DarwinProcess_class; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* DarwinProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps, bool exists); + +void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* dpl, double time_interval); + +/* + * Scan threads for process state information. + * Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread + * and https://github.com/max-horvath/htop-osx/blob/e86692e869e30b0bc7264b3675d2a4014866ef46/ProcessList.c + */ +void DarwinProcess_scanThreads(DarwinProcess* dp); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,236 @@ +/* +htop - DarwinProcessList.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "darwin/DarwinProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "ProcessList.h" +#include "darwin/DarwinProcess.h" +#include "darwin/Platform.h" +#include "generic/openzfs_sysctl.h" +#include "zfs/ZfsArcStats.h" + + +struct kern { + short int version[3]; +}; + +static void GetKernelVersion(struct kern* k) { + static short int version_[3] = {0}; + if (!version_[0]) { + // just in case it fails someday + version_[0] = version_[1] = version_[2] = -1; + char str[256] = {0}; + size_t size = sizeof(str); + int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0); + if (ret == 0) { + sscanf(str, "%hd.%hd.%hd", &version_[0], &version_[1], &version_[2]); + } + } + memcpy(k->version, version_, sizeof(version_)); +} + +/* compare the given os version with the one installed returns: +0 if equals the installed version +positive value if less than the installed version +negative value if more than the installed version +*/ +static int CompareKernelVersion(short int major, short int minor, short int component) { + struct kern k; + GetKernelVersion(&k); + + if (k.version[0] != major) { + return k.version[0] - major; + } + if (k.version[1] != minor) { + return k.version[1] - minor; + } + if (k.version[2] != component) { + return k.version[2] - component; + } + + return 0; +} + +static void ProcessList_getHostInfo(host_basic_info_data_t* p) { + mach_msg_type_number_t info_size = HOST_BASIC_INFO_COUNT; + + if (0 != host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)p, &info_size)) { + CRT_fatalError("Unable to retrieve host info"); + } +} + +static void ProcessList_freeCPULoadInfo(processor_cpu_load_info_t* p) { + if (NULL != p && NULL != *p) { + if (0 != munmap(*p, vm_page_size)) { + CRT_fatalError("Unable to free old CPU load information"); + } + *p = NULL; + } +} + +static unsigned ProcessList_allocateCPULoadInfo(processor_cpu_load_info_t* p) { + mach_msg_type_number_t info_size = sizeof(processor_cpu_load_info_t); + unsigned cpu_count; + + // TODO Improving the accuracy of the load counts woule help a lot. + if (0 != host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, (processor_info_array_t*)p, &info_size)) { + CRT_fatalError("Unable to retrieve CPU info"); + } + + return cpu_count; +} + +static void ProcessList_getVMStats(vm_statistics_t p) { + mach_msg_type_number_t info_size = HOST_VM_INFO_COUNT; + + if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)p, &info_size) != 0) { + CRT_fatalError("Unable to retrieve VM statistics"); + } +} + +static struct kinfo_proc* ProcessList_getKInfoProcs(size_t* count) { + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; + struct kinfo_proc* processes = NULL; + + for (int retry = 3; retry > 0; retry--) { + size_t size = 0; + if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0 || size == 0) { + CRT_fatalError("Unable to get size of kproc_infos"); + } + + processes = xRealloc(processes, size); + + if (sysctl(mib, 4, processes, &size, NULL, 0) == 0) { + *count = size / sizeof(struct kinfo_proc); + return processes; + } + + if (errno != ENOMEM) + break; + } + + CRT_fatalError("Unable to get kinfo_procs"); +} + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + DarwinProcessList* this = xCalloc(1, sizeof(DarwinProcessList)); + + ProcessList_init(&this->super, Class(DarwinProcess), usersTable, dynamicMeters, pidMatchList, userId); + + /* Initialize the CPU information */ + this->super.cpuCount = ProcessList_allocateCPULoadInfo(&this->prev_load); + ProcessList_getHostInfo(&this->host_info); + ProcessList_allocateCPULoadInfo(&this->curr_load); + + /* Initialize the VM statistics */ + ProcessList_getVMStats(&this->vm_stats); + + /* Initialize the ZFS kstats, if zfs.kext loaded */ + openzfs_sysctl_init(&this->zfs); + openzfs_sysctl_updateArcStats(&this->zfs); + + this->super.kernelThreads = 0; + this->super.userlandThreads = 0; + this->super.totalTasks = 0; + this->super.runningTasks = 0; + + return &this->super; +} + +void ProcessList_delete(ProcessList* this) { + ProcessList_done(this); + free(this); +} + +static double ticksToNanoseconds(const double ticks) { + const double nanos_per_sec = 1e9; + return (ticks / Platform_timebaseToNS) * (nanos_per_sec / (double) Platform_clockTicksPerSec); +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + DarwinProcessList* dpl = (DarwinProcessList*)super; + bool preExisting = true; + struct kinfo_proc* ps; + size_t count; + DarwinProcess* proc; + + /* Update the global data (CPU times and VM stats) */ + ProcessList_freeCPULoadInfo(&dpl->prev_load); + dpl->prev_load = dpl->curr_load; + ProcessList_allocateCPULoadInfo(&dpl->curr_load); + ProcessList_getVMStats(&dpl->vm_stats); + openzfs_sysctl_updateArcStats(&dpl->zfs); + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + /* Get the time difference */ + dpl->global_diff = 0; + for (unsigned int i = 0; i < dpl->super.cpuCount; ++i) { + for (size_t j = 0; j < CPU_STATE_MAX; ++j) { + dpl->global_diff += dpl->curr_load[i].cpu_ticks[j] - dpl->prev_load[i].cpu_ticks[j]; + } + } + + const double time_interval = ticksToNanoseconds(dpl->global_diff) / (double) dpl->super.cpuCount; + + /* Clear the thread counts */ + super->kernelThreads = 0; + super->userlandThreads = 0; + super->totalTasks = 0; + super->runningTasks = 0; + + /* We use kinfo_procs for initial data since : + * + * 1) They always succeed. + * 2) The contain the basic information. + * + * We attempt to fill-in additional information with libproc. + */ + ps = ProcessList_getKInfoProcs(&count); + + for (size_t i = 0; i < count; ++i) { + proc = (DarwinProcess*)ProcessList_getProcess(super, ps[i].kp_proc.p_pid, &preExisting, DarwinProcess_new); + + DarwinProcess_setFromKInfoProc(&proc->super, &ps[i], preExisting); + DarwinProcess_setFromLibprocPidinfo(proc, dpl, time_interval); + + if (proc->super.st_uid != ps[i].kp_eproc.e_ucred.cr_uid) { + proc->super.st_uid = ps[i].kp_eproc.e_ucred.cr_uid; + proc->super.user = UsersTable_getRef(super->usersTable, proc->super.st_uid); + } + + // Disabled for High Sierra due to bug in macOS High Sierra + bool isScanThreadSupported = ! ( CompareKernelVersion(17, 0, 0) >= 0 && CompareKernelVersion(17, 5, 0) < 0); + + if (isScanThreadSupported) { + DarwinProcess_scanThreads(proc); + } + + super->totalTasks += 1; + + if (!preExisting) { + ProcessList_add(super, &proc->super); + } + } + + free(ps); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/DarwinProcessList.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,37 @@ +#ifndef HEADER_DarwinProcessList +#define HEADER_DarwinProcessList +/* +htop - DarwinProcessList.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + +#include "ProcessList.h" +#include "zfs/ZfsArcStats.h" + + +typedef struct DarwinProcessList_ { + ProcessList super; + + host_basic_info_data_t host_info; + vm_statistics_data_t vm_stats; + processor_cpu_load_info_t prev_load; + processor_cpu_load_info_t curr_load; + uint64_t kernel_threads; + uint64_t user_threads; + uint64_t global_diff; + + ZfsArcStats zfs; +} DarwinProcessList; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/Platform.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,431 @@ +/* +htop - darwin/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2015 David C. Hunt +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "darwin/Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ClockMeter.h" +#include "CPUMeter.h" +#include "CRT.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MemoryMeter.h" +#include "ProcessLocksScreen.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "darwin/DarwinProcessList.h" +#include "zfs/ZfsArcMeter.h" +#include "zfs/ZfsCompressedArcMeter.h" + +#ifdef HAVE_HOST_GET_CLOCK_SERVICE +#include +#include +#endif +#ifdef HAVE_MACH_MACH_TIME_H +#include +#endif + + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 6 SIGIOT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGURG", .number = 16 }, + { .name = "17 SIGSTOP", .number = 17 }, + { .name = "18 SIGTSTP", .number = 18 }, + { .name = "19 SIGCONT", .number = 19 }, + { .name = "20 SIGCHLD", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGIO", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGINFO", .number = 29 }, + { .name = "30 SIGUSR1", .number = 30 }, + { .name = "31 SIGUSR2", .number = 31 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &UptimeMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &ZfsArcMeter_class, + &ZfsCompressedArcMeter_class, + &BlankMeter_class, + NULL +}; + +double Platform_timebaseToNS = 1.0; + +long Platform_clockTicksPerSec = -1; + +void Platform_init(void) { + // Check if we can determine the timebase used on this system. + // If the API is unavailable assume we get our timebase in nanoseconds. +#ifdef HAVE_MACH_TIMEBASE_INFO + mach_timebase_info_data_t info; + mach_timebase_info(&info); + Platform_timebaseToNS = (double)info.numer / (double)info.denom; +#else + Platform_timebaseToNS = 1.0; +#endif + + // Determine the number of clock ticks per second + errno = 0; + Platform_clockTicksPerSec = sysconf(_SC_CLK_TCK); + + if (errno || Platform_clockTicksPerSec < 1) { + CRT_fatalError("Unable to retrieve clock tick rate"); + } +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + struct timeval bootTime, currTime; + int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t size = sizeof(bootTime); + + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); + if (err) { + return -1; + } + gettimeofday(&currTime, NULL); + + return (int) difftime(currTime.tv_sec, bootTime.tv_sec); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + double results[3]; + + if (3 == getloadavg(results, 3)) { + *one = results[0]; + *five = results[1]; + *fifteen = results[2]; + } else { + *one = 0; + *five = 0; + *fifteen = 0; + } +} + +int Platform_getMaxPid() { + /* http://opensource.apple.com/source/xnu/xnu-2782.1.97/bsd/sys/proc_internal.hh */ + return 99999; +} + +static double Platform_setCPUAverageValues(Meter* mtr) { + const ProcessList* dpl = mtr->pl; + unsigned int cpus = dpl->cpuCount; + double sumNice = 0.0; + double sumNormal = 0.0; + double sumKernel = 0.0; + double sumPercent = 0.0; + for (unsigned int i = 1; i <= cpus; i++) { + sumPercent += Platform_setCPUValues(mtr, i); + sumNice += mtr->values[CPU_METER_NICE]; + sumNormal += mtr->values[CPU_METER_NORMAL]; + sumKernel += mtr->values[CPU_METER_KERNEL]; + } + mtr->values[CPU_METER_NICE] = sumNice / cpus; + mtr->values[CPU_METER_NORMAL] = sumNormal / cpus; + mtr->values[CPU_METER_KERNEL] = sumKernel / cpus; + return sumPercent / cpus; +} + +double Platform_setCPUValues(Meter* mtr, unsigned int cpu) { + + if (cpu == 0) { + return Platform_setCPUAverageValues(mtr); + } + + const DarwinProcessList* dpl = (const DarwinProcessList*)mtr->pl; + const processor_cpu_load_info_t prev = &dpl->prev_load[cpu - 1]; + const processor_cpu_load_info_t curr = &dpl->curr_load[cpu - 1]; + double total = 0; + + /* Take the sums */ + for (size_t i = 0; i < CPU_STATE_MAX; ++i) { + total += (double)curr->cpu_ticks[i] - (double)prev->cpu_ticks[i]; + } + + mtr->values[CPU_METER_NICE] + = ((double)curr->cpu_ticks[CPU_STATE_NICE] - (double)prev->cpu_ticks[CPU_STATE_NICE]) * 100.0 / total; + mtr->values[CPU_METER_NORMAL] + = ((double)curr->cpu_ticks[CPU_STATE_USER] - (double)prev->cpu_ticks[CPU_STATE_USER]) * 100.0 / total; + mtr->values[CPU_METER_KERNEL] + = ((double)curr->cpu_ticks[CPU_STATE_SYSTEM] - (double)prev->cpu_ticks[CPU_STATE_SYSTEM]) * 100.0 / total; + + mtr->curItems = 3; + + /* Convert to percent and return */ + total = mtr->values[CPU_METER_NICE] + mtr->values[CPU_METER_NORMAL] + mtr->values[CPU_METER_KERNEL]; + + mtr->values[CPU_METER_FREQUENCY] = NAN; + mtr->values[CPU_METER_TEMPERATURE] = NAN; + + return CLAMP(total, 0.0, 100.0); +} + +void Platform_setMemoryValues(Meter* mtr) { + const DarwinProcessList* dpl = (const DarwinProcessList*)mtr->pl; + const struct vm_statistics* vm = &dpl->vm_stats; + double page_K = (double)vm_page_size / (double)1024; + + mtr->total = dpl->host_info.max_mem / 1024; + mtr->values[0] = (double)(vm->active_count + vm->wire_count) * page_K; + mtr->values[1] = (double)vm->purgeable_count * page_K; + // mtr->values[2] = "shared memory, like tmpfs and shm" + mtr->values[3] = (double)vm->inactive_count * page_K; + // mtr->values[4] = "available memory" +} + +void Platform_setSwapValues(Meter* mtr) { + int mib[2] = {CTL_VM, VM_SWAPUSAGE}; + struct xsw_usage swapused; + size_t swlen = sizeof(swapused); + sysctl(mib, 2, &swapused, &swlen, NULL, 0); + + mtr->total = swapused.xsu_total / 1024; + mtr->values[0] = swapused.xsu_used / 1024; +} + +void Platform_setZfsArcValues(Meter* this) { + const DarwinProcessList* dpl = (const DarwinProcessList*) this->pl; + + ZfsArcMeter_readStats(this, &(dpl->zfs)); +} + +void Platform_setZfsCompressedArcValues(Meter* this) { + const DarwinProcessList* dpl = (const DarwinProcessList*) this->pl; + + ZfsCompressedArcMeter_readStats(this, &(dpl->zfs)); +} + +char* Platform_getProcessEnv(pid_t pid) { + char* env = NULL; + + int argmax; + size_t bufsz = sizeof(argmax); + + int mib[3]; + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + if (sysctl(mib, 2, &argmax, &bufsz, 0, 0) == 0) { + char* buf = xMalloc(argmax); + if (buf) { + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = pid; + bufsz = argmax; + if (sysctl(mib, 3, buf, &bufsz, 0, 0) == 0) { + if (bufsz > sizeof(int)) { + char *p = buf, *endp = buf + bufsz; + int argc = *(int*)(void*)p; + p += sizeof(int); + + // skip exe + p = strchr(p, 0) + 1; + + // skip padding + while (!*p && p < endp) + ++p; + + // skip argv + for (; argc-- && p < endp; p = strrchr(p, 0) + 1) + ; + + // skip padding + while (!*p && p < endp) + ++p; + + size_t size = endp - p; + env = xMalloc(size + 2); + memcpy(env, p, size); + env[size] = 0; + env[size + 1] = 0; + } + } + free(buf); + } + } + + return env; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + // TODO + (void)data; + return false; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + // TODO + (void)data; + return false; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + CFTypeRef power_sources = IOPSCopyPowerSourcesInfo(); + + *percent = NAN; + *isOnAC = AC_ERROR; + + if (NULL == power_sources) + return; + + CFArrayRef list = IOPSCopyPowerSourcesList(power_sources); + CFDictionaryRef battery = NULL; + int len; + + if (NULL == list) { + CFRelease(power_sources); + + return; + } + + len = CFArrayGetCount(list); + + /* Get the battery */ + for (int i = 0; i < len && battery == NULL; ++i) { + CFDictionaryRef candidate = IOPSGetPowerSourceDescription(power_sources, + CFArrayGetValueAtIndex(list, i)); /* GET rule */ + CFStringRef type; + + if (NULL != candidate) { + type = (CFStringRef) CFDictionaryGetValue(candidate, + CFSTR(kIOPSTransportTypeKey)); /* GET rule */ + + if (kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { + CFRetain(candidate); + battery = candidate; + } + } + } + + if (NULL != battery) { + /* Determine the AC state */ + CFStringRef power_state = CFDictionaryGetValue(battery, CFSTR(kIOPSPowerSourceStateKey)); + + *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) + ? AC_PRESENT + : AC_ABSENT; + + /* Get the percentage remaining */ + double current; + double max; + + CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey)), + kCFNumberDoubleType, ¤t); + CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey)), + kCFNumberDoubleType, &max); + + *percent = (current * 100.0) / max; + + CFRelease(battery); + } + + CFRelease(list); + CFRelease(power_sources); +} + +void Platform_gettime_monotonic(uint64_t* msec) { + +#ifdef HAVE_HOST_GET_CLOCK_SERVICE + + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + *msec = ((uint64_t)mts.tv_sec * 1000) + ((uint64_t)mts.tv_nsec / 1000000); + +#else + + Generic_gettime_monotomic(msec); + +#endif +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/Platform.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,105 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - darwin/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2015 David C. Hunt +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "CPUMeter.h" +#include "DiskIOMeter.h" +#include "NetworkIOMeter.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "darwin/DarwinProcess.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + + +extern const ProcessField Platform_defaultFields[]; + +extern double Platform_timebaseToNS; + +extern long Platform_clockTicksPerSec; + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* mtr, unsigned int cpu); + +void Platform_setMemoryValues(Meter* mtr); + +void Platform_setSwapValues(Meter* mtr); + +void Platform_setZfsArcValues(Meter* this); + +void Platform_setZfsCompressedArcValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +#define PLATFORM_LONG_OPTIONS + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +void Platform_gettime_monotonic(uint64_t* msec); + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/darwin/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/darwin/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,18 @@ +#ifndef HEADER_DarwinProcessField +#define HEADER_DarwinProcessField +/* +htop - darwin/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + TRANSLATED = 100, \ + \ + DUMMY_BUMP_FIELD = CWD, \ + // End of list + + +#endif /* HEADER_DarwinProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DateMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/DateMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DateMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DateMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,52 @@ +/* +htop - DateMeter.c +(C) 2004-2020 Hisham H. Muhammad, Michael Schönitzer +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "DateMeter.h" + +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "ProcessList.h" + + +static const int DateMeter_attributes[] = { + DATE +}; + +static void DateMeter_updateValues(Meter* this) { + const ProcessList* pl = this->pl; + + struct tm result; + const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result); + this->values[0] = lt->tm_yday; + int year = lt->tm_year + 1900; + if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { + this->total = 366; + } else { + this->total = 365; + } + strftime(this->txtBuffer, sizeof(this->txtBuffer), "%F", lt); +} + +const MeterClass DateMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = DateMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 365, + .attributes = DateMeter_attributes, + .name = "Date", + .uiName = "Date", + .caption = "Date: ", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DateMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/DateMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DateMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DateMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_DateMeter +#define HEADER_DateMeter +/* +htop - DateMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass DateMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DateTimeMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/DateTimeMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DateTimeMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DateTimeMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,52 @@ +/* +htop - DateTimeMeter.c +(C) 2004-2020 Hisham H. Muhammad, Michael Schönitzer +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "DateTimeMeter.h" + +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "ProcessList.h" + + +static const int DateTimeMeter_attributes[] = { + DATETIME +}; + +static void DateTimeMeter_updateValues(Meter* this) { + const ProcessList* pl = this->pl; + + struct tm result; + const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result); + int year = lt->tm_year + 1900; + if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { + this->total = 366; + } else { + this->total = 365; + } + this->values[0] = lt->tm_yday; + strftime(this->txtBuffer, sizeof(this->txtBuffer), "%F %H:%M:%S", lt); +} + +const MeterClass DateTimeMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = DateTimeMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 365, + .attributes = DateTimeMeter_attributes, + .name = "DateTime", + .uiName = "Date and Time", + .caption = "Date & Time: ", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DateTimeMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/DateTimeMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DateTimeMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DateTimeMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_DateTimeMeter +#define HEADER_DateTimeMeter +/* +htop - DateTimeMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass DateTimeMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DiskIOMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/DiskIOMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DiskIOMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DiskIOMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,129 @@ +/* +htop - DiskIOMeter.c +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "DiskIOMeter.h" + +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "XUtils.h" + + +static const int DiskIOMeter_attributes[] = { + METER_VALUE_NOTICE, + METER_VALUE_IOREAD, + METER_VALUE_IOWRITE, +}; + +static bool hasData = false; +static uint32_t cached_read_diff; +static uint32_t cached_write_diff; +static double cached_utilisation_diff; + +static void DiskIOMeter_updateValues(Meter* this) { + const ProcessList* pl = this->pl; + + static uint64_t cached_last_update; + uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update; + + /* update only every 500ms */ + if (passedTimeInMs > 500) { + static uint64_t cached_read_total; + static uint64_t cached_write_total; + static uint64_t cached_msTimeSpend_total; + uint64_t diff; + + cached_last_update = pl->realtimeMs; + + DiskIOData data; + + hasData = Platform_getDiskIO(&data); + if (!hasData) { + this->values[0] = 0; + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "no data"); + return; + } + + if (data.totalBytesRead > cached_read_total) { + diff = data.totalBytesRead - cached_read_total; + diff /= 1024; /* Meter_humanUnit() expects unit in kilo */ + cached_read_diff = (uint32_t)diff; + } else { + cached_read_diff = 0; + } + cached_read_total = data.totalBytesRead; + + if (data.totalBytesWritten > cached_write_total) { + diff = data.totalBytesWritten - cached_write_total; + diff /= 1024; /* Meter_humanUnit() expects unit in kilo */ + cached_write_diff = (uint32_t)diff; + } else { + cached_write_diff = 0; + } + cached_write_total = data.totalBytesWritten; + + if (data.totalMsTimeSpend > cached_msTimeSpend_total) { + diff = data.totalMsTimeSpend - cached_msTimeSpend_total; + cached_utilisation_diff = 100.0 * (double)diff / passedTimeInMs; + } else { + cached_utilisation_diff = 0.0; + } + cached_msTimeSpend_total = data.totalMsTimeSpend; + } + + this->values[0] = cached_utilisation_diff; + this->total = MAXIMUM(this->values[0], 100.0); /* fix total after (initial) spike */ + + char bufferRead[12], bufferWrite[12]; + Meter_humanUnit(bufferRead, cached_read_diff, sizeof(bufferRead)); + Meter_humanUnit(bufferWrite, cached_write_diff, sizeof(bufferWrite)); + snprintf(this->txtBuffer, sizeof(this->txtBuffer), "%sB %sB %.1f%%", bufferRead, bufferWrite, cached_utilisation_diff); +} + +static void DiskIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) { + if (!hasData) { + RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data"); + return; + } + + char buffer[16]; + int len; + + int color = cached_utilisation_diff > 40.0 ? METER_VALUE_NOTICE : METER_VALUE; + len = xSnprintf(buffer, sizeof(buffer), "%.1f%%", cached_utilisation_diff); + RichString_appendnAscii(out, CRT_colors[color], buffer, len); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " read: "); + Meter_humanUnit(buffer, cached_read_diff, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " write: "); + Meter_humanUnit(buffer, cached_write_diff, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer); +} + +const MeterClass DiskIOMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = DiskIOMeter_display + }, + .updateValues = DiskIOMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 100.0, + .attributes = DiskIOMeter_attributes, + .name = "DiskIO", + .uiName = "Disk IO", + .caption = "Disk IO: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DiskIOMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/DiskIOMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DiskIOMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DiskIOMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,21 @@ +#ifndef HEADER_DiskIOMeter +#define HEADER_DiskIOMeter +/* +htop - DiskIOMeter.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +typedef struct DiskIOData_ { + uint64_t totalBytesRead; + uint64_t totalBytesWritten; + uint64_t totalMsTimeSpend; +} DiskIOData; + +extern const MeterClass DiskIOMeter_class; + +#endif /* HEADER_DiskIOMeter */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,145 @@ +/* +htop - DisplayOptionsPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "DisplayOptionsPanel.h" + +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Header.h" +#include "Object.h" +#include "OptionItem.h" +#include "ProvideCurses.h" + + +static const char* const DisplayOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL}; + +static void DisplayOptionsPanel_delete(Object* object) { + Panel* super = (Panel*) object; + DisplayOptionsPanel* this = (DisplayOptionsPanel*) object; + Panel_done(super); + free(this); +} + +static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) { + DisplayOptionsPanel* this = (DisplayOptionsPanel*) super; + + HandlerResult result = IGNORED; + OptionItem* selected = (OptionItem*) Panel_getSelected(super); + + switch (ch) { + case '\n': + case '\r': + case KEY_ENTER: + case KEY_MOUSE: + case KEY_RECLICK: + case ' ': + switch (OptionItem_kind(selected)) { + case OPTION_ITEM_CHECK: + CheckItem_toggle((CheckItem*)selected); + result = HANDLED; + break; + case OPTION_ITEM_NUMBER: + NumberItem_toggle((NumberItem*)selected); + result = HANDLED; + break; + } + break; + case '-': + if (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) { + NumberItem_decrease((NumberItem*)selected); + result = HANDLED; + } + break; + case '+': + if (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) { + NumberItem_increase((NumberItem*)selected); + result = HANDLED; + } + break; + } + + if (result == HANDLED) { + this->settings->changed = true; + Header* header = this->scr->header; + Header_calculateHeight(header); + Header_reinit(header); + Header_updateData(header); + Header_draw(header); + ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); + } + return result; +} + +const PanelClass DisplayOptionsPanel_class = { + .super = { + .extends = Class(Panel), + .delete = DisplayOptionsPanel_delete + }, + .eventHandler = DisplayOptionsPanel_eventHandler +}; + +DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr) { + DisplayOptionsPanel* this = AllocThis(DisplayOptionsPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(DisplayOptionsFunctions, NULL, NULL); + Panel_init(super, 1, 1, 1, 1, Class(OptionItem), true, fuBar); + + this->settings = settings; + this->scr = scr; + + Panel_setHeader(super, "Display options"); + Panel_add(super, (Object*) CheckItem_newByRef("Tree view", &(settings->treeView))); + Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is always sorted by PID (htop 2 behavior)", &(settings->treeViewAlwaysByPID))); + Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is collapsed by default", &(settings->allBranchesCollapsed))); + Panel_add(super, (Object*) CheckItem_newByRef("Shadow other users' processes", &(settings->shadowOtherUsers))); + Panel_add(super, (Object*) CheckItem_newByRef("Hide kernel threads", &(settings->hideKernelThreads))); + Panel_add(super, (Object*) CheckItem_newByRef("Hide userland process threads", &(settings->hideUserlandThreads))); + Panel_add(super, (Object*) CheckItem_newByRef("Display threads in a different color", &(settings->highlightThreads))); + Panel_add(super, (Object*) CheckItem_newByRef("Show custom thread names", &(settings->showThreadNames))); + Panel_add(super, (Object*) CheckItem_newByRef("Show program path", &(settings->showProgramPath))); + Panel_add(super, (Object*) CheckItem_newByRef("Highlight program \"basename\"", &(settings->highlightBaseName))); + Panel_add(super, (Object*) CheckItem_newByRef("Highlight out-dated/removed programs", &(settings->highlightDeletedExe))); + Panel_add(super, (Object*) CheckItem_newByRef("Merge exe, comm and cmdline in Command", &(settings->showMergedCommand))); + Panel_add(super, (Object*) CheckItem_newByRef("- Try to find comm in cmdline (when Command is merged)", &(settings->findCommInCmdline))); + Panel_add(super, (Object*) CheckItem_newByRef("- Try to strip exe from cmdline (when Command is merged)", &(settings->stripExeFromCmdline))); + Panel_add(super, (Object*) CheckItem_newByRef("Highlight large numbers in memory counters", &(settings->highlightMegabytes))); + Panel_add(super, (Object*) CheckItem_newByRef("Leave a margin around header", &(settings->headerMargin))); + Panel_add(super, (Object*) CheckItem_newByRef("Detailed CPU time (System/IO-Wait/Hard-IRQ/Soft-IRQ/Steal/Guest)", &(settings->detailedCPUTime))); + Panel_add(super, (Object*) CheckItem_newByRef("Count CPUs from 1 instead of 0", &(settings->countCPUsFromOne))); + Panel_add(super, (Object*) CheckItem_newByRef("Update process names on every refresh", &(settings->updateProcessNames))); + Panel_add(super, (Object*) CheckItem_newByRef("Add guest time in CPU meter percentage", &(settings->accountGuestInCPUMeter))); + Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU percentage numerically", &(settings->showCPUUsage))); + Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU frequency", &(settings->showCPUFrequency))); + #ifdef BUILD_WITH_CPU_TEMP + Panel_add(super, (Object*) CheckItem_newByRef( + #if defined(HTOP_LINUX) + "Also show CPU temperature (requires libsensors)", + #elif defined(HTOP_FREEBSD) + "Also show CPU temperature", + #else + #error Unknown temperature implementation! + #endif + &(settings->showCPUTemperature))); + Panel_add(super, (Object*) CheckItem_newByRef("- Show temperature in degree Fahrenheit instead of Celsius", &(settings->degreeFahrenheit))); + #endif + #ifdef HAVE_GETMOUSE + Panel_add(super, (Object*) CheckItem_newByRef("Enable the mouse", &(settings->enableMouse))); + #endif + Panel_add(super, (Object*) NumberItem_newByRef("Update interval (in seconds)", &(settings->delay), -1, 1, 255)); + Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges))); + Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24 * 60 * 60)); + Panel_add(super, (Object*) NumberItem_newByRef("Hide main function bar (0 - off, 1 - on ESC until next input, 2 - permanently)", &(settings->hideFunctionBar), 0, 0, 2)); + #ifdef HAVE_LIBHWLOC + Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity))); + #endif + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DisplayOptionsPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,26 @@ +#ifndef HEADER_DisplayOptionsPanel +#define HEADER_DisplayOptionsPanel +/* +htop - DisplayOptionsPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" +#include "ScreenManager.h" +#include "Settings.h" + + +typedef struct DisplayOptionsPanel_ { + Panel super; + + Settings* settings; + ScreenManager* scr; +} DisplayOptionsPanel; + +extern const PanelClass DisplayOptionsPanel_class; + +DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* scr); + +#endif Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/vendor/github.com/htop-dev/htop/docs/images/screenshot.png and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/vendor/github.com/htop-dev/htop/docs/images/screenshot.png differ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/docs/styleguide.md pcp-5.3.2/vendor/github.com/htop-dev/htop/docs/styleguide.md --- pcp-5.3.1/vendor/github.com/htop-dev/htop/docs/styleguide.md 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/docs/styleguide.md 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,241 @@ +htop coding style guide +======================= + +Naming conventions +------------------ + +Names are important to convey what all those things inside the project are for. +Filenames for source code traditionally used camel-case naming with the first letter written in uppercase. +The file extension is always lowercase. + +The only exception here is `htop.c` which is the main entrance point into the code. + +Folders for e.g. platform-specific code or complex features spawning multiple files are written in lowercase, e.g. `linux`, `freebsd`, `zfs`. + +Inside files, the naming somewhat depends on the context. +For functions names should include a camel-case prefix before the actual name, separated by an underscore. +While this prefix usually coincides with the module name, this is not required, yet strongly advised. +One important exception to this rule are the memory management and the string utility functions from `XUtils.h`. + +Variable names inside functions should be short and precise. +Using `i` for some loop counter is totally fine, using `someCounterValueForThisSimpleLoop` is not. +On the other hand, when you need to hold global storage try to keep this local to your module, i.e. declare such variables `static` within the C source file. +Only if your variable really needs to be visible for the whole project (which is really rare) it deserves a declaration in the header, marked `extern`. + +File content structure +---------------------- + +The content within each file is usually structured according to the following loose template: + +* Copyright declaration +* Inclusion of used headers +* Necessary data structures and forward declarations +* Static module-private function implementations +* Externally visible function implementations +* Externally visible constant structures (pseudo-OOP definitions) + +For header files header guards based on `#ifdef` should be used. +These header guards are historically placed **before** the Copyright declaration. +Stick to that for consistency please. + +Example: + +```c +#ifndef HEADER_FILENAME +#define HEADER_FILENAME +/* +htop - Filename.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +``` + +Import and use of headers +------------------------- + +Every file should import headers for all symbols it's using. +Thus when using a symbol from a header, even if that symbol is already imported by something else you use, you should declare an import for that header. +Doing so allows for easier restructuring of the code when things need to be moved around. +If you are unsure if all necessary headers are included you might use IWYU to tell you. + +The list of includes should be the first thing in the file, after the copyright comment and be followed by two blank lines. +The include list should be in the following order, with each group separated by one blank line: + +1. `include "config.h" // IWYU pragma: keep` if the global configuration + from automake&autoconfigure or any of the feature guards for C library headers + (like `__GNU_SOURCE`) are required, optional otherwise. Beware of the IWYU comment. +2. Accompanying module header file (for C source files only, missing inside headers) +3. List of used system headers (non-conditional includes) +4. List of used program headers +5. Conditionally included header files, system headers first + +The list of headers should be sorted with includes from subdirectories following after files inside their parent directory. +Thus `unistd.h` sorts before `sys/time.h`. + +Symbol Exports +-------------- + +Exports of symbols should be used sparingly. +Thus unless a function you write is intended to become public API of a module you should mark it as `static`. +If a function should be public API an appropriate declaration for that function has to be placed in the accompanying header file. + +Please avoid function-like macros, in particular when exporting them in a header file. +They have several downsides (re-evaluation of arguments, syntactic escapes, weak typing) for which usually a better alternative like an actual function exists. +Furthermore when using function-like `define`s you may need to mark certain headers for IWYU so tracking of used symbols works. + +Memory Management +----------------- + +When allocating memory make sure to free resources properly. +For allocation this project uses a set of tiny wrappers around the common functions `malloc`, `calloc` and `realloc` named `xMalloc`, `xCalloc` and `xRealloc`. +These functions check that memory allocation worked and error out on failure. + +Allocation functions assert the amount of memory requested is non-zero. +Trying to allocate 0 bytes of memory is an error. +Please use the explicit value `NULL` in this case and handle it in your code accordingly. + +Working with Strings +-------------------- + +It is strongly encouraged to use the functions starting with `String_` from `XUtils.h` for working with zero-terminated strings as these make the API easier to use and are intended to make the intent of your code easier to grasp. + +Thus instead of `!strcmp(foo, "foo")` it's preferred to use `String_eq(foo, "foo")` instead. +While sometimes a bit more to type, this helps a lot with making the code easier to follow. + +Styling the code +---------------- + +Now for the style details that can mostly be automated: Indentation, spacing and bracing. +While there is no definitive code style we use, a set of rules loosely enforced has evolved. + +Indentation in the code is done by three (3) spaces. No tabs are used. Ever. + +Before and after keywords should be a space, e.g. `if (condition)` and `do { … } while (condition);`. + +After opening and before closing braces a new line should be started. +Content of such encoded blocks should be indented one level further than their enclosing block. + +If a line of source code becomes too long, or when structuring it into multiple parts for clarity, the continuation line should be indented one more level than the first line it continues: + +```c +if (very_long_condition && + another_very_complex_expression && + something_else_to_check) { + // Code follows as normal ... +} else { + +} +``` + +Braces around simple single code statements (return, break, continue, goto, trivial assignments) are usually left out. + +```c +if (answer) + return 42; +``` + +If it helps readability (with several unrelated if statements in a row) or to avoid dangling-else situations braces can be added. + +Control flow statements and the instruction making up their body should not be put on a single line, +i.e. after the condition of an if statement a new line should be inserted and the body indented accordingly. + +```c +if (answer) + return 42; +else if (again) + continue; +else + break; +``` + +When the statements that form control flow constructs are complex (e.g. more than just a simple assignment or jump) or need explanatory comments you should use braces. +If any block of such a statement uses braces then all blocks of that statement must have braces too. + +```c +if ((fd = open(filename, O_RDONLY)) >= 0 && + (amtRead = read(buffer, sizeof(buffer))) > 0) { + // Parse the information further ... + metric = handleBufferContent(buffer, amtRead); +} else { + metric = -1; +} + +if (fd >= 0) + close(fd); +``` + +While the existing code base isn't fully consistent with this code style yet it is strongly recommended that new code follows these rules. +Adapting surrounding code near places you need to touch is encouraged. +Try to separate such changes into a single, clean-up only commit to reduce noise while reviewing your changes. + +When writing your code consistency with the surrounding codebase is favoured. + +Don't shy away from leaving (single) blank lines to separate different groups of related statements. +They can be a great asset to structure the flow of a method. + +```c + int stuff = 0; + + // If asked for gives only half the answer ... + if (param) + stuff = 21; + + // Compute the answer + stuff %= 2; + stuff *= 4; + stuff *= 5; + stuff += !!stuff; + stuff *= 2; + + return stuff; +``` + +If you want to automate formatting your code, the following command gives you a good baseline of how it should look: + +```bash +astyle -r -xb -s3 -p -xg -c -k1 -W1 \*.c \*.h +``` + +Working with System APIs +------------------------ + +Please try to be considerate when using modern platform features. +While they usually provide quite a performance gain or make your life easier, it is beneficial if `htop` runs on rather ancient systems. +Thus when you want to use such features you should try to have an alternative available that works as a fallback. + +An example for this are functions like `fstatat` on Linux that extend the kernel API on modern systems. +But even though it has been around for over a decade you are asked to provide a POSIX alternative like emulating such calls by `fstat` if this is doable. +If an alternative can not be provided you should gracefully downgrade. That could make a feature that requires this shiny API unavailable on systems that lack support for that API. Make this case visually clear to the user. + +In general, code written for the project should be able to compile on any C99-compliant compiler. + +Writing documentation +--------------------- + +The primary user documentation should be the man file which you can find in `htop.1.in`. + +Additional documentation, like this file, should be written in gh-style markdown. +Make each sentence one line. +Markdown will combined these in output formats. +It does only insert a paragraph if you insert a blank line into the source file. +This way git can better diff and present the changes when documentation is altered. + +Documentation files reside in the `docs/` directory and have a `.md` extension. + +Writing pull-requests (PRs) +--------------------------- + +When writing your PR or patch, the set of patches should contain the minimal changes required. +Each patch in itself should ideally be self-contained and runable. + +A PR should not contain any merge commits. +To follow the uptream branch of your PR rebase your work instead. + +Avoid small commits that just fix typos that another of your commits introduced. +Instead squash those changes in the appropriate commit that introduced that mistake. +Git offers `git commit --fixup=` and `git rebase -i --autosquash` to help you with this. + +Your final PR should contain a minimal set of reasonably sized commits that by themselves are easy to review. + +Rebase early. Rebase often. diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,110 @@ +/* +htop - dragonflybsd/DragonFlyBSDProcess.c +(C) 2015 Hisham H. Muhammad +(C) 2017 Diederik de Groot +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "dragonflybsd/DragonFlyBSDProcess.h" + +#include +#include +#include +#include + +#include "CRT.h" + +#include "dragonflybsd/Platform.h" + + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping (<20s), I Idle, Q Queued for Run, R running, D disk, Z zombie, T traced, W paging, B Blocked, A AskedPage, C Core, J Jailed)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, + [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, + [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process", .flags = 0, }, + [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process", .flags = 0, }, + [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, + [JID] = { .name = "JID", .title = "JID", .description = "Jail prison ID", .flags = 0, .pidColumn = true, }, + [JAIL] = { .name = "JAIL", .title = "JAIL ", .description = "Jail prison name", .flags = 0, }, +}; + +Process* DragonFlyBSDProcess_new(const Settings* settings) { + DragonFlyBSDProcess* this = xCalloc(1, sizeof(DragonFlyBSDProcess)); + Object_setClass(this, Class(DragonFlyBSDProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + DragonFlyBSDProcess* this = (DragonFlyBSDProcess*) cast; + Process_done((Process*)cast); + free(this->jname); + free(this); +} + +static void DragonFlyBSDProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const DragonFlyBSDProcess* fp = (const DragonFlyBSDProcess*) this; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + size_t n = sizeof(buffer) - 1; + switch (field) { + // add Platform-specific fields here + case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, Process_isKernelThread(this) ? -1 : this->pid); break; + case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break; + case JAIL: Process_printLeftAlignedField(str, attr, fp->jname, 11); return; + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int DragonFlyBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const DragonFlyBSDProcess* p1 = (const DragonFlyBSDProcess*)v1; + const DragonFlyBSDProcess* p2 = (const DragonFlyBSDProcess*)v2; + + switch (key) { + // add Platform-specific fields here + case JID: + return SPACESHIP_NUMBER(p1->jid, p2->jid); + case JAIL: + return SPACESHIP_NULLSTR(p1->jname, p2->jname); + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass DragonFlyBSDProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = DragonFlyBSDProcess_writeField, + .compareByKey = DragonFlyBSDProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef HEADER_DragonFlyBSDProcess +#define HEADER_DragonFlyBSDProcess +/* +htop - dragonflybsd/DragonFlyBSDProcess.h +(C) 2015 Hisham H. Muhammad +(C) 2017 Diederik de Groot +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Object.h" +#include "Process.h" +#include "Settings.h" + + +typedef struct DragonFlyBSDProcess_ { + Process super; + int jid; + char* jname; +} DragonFlyBSDProcess; + +extern const ProcessClass DragonFlyBSDProcess_class; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* DragonFlyBSDProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,601 @@ +/* +htop - DragonFlyBSDProcessList.c +(C) 2014 Hisham H. Muhammad +(C) 2017 Diederik de Groot +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "dragonflybsd/DragonFlyBSDProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" + +#include "dragonflybsd/DragonFlyBSDProcess.h" + + +static int MIB_hw_physmem[2]; +static int MIB_vm_stats_vm_v_page_count[4]; +static int pageSize; +static int pageSizeKb; + +static int MIB_vm_stats_vm_v_wire_count[4]; +static int MIB_vm_stats_vm_v_active_count[4]; +static int MIB_vm_stats_vm_v_cache_count[4]; +static int MIB_vm_stats_vm_v_inactive_count[4]; +static int MIB_vm_stats_vm_v_free_count[4]; + +static int MIB_vfs_bufspace[2]; + +static int MIB_kern_cp_time[2]; +static int MIB_kern_cp_times[2]; +static int kernelFScale; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + size_t len; + char errbuf[_POSIX2_LINE_MAX]; + DragonFlyBSDProcessList* dfpl = xCalloc(1, sizeof(DragonFlyBSDProcessList)); + ProcessList* pl = (ProcessList*) dfpl; + ProcessList_init(pl, Class(DragonFlyBSDProcess), usersTable, dynamicMeters, pidMatchList, userId); + + // physical memory in system: hw.physmem + // physical page size: hw.pagesize + // usable pagesize : vm.stats.vm.v_page_size + len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); + + len = sizeof(pageSize); + if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) + CRT_fatalError("Cannot get pagesize by sysctl"); + pageSizeKb = pageSize / ONE_K; + + // usable page count vm.stats.vm.v_page_count + // actually usable memory : vm.stats.vm.v_page_count * vm.stats.vm.v_page_size + len = 4; sysctlnametomib("vm.stats.vm.v_page_count", MIB_vm_stats_vm_v_page_count, &len); + + len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_active_count", MIB_vm_stats_vm_v_active_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_inactive_count", MIB_vm_stats_vm_v_inactive_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_free_count", MIB_vm_stats_vm_v_free_count, &len); + + len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len); + + int cpus = 1; + len = sizeof(cpus); + if (sysctlbyname("hw.ncpu", &cpus, &len, NULL, 0) != 0) { + cpus = 1; + } + + size_t sizeof_cp_time_array = sizeof(unsigned long) * CPUSTATES; + len = 2; sysctlnametomib("kern.cp_time", MIB_kern_cp_time, &len); + dfpl->cp_time_o = xCalloc(cpus, sizeof_cp_time_array); + dfpl->cp_time_n = xCalloc(cpus, sizeof_cp_time_array); + len = sizeof_cp_time_array; + + // fetch initial single (or average) CPU clicks from kernel + sysctl(MIB_kern_cp_time, 2, dfpl->cp_time_o, &len, NULL, 0); + + // on smp box, fetch rest of initial CPU's clicks + if (cpus > 1) { + len = 2; sysctlnametomib("kern.cp_times", MIB_kern_cp_times, &len); + dfpl->cp_times_o = xCalloc(cpus, sizeof_cp_time_array); + dfpl->cp_times_n = xCalloc(cpus, sizeof_cp_time_array); + len = cpus * sizeof_cp_time_array; + sysctl(MIB_kern_cp_times, 2, dfpl->cp_times_o, &len, NULL, 0); + } + + pl->cpuCount = MAXIMUM(cpus, 1); + + if (cpus == 1 ) { + dfpl->cpus = xRealloc(dfpl->cpus, sizeof(CPUData)); + } else { + // on smp we need CPUs + 1 to store averages too (as kernel kindly provides that as well) + dfpl->cpus = xRealloc(dfpl->cpus, (pl->cpuCount + 1) * sizeof(CPUData)); + } + + len = sizeof(kernelFScale); + if (sysctlbyname("kern.fscale", &kernelFScale, &len, NULL, 0) == -1) { + //sane default for kernel provided CPU percentage scaling, at least on x86 machines, in case this sysctl call failed + kernelFScale = 2048; + } + + dfpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf); + if (dfpl->kd == NULL) { + CRT_fatalError("kvm_openfiles() failed"); + } + + return pl; +} + +void ProcessList_delete(ProcessList* this) { + const DragonFlyBSDProcessList* dfpl = (DragonFlyBSDProcessList*) this; + if (dfpl->kd) { + kvm_close(dfpl->kd); + } + + if (dfpl->jails) { + Hashtable_delete(dfpl->jails); + } + free(dfpl->cp_time_o); + free(dfpl->cp_time_n); + free(dfpl->cp_times_o); + free(dfpl->cp_times_n); + free(dfpl->cpus); + + ProcessList_done(this); + free(this); +} + +static inline void DragonFlyBSDProcessList_scanCPUTime(ProcessList* pl) { + const DragonFlyBSDProcessList* dfpl = (DragonFlyBSDProcessList*) pl; + + unsigned int cpus = pl->cpuCount; // actual CPU count + unsigned int maxcpu = cpus; // max iteration (in case we have average + smp) + int cp_times_offset; + + assert(cpus > 0); + + size_t sizeof_cp_time_array; + + unsigned long* cp_time_n; // old clicks state + unsigned long* cp_time_o; // current clicks state + + unsigned long cp_time_d[CPUSTATES]; + double cp_time_p[CPUSTATES]; + + // get averages or single CPU clicks + sizeof_cp_time_array = sizeof(unsigned long) * CPUSTATES; + sysctl(MIB_kern_cp_time, 2, dfpl->cp_time_n, &sizeof_cp_time_array, NULL, 0); + + // get rest of CPUs + if (cpus > 1) { + // on smp systems DragonFlyBSD kernel concats all CPU states into one long array in + // kern.cp_times sysctl OID + // we store averages in dfpl->cpus[0], and actual cores after that + maxcpu = cpus + 1; + sizeof_cp_time_array = cpus * sizeof(unsigned long) * CPUSTATES; + sysctl(MIB_kern_cp_times, 2, dfpl->cp_times_n, &sizeof_cp_time_array, NULL, 0); + } + + for (unsigned int i = 0; i < maxcpu; i++) { + if (cpus == 1) { + // single CPU box + cp_time_n = dfpl->cp_time_n; + cp_time_o = dfpl->cp_time_o; + } else { + if (i == 0 ) { + // average + cp_time_n = dfpl->cp_time_n; + cp_time_o = dfpl->cp_time_o; + } else { + // specific smp cores + cp_times_offset = i - 1; + cp_time_n = dfpl->cp_times_n + (cp_times_offset * CPUSTATES); + cp_time_o = dfpl->cp_times_o + (cp_times_offset * CPUSTATES); + } + } + + // diff old vs new + unsigned long long total_o = 0; + unsigned long long total_n = 0; + unsigned long long total_d = 0; + for (int s = 0; s < CPUSTATES; s++) { + cp_time_d[s] = cp_time_n[s] - cp_time_o[s]; + total_o += cp_time_o[s]; + total_n += cp_time_n[s]; + } + + // totals + total_d = total_n - total_o; + if (total_d < 1 ) { + total_d = 1; + } + + // save current state as old and calc percentages + for (int s = 0; s < CPUSTATES; ++s) { + cp_time_o[s] = cp_time_n[s]; + cp_time_p[s] = ((double)cp_time_d[s]) / ((double)total_d) * 100; + } + + CPUData* cpuData = &(dfpl->cpus[i]); + cpuData->userPercent = cp_time_p[CP_USER]; + cpuData->nicePercent = cp_time_p[CP_NICE]; + cpuData->systemPercent = cp_time_p[CP_SYS]; + cpuData->irqPercent = cp_time_p[CP_INTR]; + cpuData->systemAllPercent = cp_time_p[CP_SYS] + cp_time_p[CP_INTR]; + // this one is not really used, but we store it anyway + cpuData->idlePercent = cp_time_p[CP_IDLE]; + } +} + +static inline void DragonFlyBSDProcessList_scanMemoryInfo(ProcessList* pl) { + DragonFlyBSDProcessList* dfpl = (DragonFlyBSDProcessList*) pl; + + // @etosan: + // memory counter relationships seem to be these: + // total = active + wired + inactive + cache + free + // htop_used (unavail to anybody) = active + wired + // htop_cache (for cache meter) = buffers + cache + // user_free (avail to procs) = buffers + inactive + cache + free + size_t len = sizeof(pl->totalMem); + + //disabled for now, as it is always smaller than phycal amount of memory... + //...to avoid "where is my memory?" questions + //sysctl(MIB_vm_stats_vm_v_page_count, 4, &(pl->totalMem), &len, NULL, 0); + //pl->totalMem *= pageSizeKb; + sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0); + pl->totalMem /= 1024; + + sysctl(MIB_vm_stats_vm_v_active_count, 4, &(dfpl->memActive), &len, NULL, 0); + dfpl->memActive *= pageSizeKb; + + sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(dfpl->memWire), &len, NULL, 0); + dfpl->memWire *= pageSizeKb; + + sysctl(MIB_vfs_bufspace, 2, &(pl->buffersMem), &len, NULL, 0); + pl->buffersMem /= 1024; + + sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0); + pl->cachedMem *= pageSizeKb; + pl->usedMem = dfpl->memActive + dfpl->memWire; + + struct kvm_swap swap[16]; + int nswap = kvm_getswapinfo(dfpl->kd, swap, ARRAYSIZE(swap), 0); + pl->totalSwap = 0; + pl->usedSwap = 0; + for (int i = 0; i < nswap; i++) { + pl->totalSwap += swap[i].ksw_total; + pl->usedSwap += swap[i].ksw_used; + } + pl->totalSwap *= pageSizeKb; + pl->usedSwap *= pageSizeKb; +} + +//static void DragonFlyBSDProcessList_updateExe(const struct kinfo_proc* kproc, Process* proc) { +// const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, kproc->kp_pid }; +// char buffer[2048]; +// size_t size = sizeof(buffer); +// if (sysctl(mib, 4, buffer, &size, NULL, 0) != 0) { +// Process_updateExe(proc, NULL); +// return; +// } +// +// /* Kernel threads return an empty buffer */ +// if (buffer[0] == '\0') { +// Process_updateExe(proc, NULL); +// return; +// } +// +// Process_updateExe(proc, buffer); +//} + +static void DragonFlyBSDProcessList_updateExe(const struct kinfo_proc* kproc, Process* proc) { + if (Process_isKernelThread(proc)) + return; + + char path[32]; + xSnprintf(path, sizeof(path), "/proc/%d/file", kproc->kp_pid); + + char target[PATH_MAX]; + ssize_t ret = readlink(path, target, sizeof(target) - 1); + if (ret <= 0) + return; + + target[ret] = '\0'; + Process_updateExe(proc, target); +} + +static void DragonFlyBSDProcessList_updateCwd(const struct kinfo_proc* kproc, Process* proc) { + const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, kproc->kp_pid }; + char buffer[2048]; + size_t size = sizeof(buffer); + if (sysctl(mib, 4, buffer, &size, NULL, 0) != 0) { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + /* Kernel threads return an empty buffer */ + if (buffer[0] == '\0') { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + free_and_xStrdup(&proc->procCwd, buffer); +} + +static void DragonFlyBSDProcessList_updateProcessName(kvm_t* kd, const struct kinfo_proc* kproc, Process* proc) { + Process_updateComm(proc, kproc->kp_comm); + + char** argv = kvm_getargv(kd, kproc, 0); + if (!argv || !argv[0]) { + Process_updateCmdline(proc, kproc->kp_comm, 0, strlen(kproc->kp_comm)); + return; + } + + size_t len = 0; + for (int i = 0; argv[i]; i++) { + len += strlen(argv[i]) + 1; + } + + char* cmdline = xMalloc(len); + char* at = cmdline; + int end = 0; + for (int i = 0; argv[i]; i++) { + at = stpcpy(at, argv[i]); + if (end == 0) { + end = at - cmdline; + } + *at++ = ' '; + } + at--; + *at = '\0'; + + Process_updateCmdline(proc, cmdline, 0, end); +} + +static inline void DragonFlyBSDProcessList_scanJails(DragonFlyBSDProcessList* dfpl) { + size_t len; + char* jls; /* Jail list */ + char* curpos; + char* nextpos; + + if (sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1) { + CRT_fatalError("initial sysctlbyname / jail.list failed"); + } + +retry: + if (len == 0) + return; + + jls = xMalloc(len); + + if (sysctlbyname("jail.list", jls, &len, NULL, 0) == -1) { + if (errno == ENOMEM) { + free(jls); + goto retry; + } + CRT_fatalError("sysctlbyname / jail.list failed"); + } + + if (dfpl->jails) { + Hashtable_delete(dfpl->jails); + } + + dfpl->jails = Hashtable_new(20, true); + curpos = jls; + while (curpos) { + int jailid; + char* str_hostname; + + nextpos = strchr(curpos, '\n'); + if (nextpos) { + *nextpos++ = 0; + } + + jailid = atoi(strtok(curpos, " ")); + str_hostname = strtok(NULL, " "); + + char* jname = (char*) (Hashtable_get(dfpl->jails, jailid)); + if (jname == NULL) { + jname = xStrdup(str_hostname); + Hashtable_put(dfpl->jails, jailid, jname); + } + + curpos = nextpos; + } + + free(jls); +} + +static char* DragonFlyBSDProcessList_readJailName(DragonFlyBSDProcessList* dfpl, int jailid) { + char* hostname; + char* jname; + + if (jailid != 0 && dfpl->jails && (hostname = (char*)Hashtable_get(dfpl->jails, jailid))) { + jname = xStrdup(hostname); + } else { + jname = xStrdup("-"); + } + + return jname; +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + DragonFlyBSDProcessList* dfpl = (DragonFlyBSDProcessList*) super; + const Settings* settings = super->settings; + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + + DragonFlyBSDProcessList_scanMemoryInfo(super); + DragonFlyBSDProcessList_scanCPUTime(super); + DragonFlyBSDProcessList_scanJails(dfpl); + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + int count = 0; + + // TODO Kernel Threads seem to be skipped, need to figure out the correct flag + const struct kinfo_proc* kprocs = kvm_getprocs(dfpl->kd, KERN_PROC_ALL | (!hideUserlandThreads ? KERN_PROC_FLAG_LWP : 0), 0, &count); + + for (int i = 0; i < count; i++) { + const struct kinfo_proc* kproc = &kprocs[i]; + bool preExisting = false; + bool ATTR_UNUSED isIdleProcess = false; + + // note: dragonflybsd kernel processes all have the same pid, so we misuse the kernel thread address to give them a unique identifier + Process* proc = ProcessList_getProcess(super, kproc->kp_ktaddr ? (pid_t)kproc->kp_ktaddr : kproc->kp_pid, &preExisting, DragonFlyBSDProcess_new); + DragonFlyBSDProcess* dfp = (DragonFlyBSDProcess*) proc; + + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc))); + + if (!preExisting) { + dfp->jid = kproc->kp_jailid; + if (kproc->kp_ktaddr && kproc->kp_flags & P_SYSTEM) { + // dfb kernel threads all have the same pid, so we misuse the kernel thread address to give them a unique identifier + proc->pid = (pid_t)kproc->kp_ktaddr; + proc->isKernelThread = true; + } else { + proc->pid = kproc->kp_pid; // process ID + proc->isKernelThread = false; + } + proc->isUserlandThread = kproc->kp_nthreads > 1; + proc->ppid = kproc->kp_ppid; // parent process id + proc->tpgid = kproc->kp_tpgid; // tty process group id + //proc->tgid = kproc->kp_lwp.kl_tid; // thread group id + proc->tgid = kproc->kp_pid; // thread group id + proc->pgrp = kproc->kp_pgid; // process group id + proc->session = kproc->kp_sid; + proc->st_uid = kproc->kp_uid; // user ID + proc->processor = kproc->kp_lwp.kl_origcpu; + proc->starttime_ctime = kproc->kp_start.tv_sec; + Process_fillStarttimeBuffer(proc); + proc->user = UsersTable_getRef(super->usersTable, proc->st_uid); + + proc->tty_nr = kproc->kp_tdev; // control terminal device number + const char* name = (kproc->kp_tdev != NODEV) ? devname(kproc->kp_tdev, S_IFCHR) : NULL; + if (!name) { + free(proc->tty_name); + proc->tty_name = NULL; + } else { + free_and_xStrdup(&proc->tty_name, name); + } + + DragonFlyBSDProcessList_updateExe(kproc, proc); + DragonFlyBSDProcessList_updateProcessName(dfpl->kd, kproc, proc); + + if (settings->flags & PROCESS_FLAG_CWD) { + DragonFlyBSDProcessList_updateCwd(kproc, proc); + } + + ProcessList_add(super, proc); + + dfp->jname = DragonFlyBSDProcessList_readJailName(dfpl, kproc->kp_jailid); + } else { + proc->processor = kproc->kp_lwp.kl_cpuid; + if (dfp->jid != kproc->kp_jailid) { // process can enter jail anytime + dfp->jid = kproc->kp_jailid; + free(dfp->jname); + dfp->jname = DragonFlyBSDProcessList_readJailName(dfpl, kproc->kp_jailid); + } + // if there are reapers in the system, process can get reparented anytime + proc->ppid = kproc->kp_ppid; + if (proc->st_uid != kproc->kp_uid) { // some processes change users (eg. to lower privs) + proc->st_uid = kproc->kp_uid; + proc->user = UsersTable_getRef(super->usersTable, proc->st_uid); + } + if (settings->updateProcessNames) { + DragonFlyBSDProcessList_updateProcessName(dfpl->kd, kproc, proc); + } + } + + proc->m_virt = kproc->kp_vm_map_size / ONE_K; + proc->m_resident = kproc->kp_vm_rssize * pageSizeKb; + proc->nlwp = kproc->kp_nthreads; // number of lwp thread + proc->time = (kproc->kp_swtime + 5000) / 10000; + + proc->percent_cpu = 100.0 * ((double)kproc->kp_lwp.kl_pctcpu / (double)kernelFScale); + proc->percent_mem = 100.0 * proc->m_resident / (double)(super->totalMem); + + if (proc->percent_cpu > 0.1) { + // system idle process should own all CPU time left regardless of CPU count + if (String_eq("idle", kproc->kp_comm)) { + isIdleProcess = true; + } + } + + if (kproc->kp_lwp.kl_pid != -1) + proc->priority = kproc->kp_lwp.kl_prio; + else + proc->priority = -kproc->kp_lwp.kl_tdprio; + + switch(kproc->kp_lwp.kl_rtprio.type) { + case RTP_PRIO_REALTIME: + proc->nice = PRIO_MIN - 1 - RTP_PRIO_MAX + kproc->kp_lwp.kl_rtprio.prio; + break; + case RTP_PRIO_IDLE: + proc->nice = PRIO_MAX + 1 + kproc->kp_lwp.kl_rtprio.prio; + break; + case RTP_PRIO_THREAD: + proc->nice = PRIO_MIN - 1 - RTP_PRIO_MAX - kproc->kp_lwp.kl_rtprio.prio; + break; + default: + proc->nice = kproc->kp_nice; + break; + } + + // would be nice if we could store multiple states in proc->state (as enum) and have writeField render them + switch (kproc->kp_stat) { + case SIDL: proc->state = 'I'; isIdleProcess = true; break; + case SACTIVE: + switch (kproc->kp_lwp.kl_stat) { + case LSSLEEP: + if (kproc->kp_lwp.kl_flags & LWP_SINTR) // interruptible wait short/long + if (kproc->kp_lwp.kl_slptime >= MAXSLP) { + proc->state = 'I'; + isIdleProcess = true; + } else { + proc->state = 'S'; + } + else if (kproc->kp_lwp.kl_tdflags & TDF_SINTR) // interruptible lwkt wait + proc->state = 'S'; + else if (kproc->kp_paddr) // uninterruptible wait + proc->state = 'D'; + else // uninterruptible lwkt wait + proc->state = 'B'; + break; + case LSRUN: + if (kproc->kp_lwp.kl_stat == LSRUN) { + if (!(kproc->kp_lwp.kl_tdflags & (TDF_RUNNING | TDF_RUNQ))) + proc->state = 'Q'; + else + proc->state = 'R'; + } + break; + case LSSTOP: + proc->state = 'T'; + break; + default: + proc->state = 'A'; + break; + } + break; + case SSTOP: proc->state = 'T'; break; + case SZOMB: proc->state = 'Z'; break; + case SCORE: proc->state = 'C'; break; + default: proc->state = '?'; + } + + if (kproc->kp_flags & P_SWAPPEDOUT) + proc->state = 'W'; + if (kproc->kp_flags & P_TRACED) + proc->state = 'T'; + if (kproc->kp_flags & P_JAILED) + proc->state = 'J'; + + if (Process_isKernelThread(proc)) + super->kernelThreads++; + + super->totalTasks++; + + if (proc->state == 'R') + super->runningTasks++; + + proc->updated = true; + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/DragonFlyBSDProcessList.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,62 @@ +#ifndef HEADER_DragonFlyBSDProcessList +#define HEADER_DragonFlyBSDProcessList +/* +htop - DragonFlyBSDProcessList.h +(C) 2014 Hisham H. Muhammad +(C) 2017 Diederik de Groot +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include // required for kvm.h +#include +#include +#include +#include +#include +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" + +#include "dragonflybsd/DragonFlyBSDProcess.h" + + +typedef struct CPUData_ { + double userPercent; + double nicePercent; + double systemPercent; + double irqPercent; + double idlePercent; + double systemAllPercent; +} CPUData; + +typedef struct DragonFlyBSDProcessList_ { + ProcessList super; + kvm_t* kd; + + unsigned long long int memWire; + unsigned long long int memActive; + unsigned long long int memInactive; + unsigned long long int memFree; + + CPUData* cpus; + + unsigned long* cp_time_o; + unsigned long* cp_time_n; + + unsigned long* cp_times_o; + unsigned long* cp_times_n; + + Hashtable* jails; +} DragonFlyBSDProcessList; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,258 @@ +/* +htop - dragonflybsd/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2017 Diederik de Groot +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "dragonflybsd/Platform.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "ClockMeter.h" +#include "CPUMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "MemoryMeter.h" +#include "ProcessList.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "dragonflybsd/DragonFlyBSDProcess.h" +#include "dragonflybsd/DragonFlyBSDProcessList.h" + + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGURG", .number = 16 }, + { .name = "17 SIGSTOP", .number = 17 }, + { .name = "18 SIGTSTP", .number = 18 }, + { .name = "19 SIGCONT", .number = 19 }, + { .name = "20 SIGCHLD", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGIO", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGINFO", .number = 29 }, + { .name = "30 SIGUSR1", .number = 30 }, + { .name = "31 SIGUSR2", .number = 31 }, + { .name = "32 SIGTHR", .number = 32 }, + { .name = "33 SIGLIBRT", .number = 33 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + NULL +}; + +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + struct timeval bootTime, currTime; + int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t size = sizeof(bootTime); + + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); + if (err) { + return -1; + } + gettimeofday(&currTime, NULL); + + return (int) difftime(currTime.tv_sec, bootTime.tv_sec); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + struct loadavg loadAverage; + int mib[2] = { CTL_VM, VM_LOADAVG }; + size_t size = sizeof(loadAverage); + + int err = sysctl(mib, 2, &loadAverage, &size, NULL, 0); + if (err) { + *one = 0; + *five = 0; + *fifteen = 0; + return; + } + *one = (double) loadAverage.ldavg[0] / loadAverage.fscale; + *five = (double) loadAverage.ldavg[1] / loadAverage.fscale; + *fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale; +} + +int Platform_getMaxPid() { + int maxPid; + size_t size = sizeof(maxPid); + int err = sysctlbyname("kern.pid_max", &maxPid, &size, NULL, 0); + if (err) { + return 999999; + } + return maxPid; +} + +double Platform_setCPUValues(Meter* this, unsigned int cpu) { + const DragonFlyBSDProcessList* fpl = (const DragonFlyBSDProcessList*) this->pl; + unsigned int cpus = this->pl->cpuCount; + const CPUData* cpuData; + + if (cpus == 1) { + // single CPU box has everything in fpl->cpus[0] + cpuData = &(fpl->cpus[0]); + } else { + cpuData = &(fpl->cpus[cpu]); + } + + double percent; + double* v = this->values; + + v[CPU_METER_NICE] = cpuData->nicePercent; + v[CPU_METER_NORMAL] = cpuData->userPercent; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->systemPercent; + v[CPU_METER_IRQ] = cpuData->irqPercent; + this->curItems = 4; + percent = v[0] + v[1] + v[2] + v[3]; + } else { + v[2] = cpuData->systemAllPercent; + this->curItems = 3; + percent = v[0] + v[1] + v[2]; + } + + percent = isnan(percent) ? 0.0 : CLAMP(percent, 0.0, 100.0); + + v[CPU_METER_FREQUENCY] = NAN; + v[CPU_METER_TEMPERATURE] = NAN; + + return percent; +} + +void Platform_setMemoryValues(Meter* this) { + // TODO + const ProcessList* pl = this->pl; + + this->total = pl->totalMem; + this->values[0] = pl->usedMem; + this->values[1] = pl->buffersMem; + // this->values[2] = "shared memory, like tmpfs and shm" + this->values[3] = pl->cachedMem; + // this->values[4] = "available memory" +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = NAN; +} + +char* Platform_getProcessEnv(pid_t pid) { + // TODO + (void)pid; // prevent unused warning + return NULL; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + // TODO + (void)data; + return false; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + // TODO + (void)data; + return false; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + int life; + size_t life_len = sizeof(life); + if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) + *percent = NAN; + else + *percent = life; + + int acline; + size_t acline_len = sizeof(acline); + if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) + *isOnAC = AC_ERROR; + else + *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/Platform.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,102 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - dragonflybsd/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2017 Diederik de Groot +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Macros.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + + +extern const ProcessField Platform_defaultFields[]; + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, unsigned int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +#define PLATFORM_LONG_OPTIONS + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/dragonflybsd/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/dragonflybsd/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_DragonFlyBSDProcessField +#define HEADER_DragonFlyBSDProcessField +/* +htop - dragonflybsd/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + JID = 100, \ + JAIL = 101, \ + \ + DUMMY_BUMP_FIELD = CWD, \ + // End of list + + +#endif /* HEADER_DragonFlyBSDProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DynamicMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/DynamicMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DynamicMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DynamicMeter.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,123 @@ +/* +htop - DynamicMeter.c +(C) 2021 htop dev team +(C) 2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "DynamicMeter.h" + +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "XUtils.h" + + +static const int DynamicMeter_attributes[] = { + DYNAMIC_GRAY, + DYNAMIC_DARKGRAY, + DYNAMIC_RED, + DYNAMIC_GREEN, + DYNAMIC_BLUE, + DYNAMIC_CYAN, + DYNAMIC_MAGENTA, + DYNAMIC_YELLOW, + DYNAMIC_WHITE +}; + +Hashtable* DynamicMeters_new(void) { + return Platform_dynamicMeters(); +} + +typedef struct { + unsigned int key; + const char* name; + bool found; +} DynamicIterator; + +static void DynamicMeter_compare(ht_key_t key, void* value, void* data) { + const DynamicMeter* meter = (const DynamicMeter*)value; + DynamicIterator* iter = (DynamicIterator*)data; + if (String_eq(iter->name, meter->name)) { + iter->found = true; + iter->key = key; + } +} + +bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key) { + DynamicIterator iter = { .key = 0, .name = name, .found = false }; + if (dynamics) + Hashtable_foreach(dynamics, DynamicMeter_compare, &iter); + if (key) + *key = iter.key; + return iter.found; +} + +const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int key) { + const DynamicMeter* meter = Hashtable_get(dynamics, key); + return meter ? meter->name : NULL; +} + +static void DynamicMeter_init(Meter* meter) { + Platform_dynamicMeterInit(meter); +} + +static void DynamicMeter_updateValues(Meter* meter) { + Platform_dynamicMeterUpdateValues(meter); +} + +static void DynamicMeter_display(const Object* cast, RichString* out) { + const Meter* meter = (const Meter*)cast; + Platform_dynamicMeterDisplay(meter, out); +} + +static const char* DynamicMeter_getCaption(const Meter* this) { + const ProcessList* pl = this->pl; + const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, this->param); + if (meter) + return meter->caption ? meter->caption : meter->name; + return this->caption; +} + +static void DynamicMeter_getUiName(const Meter* this, char* name, size_t length) { + const ProcessList* pl = this->pl; + const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, this->param); + if (meter) { + const char* uiName = meter->caption; + if (uiName) { + int len = strlen(uiName); + if (len > 2 && uiName[len - 2] == ':') + len -= 2; + xSnprintf(name, length, "%.*s", len, uiName); + } else { + xSnprintf(name, length, "%s", meter->name); + } + } +} + +const MeterClass DynamicMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = DynamicMeter_display + }, + .init = DynamicMeter_init, + .updateValues = DynamicMeter_updateValues, + .getCaption = DynamicMeter_getCaption, + .getUiName = DynamicMeter_getUiName, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = DynamicMeter_attributes, + .name = "Dynamic", + .uiName = "Dynamic", + .caption = "", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/DynamicMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/DynamicMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/DynamicMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/DynamicMeter.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,26 @@ +#ifndef HEADER_DynamicMeter +#define HEADER_DynamicMeter + +#include "Hashtable.h" +#include "Meter.h" + + +typedef struct DynamicMeter_ { + char name[32]; /* unique name, cannot contain spaces */ + char* caption; + char* description; + unsigned int type; + double maximum; + + void* dynamicData; /* platform-specific meter data */ +} DynamicMeter; + +Hashtable* DynamicMeters_new(void); + +const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int param); + +bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key); + +extern const MeterClass DynamicMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/.editorconfig pcp-5.3.2/vendor/github.com/htop-dev/htop/.editorconfig --- pcp-5.3.1/vendor/github.com/htop-dev/htop/.editorconfig 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/.editorconfig 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,17 @@ +# EditorConfig configuration for htop +# http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file, utf-8 charset +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +# match C source and header files, set indent to three spaces +[*.{c,h}] +indent_style = space +indent_size = 3 +trim_trailing_whitespace = true diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/EnvScreen.c pcp-5.3.2/vendor/github.com/htop-dev/htop/EnvScreen.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/EnvScreen.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/EnvScreen.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,58 @@ +#include "config.h" // IWYU pragma: keep + +#include "EnvScreen.h" + +#include +#include + +#include "Macros.h" +#include "Panel.h" +#include "Platform.h" +#include "ProvideCurses.h" +#include "Vector.h" +#include "XUtils.h" + + +EnvScreen* EnvScreen_new(Process* process) { + EnvScreen* this = xMalloc(sizeof(EnvScreen)); + Object_setClass(this, Class(EnvScreen)); + return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " "); +} + +void EnvScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); +} + +static void EnvScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Environment of process %d - %s", this->process->pid, Process_getCommand(this->process)); +} + +static void EnvScreen_scan(InfoScreen* this) { + Panel* panel = this->display; + int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0); + + Panel_prune(panel); + + char* env = Platform_getProcessEnv(this->process->pid); + if (env) { + for (const char* p = env; *p; p = strrchr(p, 0) + 1) + InfoScreen_addLine(this, p); + free(env); + } + else { + InfoScreen_addLine(this, "Could not read process environment."); + } + + Vector_insertionSort(this->lines); + Vector_insertionSort(panel->items); + Panel_setSelected(panel, idx); +} + +const InfoScreenClass EnvScreen_class = { + .super = { + .extends = Class(Object), + .delete = EnvScreen_delete + }, + .scan = EnvScreen_scan, + .draw = EnvScreen_draw +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/EnvScreen.h pcp-5.3.2/vendor/github.com/htop-dev/htop/EnvScreen.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/EnvScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/EnvScreen.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_EnvScreen +#define HEADER_EnvScreen + +#include "InfoScreen.h" +#include "Object.h" +#include "Process.h" + + +typedef struct EnvScreen_ { + InfoScreen super; +} EnvScreen; + +extern const InfoScreenClass EnvScreen_class; + +EnvScreen* EnvScreen_new(Process* process); + +void EnvScreen_delete(Object* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,111 @@ +/* +htop - FreeBSDProcess.c +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "freebsd/FreeBSDProcess.h" + +#include + +#include "CRT.h" +#include "Macros.h" +#include "Process.h" +#include "RichString.h" +#include "XUtils.h" + + +const char* const nodevStr = "nodev"; + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, + [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of copy-on-write faults", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, + [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process", .flags = 0, }, + [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process", .flags = 0, }, + [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, + [JID] = { .name = "JID", .title = "JID", .description = "Jail prison ID", .flags = 0, .pidColumn = true, }, + [JAIL] = { .name = "JAIL", .title = "JAIL ", .description = "Jail prison name", .flags = 0, }, +}; + +Process* FreeBSDProcess_new(const Settings* settings) { + FreeBSDProcess* this = xCalloc(1, sizeof(FreeBSDProcess)); + Object_setClass(this, Class(FreeBSDProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + FreeBSDProcess* this = (FreeBSDProcess*) cast; + Process_done((Process*)cast); + free(this->jname); + free(this); +} + +static void FreeBSDProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const FreeBSDProcess* fp = (const FreeBSDProcess*) this; + char buffer[256]; + size_t n = sizeof(buffer); + int attr = CRT_colors[DEFAULT_COLOR]; + + switch (field) { + // add FreeBSD-specific fields here + case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break; + case JAIL: + Process_printLeftAlignedField(str, attr, fp->jname ? fp->jname : "N/A", 11); + return; + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const FreeBSDProcess* p1 = (const FreeBSDProcess*)v1; + const FreeBSDProcess* p2 = (const FreeBSDProcess*)v2; + + switch (key) { + // add FreeBSD-specific fields here + case JID: + return SPACESHIP_NUMBER(p1->jid, p2->jid); + case JAIL: + return SPACESHIP_NULLSTR(p1->jname, p2->jname); + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass FreeBSDProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = FreeBSDProcess_writeField, + .compareByKey = FreeBSDProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,31 @@ +#ifndef HEADER_FreeBSDProcess +#define HEADER_FreeBSDProcess +/* +htop - FreeBSDProcess.h +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Object.h" +#include "Process.h" +#include "Settings.h" + + +typedef struct FreeBSDProcess_ { + Process super; + int jid; + char* jname; +} FreeBSDProcess; + +extern const ProcessClass FreeBSDProcess_class; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* FreeBSDProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,599 @@ +/* +htop - FreeBSDProcessList.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "freebsd/FreeBSDProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include // needs to be included before for MAXPATHLEN +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Compat.h" +#include "FreeBSDProcess.h" +#include "Macros.h" +#include "Object.h" +#include "Process.h" +#include "ProcessList.h" +#include "Settings.h" +#include "XUtils.h" +#include "generic/openzfs_sysctl.h" +#include "zfs/ZfsArcStats.h" + + +static int MIB_hw_physmem[2]; +static int MIB_vm_stats_vm_v_page_count[4]; +static int pageSize; +static int pageSizeKb; + +static int MIB_vm_stats_vm_v_wire_count[4]; +static int MIB_vm_stats_vm_v_active_count[4]; +static int MIB_vm_stats_vm_v_cache_count[4]; +static int MIB_vm_stats_vm_v_inactive_count[4]; +static int MIB_vm_stats_vm_v_free_count[4]; + +static int MIB_vfs_bufspace[2]; + +static int MIB_kern_cp_time[2]; +static int MIB_kern_cp_times[2]; +static int kernelFScale; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + size_t len; + char errbuf[_POSIX2_LINE_MAX]; + FreeBSDProcessList* fpl = xCalloc(1, sizeof(FreeBSDProcessList)); + ProcessList* pl = (ProcessList*) fpl; + ProcessList_init(pl, Class(FreeBSDProcess), usersTable, dynamicMeters, pidMatchList, userId); + + // physical memory in system: hw.physmem + // physical page size: hw.pagesize + // usable pagesize : vm.stats.vm.v_page_size + len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); + + len = sizeof(pageSize); + if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) + CRT_fatalError("Cannot get pagesize by sysctl"); + pageSizeKb = pageSize / ONE_K; + + // usable page count vm.stats.vm.v_page_count + // actually usable memory : vm.stats.vm.v_page_count * vm.stats.vm.v_page_size + len = 4; sysctlnametomib("vm.stats.vm.v_page_count", MIB_vm_stats_vm_v_page_count, &len); + + len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_active_count", MIB_vm_stats_vm_v_active_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_inactive_count", MIB_vm_stats_vm_v_inactive_count, &len); + len = 4; sysctlnametomib("vm.stats.vm.v_free_count", MIB_vm_stats_vm_v_free_count, &len); + + len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len); + + openzfs_sysctl_init(&fpl->zfs); + openzfs_sysctl_updateArcStats(&fpl->zfs); + + int smp = 0; + len = sizeof(smp); + + if (sysctlbyname("kern.smp.active", &smp, &len, NULL, 0) != 0 || len != sizeof(smp)) { + smp = 0; + } + + int cpus = 1; + len = sizeof(cpus); + + if (smp) { + int err = sysctlbyname("kern.smp.cpus", &cpus, &len, NULL, 0); + if (err) { + cpus = 1; + } + } else { + cpus = 1; + } + + size_t sizeof_cp_time_array = sizeof(unsigned long) * CPUSTATES; + len = 2; sysctlnametomib("kern.cp_time", MIB_kern_cp_time, &len); + fpl->cp_time_o = xCalloc(cpus, sizeof_cp_time_array); + fpl->cp_time_n = xCalloc(cpus, sizeof_cp_time_array); + len = sizeof_cp_time_array; + + // fetch initial single (or average) CPU clicks from kernel + sysctl(MIB_kern_cp_time, 2, fpl->cp_time_o, &len, NULL, 0); + + // on smp box, fetch rest of initial CPU's clicks + if (cpus > 1) { + len = 2; sysctlnametomib("kern.cp_times", MIB_kern_cp_times, &len); + fpl->cp_times_o = xCalloc(cpus, sizeof_cp_time_array); + fpl->cp_times_n = xCalloc(cpus, sizeof_cp_time_array); + len = cpus * sizeof_cp_time_array; + sysctl(MIB_kern_cp_times, 2, fpl->cp_times_o, &len, NULL, 0); + } + + pl->cpuCount = MAXIMUM(cpus, 1); + + if (cpus == 1 ) { + fpl->cpus = xRealloc(fpl->cpus, sizeof(CPUData)); + } else { + // on smp we need CPUs + 1 to store averages too (as kernel kindly provides that as well) + fpl->cpus = xRealloc(fpl->cpus, (pl->cpuCount + 1) * sizeof(CPUData)); + } + + + len = sizeof(kernelFScale); + if (sysctlbyname("kern.fscale", &kernelFScale, &len, NULL, 0) == -1) { + //sane default for kernel provided CPU percentage scaling, at least on x86 machines, in case this sysctl call failed + kernelFScale = 2048; + } + + fpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf); + if (fpl->kd == NULL) { + CRT_fatalError("kvm_openfiles() failed"); + } + + return pl; +} + +void ProcessList_delete(ProcessList* this) { + const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this; + + if (fpl->kd) { + kvm_close(fpl->kd); + } + + free(fpl->cp_time_o); + free(fpl->cp_time_n); + free(fpl->cp_times_o); + free(fpl->cp_times_n); + free(fpl->cpus); + + ProcessList_done(this); + free(this); +} + +static inline void FreeBSDProcessList_scanCPU(ProcessList* pl) { + const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + + unsigned int cpus = pl->cpuCount; // actual CPU count + unsigned int maxcpu = cpus; // max iteration (in case we have average + smp) + int cp_times_offset; + + assert(cpus > 0); + + size_t sizeof_cp_time_array; + + unsigned long* cp_time_n; // old clicks state + unsigned long* cp_time_o; // current clicks state + + unsigned long cp_time_d[CPUSTATES]; + double cp_time_p[CPUSTATES]; + + // get averages or single CPU clicks + sizeof_cp_time_array = sizeof(unsigned long) * CPUSTATES; + sysctl(MIB_kern_cp_time, 2, fpl->cp_time_n, &sizeof_cp_time_array, NULL, 0); + + // get rest of CPUs + if (cpus > 1) { + // on smp systems FreeBSD kernel concats all CPU states into one long array in + // kern.cp_times sysctl OID + // we store averages in fpl->cpus[0], and actual cores after that + maxcpu = cpus + 1; + sizeof_cp_time_array = cpus * sizeof(unsigned long) * CPUSTATES; + sysctl(MIB_kern_cp_times, 2, fpl->cp_times_n, &sizeof_cp_time_array, NULL, 0); + } + + for (unsigned int i = 0; i < maxcpu; i++) { + if (cpus == 1) { + // single CPU box + cp_time_n = fpl->cp_time_n; + cp_time_o = fpl->cp_time_o; + } else { + if (i == 0 ) { + // average + cp_time_n = fpl->cp_time_n; + cp_time_o = fpl->cp_time_o; + } else { + // specific smp cores + cp_times_offset = i - 1; + cp_time_n = fpl->cp_times_n + (cp_times_offset * CPUSTATES); + cp_time_o = fpl->cp_times_o + (cp_times_offset * CPUSTATES); + } + } + + // diff old vs new + unsigned long long total_o = 0; + unsigned long long total_n = 0; + unsigned long long total_d = 0; + for (int s = 0; s < CPUSTATES; s++) { + cp_time_d[s] = cp_time_n[s] - cp_time_o[s]; + total_o += cp_time_o[s]; + total_n += cp_time_n[s]; + } + + // totals + total_d = total_n - total_o; + if (total_d < 1 ) { + total_d = 1; + } + + // save current state as old and calc percentages + for (int s = 0; s < CPUSTATES; ++s) { + cp_time_o[s] = cp_time_n[s]; + cp_time_p[s] = ((double)cp_time_d[s]) / ((double)total_d) * 100; + } + + CPUData* cpuData = &(fpl->cpus[i]); + cpuData->userPercent = cp_time_p[CP_USER]; + cpuData->nicePercent = cp_time_p[CP_NICE]; + cpuData->systemPercent = cp_time_p[CP_SYS]; + cpuData->irqPercent = cp_time_p[CP_INTR]; + cpuData->systemAllPercent = cp_time_p[CP_SYS] + cp_time_p[CP_INTR]; + // this one is not really used + //cpuData->idlePercent = cp_time_p[CP_IDLE]; + + cpuData->temperature = NAN; + cpuData->frequency = NAN; + + const int coreId = (cpus == 1) ? 0 : ((int)i - 1); + if (coreId < 0) + continue; + + // TODO: test with hyperthreading and multi-cpu systems + if (pl->settings->showCPUTemperature) { + int temperature; + size_t len = sizeof(temperature); + char mibBuffer[32]; + xSnprintf(mibBuffer, sizeof(mibBuffer), "dev.cpu.%d.temperature", coreId); + int r = sysctlbyname(mibBuffer, &temperature, &len, NULL, 0); + if (r == 0) + cpuData->temperature = (double)(temperature - 2732) / 10.0; // convert from deci-Kelvin to Celsius + } + + // TODO: test with hyperthreading and multi-cpu systems + if (pl->settings->showCPUFrequency) { + int frequency; + size_t len = sizeof(frequency); + char mibBuffer[32]; + xSnprintf(mibBuffer, sizeof(mibBuffer), "dev.cpu.%d.freq", coreId); + int r = sysctlbyname(mibBuffer, &frequency, &len, NULL, 0); + if (r == 0) + cpuData->frequency = frequency; // keep in MHz + } + } + + // calculate max temperature and avg frequency for average meter and + // propagate frequency to all cores if only supplied for CPU 0 + if (cpus > 1) { + if (pl->settings->showCPUTemperature) { + double maxTemp = NAN; + for (unsigned int i = 1; i < maxcpu; i++) { + const double coreTemp = fpl->cpus[i].temperature; + if (isnan(coreTemp)) + continue; + + maxTemp = MAXIMUM(maxTemp, coreTemp); + } + + fpl->cpus[0].temperature = maxTemp; + } + + if (pl->settings->showCPUFrequency) { + const double coreZeroFreq = fpl->cpus[1].frequency; + double freqSum = coreZeroFreq; + if (!isnan(coreZeroFreq)) { + for (unsigned int i = 2; i < maxcpu; i++) { + if (isnan(fpl->cpus[i].frequency)) + fpl->cpus[i].frequency = coreZeroFreq; + + freqSum += fpl->cpus[i].frequency; + } + + fpl->cpus[0].frequency = freqSum / (maxcpu - 1); + } + } + } +} + +static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { + FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + + // @etosan: + // memory counter relationships seem to be these: + // total = active + wired + inactive + cache + free + // htop_used (unavail to anybody) = active + wired + // htop_cache (for cache meter) = buffers + cache + // user_free (avail to procs) = buffers + inactive + cache + free + // + // with ZFS ARC situation becomes bit muddled, as ARC behaves like "user_free" + // and belongs into cache, but is reported as wired by kernel + // + // htop_used = active + (wired - arc) + // htop_cache = buffers + cache + arc + u_long totalMem; + u_int memActive, memWire, cachedMem; + long buffersMem; + size_t len; + + //disabled for now, as it is always smaller than phycal amount of memory... + //...to avoid "where is my memory?" questions + //sysctl(MIB_vm_stats_vm_v_page_count, 4, &(pl->totalMem), &len, NULL, 0); + //pl->totalMem *= pageSizeKb; + len = sizeof(totalMem); + sysctl(MIB_hw_physmem, 2, &(totalMem), &len, NULL, 0); + totalMem /= 1024; + pl->totalMem = totalMem; + + len = sizeof(memActive); + sysctl(MIB_vm_stats_vm_v_active_count, 4, &(memActive), &len, NULL, 0); + memActive *= pageSizeKb; + fpl->memActive = memActive; + + len = sizeof(memWire); + sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(memWire), &len, NULL, 0); + memWire *= pageSizeKb; + fpl->memWire = memWire; + + len = sizeof(buffersMem); + sysctl(MIB_vfs_bufspace, 2, &(buffersMem), &len, NULL, 0); + buffersMem /= 1024; + pl->buffersMem = buffersMem; + + len = sizeof(cachedMem); + sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(cachedMem), &len, NULL, 0); + cachedMem *= pageSizeKb; + pl->cachedMem = cachedMem; + + if (fpl->zfs.enabled) { + fpl->memWire -= fpl->zfs.size; + pl->cachedMem += fpl->zfs.size; + } + + pl->usedMem = fpl->memActive + fpl->memWire; + + struct kvm_swap swap[16]; + int nswap = kvm_getswapinfo(fpl->kd, swap, ARRAYSIZE(swap), 0); + pl->totalSwap = 0; + pl->usedSwap = 0; + for (int i = 0; i < nswap; i++) { + pl->totalSwap += swap[i].ksw_total; + pl->usedSwap += swap[i].ksw_used; + } + pl->totalSwap *= pageSizeKb; + pl->usedSwap *= pageSizeKb; +} + +static void FreeBSDProcessList_updateExe(const struct kinfo_proc* kproc, Process* proc) { + const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, kproc->ki_pid }; + char buffer[2048]; + size_t size = sizeof(buffer); + if (sysctl(mib, 4, buffer, &size, NULL, 0) != 0) { + Process_updateExe(proc, NULL); + return; + } + + /* Kernel threads return an empty buffer */ + if (buffer[0] == '\0') { + Process_updateExe(proc, NULL); + return; + } + + Process_updateExe(proc, buffer); +} + +static void FreeBSDProcessList_updateCwd(const struct kinfo_proc* kproc, Process* proc) { + const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, kproc->ki_pid }; + char buffer[2048]; + size_t size = sizeof(buffer); + if (sysctl(mib, 4, buffer, &size, NULL, 0) != 0) { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + /* Kernel threads return an empty buffer */ + if (buffer[0] == '\0') { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + free_and_xStrdup(&proc->procCwd, buffer); +} + +static void FreeBSDProcessList_updateProcessName(kvm_t* kd, const struct kinfo_proc* kproc, Process* proc) { + Process_updateComm(proc, kproc->ki_comm); + + char** argv = kvm_getargv(kd, kproc, 0); + if (!argv || !argv[0]) { + Process_updateCmdline(proc, kproc->ki_comm, 0, strlen(kproc->ki_comm)); + return; + } + + size_t len = 0; + for (int i = 0; argv[i]; i++) { + len += strlen(argv[i]) + 1; + } + + char* cmdline = xMalloc(len); + char* at = cmdline; + int end = 0; + for (int i = 0; argv[i]; i++) { + at = stpcpy(at, argv[i]); + if (end == 0) { + end = at - cmdline; + } + *at++ = ' '; + } + at--; + *at = '\0'; + + Process_updateCmdline(proc, cmdline, 0, end); +} + +static char* FreeBSDProcessList_readJailName(const struct kinfo_proc* kproc) { + if (kproc->ki_jid == 0) + return xStrdup("-"); + + char jnamebuf[MAXHOSTNAMELEN] = {0}; + struct iovec jiov[4]; + +IGNORE_WCASTQUAL_BEGIN + *(const void**)&jiov[0].iov_base = "jid"; + jiov[0].iov_len = sizeof("jid"); + jiov[1].iov_base = (void*) &kproc->ki_jid; + jiov[1].iov_len = sizeof(kproc->ki_jid); + *(const void**)&jiov[2].iov_base = "name"; + jiov[2].iov_len = sizeof("name"); + jiov[3].iov_base = jnamebuf; + jiov[3].iov_len = sizeof(jnamebuf); +IGNORE_WCASTQUAL_END + + int jid = jail_get(jiov, 4, 0); + if (jid == kproc->ki_jid) + return xStrdup(jnamebuf); + + return NULL; +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + FreeBSDProcessList* fpl = (FreeBSDProcessList*) super; + const Settings* settings = super->settings; + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + + openzfs_sysctl_updateArcStats(&fpl->zfs); + FreeBSDProcessList_scanMemoryInfo(super); + FreeBSDProcessList_scanCPU(super); + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + int count = 0; + const struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_PROC, 0, &count); + + for (int i = 0; i < count; i++) { + const struct kinfo_proc* kproc = &kprocs[i]; + bool preExisting = false; + Process* proc = ProcessList_getProcess(super, kproc->ki_pid, &preExisting, FreeBSDProcess_new); + FreeBSDProcess* fp = (FreeBSDProcess*) proc; + + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc))); + + if (!preExisting) { + fp->jid = kproc->ki_jid; + proc->pid = kproc->ki_pid; + proc->isKernelThread = kproc->ki_pid != 0 && kproc->ki_pid != 1 && (kproc->ki_flag & P_SYSTEM); + proc->isUserlandThread = false; + proc->ppid = kproc->ki_ppid; + proc->tpgid = kproc->ki_tpgid; + proc->tgid = kproc->ki_pid; + proc->session = kproc->ki_sid; + proc->pgrp = kproc->ki_pgid; + proc->st_uid = kproc->ki_uid; + proc->starttime_ctime = kproc->ki_start.tv_sec; + Process_fillStarttimeBuffer(proc); + proc->user = UsersTable_getRef(super->usersTable, proc->st_uid); + ProcessList_add(super, proc); + + FreeBSDProcessList_updateExe(kproc, proc); + FreeBSDProcessList_updateProcessName(fpl->kd, kproc, proc); + + if (settings->flags & PROCESS_FLAG_CWD) { + FreeBSDProcessList_updateCwd(kproc, proc); + } + + fp->jname = FreeBSDProcessList_readJailName(kproc); + + proc->tty_nr = kproc->ki_tdev; + const char* name = (kproc->ki_tdev != NODEV) ? devname(kproc->ki_tdev, S_IFCHR) : NULL; + if (!name) { + free(proc->tty_name); + proc->tty_name = NULL; + } else { + free_and_xStrdup(&proc->tty_name, name); + } + } else { + if (fp->jid != kproc->ki_jid) { + // process can enter jail anytime + fp->jid = kproc->ki_jid; + free(fp->jname); + fp->jname = FreeBSDProcessList_readJailName(kproc); + } + // if there are reapers in the system, process can get reparented anytime + proc->ppid = kproc->ki_ppid; + if (proc->st_uid != kproc->ki_uid) { + // some processes change users (eg. to lower privs) + proc->st_uid = kproc->ki_uid; + proc->user = UsersTable_getRef(super->usersTable, proc->st_uid); + } + if (settings->updateProcessNames) { + FreeBSDProcessList_updateProcessName(fpl->kd, kproc, proc); + } + } + + // from FreeBSD source /src/usr.bin/top/machine.c + proc->m_virt = kproc->ki_size / ONE_K; + proc->m_resident = kproc->ki_rssize * pageSizeKb; + proc->nlwp = kproc->ki_numthreads; + proc->time = (kproc->ki_runtime + 5000) / 10000; + + proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale); + proc->percent_mem = 100.0 * proc->m_resident / (double)(super->totalMem); + + if (kproc->ki_stat == SRUN && kproc->ki_oncpu != NOCPU) { + proc->processor = kproc->ki_oncpu; + } else { + proc->processor = kproc->ki_lastcpu; + } + + proc->majflt = kproc->ki_cow; + + proc->priority = kproc->ki_pri.pri_level - PZERO; + + if (String_eq("intr", kproc->ki_comm) && (kproc->ki_flag & P_SYSTEM)) { + proc->nice = 0; //@etosan: intr kernel process (not thread) has weird nice value + } else if (kproc->ki_pri.pri_class == PRI_TIMESHARE) { + proc->nice = kproc->ki_nice - NZERO; + } else if (PRI_IS_REALTIME(kproc->ki_pri.pri_class)) { + proc->nice = PRIO_MIN - 1 - (PRI_MAX_REALTIME - kproc->ki_pri.pri_level); + } else { + proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE; + } + + switch (kproc->ki_stat) { + case SIDL: proc->state = 'I'; break; + case SRUN: proc->state = 'R'; break; + case SSLEEP: proc->state = 'S'; break; + case SSTOP: proc->state = 'T'; break; + case SZOMB: proc->state = 'Z'; break; + case SWAIT: proc->state = 'D'; break; + case SLOCK: proc->state = 'L'; break; + default: proc->state = '?'; + } + + if (Process_isKernelThread(proc)) + super->kernelThreads++; + + super->totalTasks++; + if (proc->state == 'R') + super->runningTasks++; + proc->updated = true; + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/FreeBSDProcessList.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,56 @@ +#ifndef HEADER_FreeBSDProcessList +#define HEADER_FreeBSDProcessList +/* +htop - FreeBSDProcessList.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" +#include "zfs/ZfsArcStats.h" + + +typedef struct CPUData_ { + double userPercent; + double nicePercent; + double systemPercent; + double irqPercent; + double systemAllPercent; + + double frequency; + double temperature; +} CPUData; + +typedef struct FreeBSDProcessList_ { + ProcessList super; + kvm_t* kd; + + unsigned long long int memWire; + unsigned long long int memActive; + + ZfsArcStats zfs; + + CPUData* cpus; + + unsigned long* cp_time_o; + unsigned long* cp_time_n; + + unsigned long* cp_times_o; + unsigned long* cp_times_n; + +} FreeBSDProcessList; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/Platform.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,367 @@ +/* +htop - freebsd/Platform.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "freebsd/Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CPUMeter.h" +#include "ClockMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "DiskIOMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MemoryMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "ProcessList.h" +#include "Settings.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "XUtils.h" +#include "freebsd/FreeBSDProcess.h" +#include "freebsd/FreeBSDProcessList.h" +#include "zfs/ZfsArcMeter.h" +#include "zfs/ZfsCompressedArcMeter.h" + + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGURG", .number = 16 }, + { .name = "17 SIGSTOP", .number = 17 }, + { .name = "18 SIGTSTP", .number = 18 }, + { .name = "19 SIGCONT", .number = 19 }, + { .name = "20 SIGCHLD", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGIO", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGINFO", .number = 29 }, + { .name = "30 SIGUSR1", .number = 30 }, + { .name = "31 SIGUSR2", .number = 31 }, + { .name = "32 SIGTHR", .number = 32 }, + { .name = "33 SIGLIBRT", .number = 33 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + &ZfsArcMeter_class, + &ZfsCompressedArcMeter_class, + &DiskIOMeter_class, + &NetworkIOMeter_class, + NULL +}; + +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + struct timeval bootTime, currTime; + const int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t size = sizeof(bootTime); + + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); + if (err) { + return -1; + } + gettimeofday(&currTime, NULL); + + return (int) difftime(currTime.tv_sec, bootTime.tv_sec); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + struct loadavg loadAverage; + const int mib[2] = { CTL_VM, VM_LOADAVG }; + size_t size = sizeof(loadAverage); + + int err = sysctl(mib, 2, &loadAverage, &size, NULL, 0); + if (err) { + *one = 0; + *five = 0; + *fifteen = 0; + return; + } + *one = (double) loadAverage.ldavg[0] / loadAverage.fscale; + *five = (double) loadAverage.ldavg[1] / loadAverage.fscale; + *fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale; +} + +int Platform_getMaxPid() { + int maxPid; + size_t size = sizeof(maxPid); + int err = sysctlbyname("kern.pid_max", &maxPid, &size, NULL, 0); + if (err) { + return 99999; + } + return maxPid; +} + +double Platform_setCPUValues(Meter* this, unsigned int cpu) { + const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) this->pl; + unsigned int cpus = this->pl->cpuCount; + const CPUData* cpuData; + + if (cpus == 1) { + // single CPU box has everything in fpl->cpus[0] + cpuData = &(fpl->cpus[0]); + } else { + cpuData = &(fpl->cpus[cpu]); + } + + double percent; + double* v = this->values; + + v[CPU_METER_NICE] = cpuData->nicePercent; + v[CPU_METER_NORMAL] = cpuData->userPercent; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->systemPercent; + v[CPU_METER_IRQ] = cpuData->irqPercent; + this->curItems = 4; + percent = v[0] + v[1] + v[2] + v[3]; + } else { + v[2] = cpuData->systemAllPercent; + this->curItems = 3; + percent = v[0] + v[1] + v[2]; + } + + percent = CLAMP(percent, 0.0, 100.0); + + v[CPU_METER_FREQUENCY] = cpuData->frequency; + v[CPU_METER_TEMPERATURE] = cpuData->temperature; + + return percent; +} + +void Platform_setMemoryValues(Meter* this) { + const ProcessList* pl = this->pl; + + this->total = pl->totalMem; + this->values[0] = pl->usedMem; + this->values[1] = pl->buffersMem; + // this->values[2] = "shared memory, like tmpfs and shm" + this->values[3] = pl->cachedMem; + // this->values[4] = "available memory" +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = NAN; +} + +void Platform_setZfsArcValues(Meter* this) { + const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) this->pl; + + ZfsArcMeter_readStats(this, &(fpl->zfs)); +} + +void Platform_setZfsCompressedArcValues(Meter* this) { + const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) this->pl; + + ZfsCompressedArcMeter_readStats(this, &(fpl->zfs)); +} + +char* Platform_getProcessEnv(pid_t pid) { + const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ENV, pid }; + + size_t capacity = ARG_MAX; + char* env = xMalloc(capacity); + + int err = sysctl(mib, 4, env, &capacity, NULL, 0); + if (err || capacity == 0) { + free(env); + return NULL; + } + + if (env[capacity - 1] || env[capacity - 2]) { + env = xRealloc(env, capacity + 2); + env[capacity] = 0; + env[capacity + 1] = 0; + } + + return env; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + + if (devstat_checkversion(NULL) < 0) + return false; + + struct devinfo info = { 0 }; + struct statinfo current = { .dinfo = &info }; + + // get number of devices + if (devstat_getdevs(NULL, ¤t) < 0) + return false; + + int count = current.dinfo->numdevs; + + unsigned long long int bytesReadSum = 0, bytesWriteSum = 0, timeSpendSum = 0; + + // get data + for (int i = 0; i < count; i++) { + uint64_t bytes_read, bytes_write; + long double busy_time; + + devstat_compute_statistics(¤t.dinfo->devices[i], + NULL, + 1.0, + DSM_TOTAL_BYTES_READ, &bytes_read, + DSM_TOTAL_BYTES_WRITE, &bytes_write, + DSM_TOTAL_BUSY_TIME, &busy_time, + DSM_NONE); + + bytesReadSum += bytes_read; + bytesWriteSum += bytes_write; + timeSpendSum += 1000 * busy_time; + } + + data->totalBytesRead = bytesReadSum; + data->totalBytesWritten = bytesWriteSum; + data->totalMsTimeSpend = timeSpendSum; + return true; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + // get number of interfaces + int count; + size_t countLen = sizeof(count); + const int countMib[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT }; + + int r = sysctl(countMib, ARRAYSIZE(countMib), &count, &countLen, NULL, 0); + if (r < 0) + return false; + + memset(data, 0, sizeof(NetworkIOData)); + for (int i = 1; i <= count; i++) { + struct ifmibdata ifmd; + size_t ifmdLen = sizeof(ifmd); + + const int dataMib[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, i, IFDATA_GENERAL }; + + r = sysctl(dataMib, ARRAYSIZE(dataMib), &ifmd, &ifmdLen, NULL, 0); + if (r < 0) + continue; + + if (ifmd.ifmd_flags & IFF_LOOPBACK) + continue; + + data->bytesReceived += ifmd.ifmd_data.ifi_ibytes; + data->packetsReceived += ifmd.ifmd_data.ifi_ipackets; + data->bytesTransmitted += ifmd.ifmd_data.ifi_obytes; + data->packetsTransmitted += ifmd.ifmd_data.ifi_opackets; + } + + return true; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + int life; + size_t life_len = sizeof(life); + if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) + *percent = NAN; + else + *percent = life; + + int acline; + size_t acline_len = sizeof(acline); + if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) + *isOnAC = AC_ERROR; + else + *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/Platform.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,102 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - freebsd/Platform.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + + +extern const ProcessField Platform_defaultFields[]; + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, unsigned int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +void Platform_setZfsArcValues(Meter* this); + +void Platform_setZfsCompressedArcValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +#define PLATFORM_LONG_OPTIONS + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/freebsd/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/freebsd/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_FreeBSDProcessField +#define HEADER_FreeBSDProcessField +/* +htop - freebsd/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + JID = 100, \ + JAIL = 101, \ + \ + DUMMY_BUMP_FIELD = CWD, \ + // End of list + + +#endif /* HEADER_FreeBSDProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/FunctionBar.c pcp-5.3.2/vendor/github.com/htop-dev/htop/FunctionBar.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/FunctionBar.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/FunctionBar.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,152 @@ +/* +htop - FunctionBar.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "FunctionBar.h" + +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static const char* const FunctionBar_FKeys[] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", NULL}; + +static const char* const FunctionBar_FLabels[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", NULL}; + +static int FunctionBar_FEvents[] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10)}; + +static const char* const FunctionBar_EnterEscKeys[] = {"Enter", "Esc", NULL}; +static const int FunctionBar_EnterEscEvents[] = {13, 27}; + +static int currentLen = 0; + +FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc) { + const char* functions[] = {enter, esc, NULL}; + return FunctionBar_new(functions, FunctionBar_EnterEscKeys, FunctionBar_EnterEscEvents); +} + +FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events) { + FunctionBar* this = xCalloc(1, sizeof(FunctionBar)); + this->functions = xCalloc(16, sizeof(char*)); + if (!functions) { + functions = FunctionBar_FLabels; + } + for (int i = 0; i < 15 && functions[i]; i++) { + this->functions[i] = xStrdup(functions[i]); + } + if (keys && events) { + this->staticData = false; + this->keys.keys = xCalloc(15, sizeof(char*)); + this->events = xCalloc(15, sizeof(int)); + int i = 0; + while (i < 15 && functions[i]) { + this->keys.keys[i] = xStrdup(keys[i]); + this->events[i] = events[i]; + i++; + } + this->size = i; + } else { + this->staticData = true; + this->keys.constKeys = FunctionBar_FKeys; + this->events = FunctionBar_FEvents; + this->size = ARRAYSIZE(FunctionBar_FEvents); + } + return this; +} + +void FunctionBar_delete(FunctionBar* this) { + for (int i = 0; i < 15 && this->functions[i]; i++) { + free(this->functions[i]); + } + free(this->functions); + if (!this->staticData) { + for (int i = 0; i < this->size; i++) { + free(this->keys.keys[i]); + } + free(this->keys.keys); + free(this->events); + } + free(this); +} + +void FunctionBar_setLabel(FunctionBar* this, int event, const char* text) { + for (int i = 0; i < this->size; i++) { + if (this->events[i] == event) { + free(this->functions[i]); + this->functions[i] = xStrdup(text); + break; + } + } +} + +void FunctionBar_draw(const FunctionBar* this) { + FunctionBar_drawExtra(this, NULL, -1, false); +} + +void FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor) { + attrset(CRT_colors[FUNCTION_BAR]); + mvhline(LINES - 1, 0, ' ', COLS); + int x = 0; + for (int i = 0; i < this->size; i++) { + attrset(CRT_colors[FUNCTION_KEY]); + mvaddstr(LINES - 1, x, this->keys.constKeys[i]); + x += strlen(this->keys.constKeys[i]); + attrset(CRT_colors[FUNCTION_BAR]); + mvaddstr(LINES - 1, x, this->functions[i]); + x += strlen(this->functions[i]); + } + + if (buffer) { + if (attr == -1) { + attrset(CRT_colors[FUNCTION_BAR]); + } else { + attrset(attr); + } + mvaddstr(LINES - 1, x, buffer); + x += strlen(buffer); + } + + attrset(CRT_colors[RESET_COLOR]); + + if (setCursor) { + CRT_cursorX = x; + curs_set(1); + } else { + curs_set(0); + } + + currentLen = x; +} + +void FunctionBar_append(const char* buffer, int attr) { + if (attr == -1) { + attrset(CRT_colors[FUNCTION_BAR]); + } else { + attrset(attr); + } + mvaddstr(LINES - 1, currentLen + 1, buffer); + attrset(CRT_colors[RESET_COLOR]); + + currentLen += strlen(buffer) + 1; +} + +int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos) { + int x = 0; + for (int i = 0; i < this->size; i++) { + x += strlen(this->keys.constKeys[i]); + x += strlen(this->functions[i]); + if (pos < x) { + return this->events[i]; + } + } + return ERR; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/FunctionBar.h pcp-5.3.2/vendor/github.com/htop-dev/htop/FunctionBar.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/FunctionBar.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/FunctionBar.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,40 @@ +#ifndef HEADER_FunctionBar +#define HEADER_FunctionBar +/* +htop - FunctionBar.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + + +typedef struct FunctionBar_ { + int size; + char** functions; + union { + char** keys; + const char* const* constKeys; + } keys; + int* events; + bool staticData; +} FunctionBar; + +FunctionBar* FunctionBar_newEnterEsc(const char* enter, const char* esc); + +FunctionBar* FunctionBar_new(const char* const* functions, const char* const* keys, const int* events); + +void FunctionBar_delete(FunctionBar* this); + +void FunctionBar_setLabel(FunctionBar* this, int event, const char* text); + +void FunctionBar_draw(const FunctionBar* this); + +void FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor); + +void FunctionBar_append(const char* buffer, int attr); + +int FunctionBar_synthesizeEvent(const FunctionBar* this, int pos); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/gettime.c pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/gettime.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/gettime.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/gettime.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,57 @@ +/* +htop - generic/gettime.c +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +#include "config.h" // IWYU pragma: keep + +#include "generic/gettime.h" + +#include +#include + + +void Generic_gettime_realtime(struct timeval* tvp, uint64_t* msec) { + +#if defined(HAVE_CLOCK_GETTIME) + + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) { + tvp->tv_sec = ts.tv_sec; + tvp->tv_usec = ts.tv_nsec / 1000; + *msec = ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000); + } else { + memset(tvp, 0, sizeof(struct timeval)); + *msec = 0; + } + +#else /* lower resolution gettimeofday(2) is always available */ + + struct timeval tv; + if (gettimeofday(&tv, NULL) == 0) { + *tvp = tv; /* struct copy */ + *msec = ((uint64_t)tv.tv_sec * 1000) + ((uint64_t)tv.tv_usec / 1000); + } else { + memset(tvp, 0, sizeof(struct timeval)); + *msec = 0; + } + +#endif +} + +void Generic_gettime_monotonic(uint64_t* msec) { +#if defined(HAVE_CLOCK_GETTIME) + + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + *msec = ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000); + else + *msec = 0; + +#else + +# error "No monotonic clock available" + +#endif +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/gettime.h pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/gettime.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/gettime.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/gettime.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,18 @@ +#ifndef HEADER_gettime +#define HEADER_gettime +/* +htop - generic/gettime.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + + +void Generic_gettime_realtime(struct timeval* tvp, uint64_t* msec); + +void Generic_gettime_monotonic(uint64_t* msec); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/hostname.c pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/hostname.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/hostname.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/hostname.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,17 @@ +/* +htop - generic/hostname.c +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +#include "config.h" // IWYU pragma: keep + +#include "generic/hostname.h" + +#include + + +void Generic_hostname(char* buffer, size_t size) { + gethostname(buffer, size - 1); + buffer[size - 1] = '\0'; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/hostname.h pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/hostname.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/hostname.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/hostname.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_hostname +#define HEADER_hostname +/* +htop - generic/hostname.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + + +void Generic_hostname(char* buffer, size_t size); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.c pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,98 @@ +/* +htop - generic/openzfs_sysctl.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "generic/openzfs_sysctl.h" + +#include +#include // IWYU pragma: keep +#include // needs for u_int with gcc + +#include "zfs/ZfsArcStats.h" + + +static int MIB_kstat_zfs_misc_arcstats_size[5]; +static int MIB_kstat_zfs_misc_arcstats_c_max[5]; +static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; +static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; +static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; +static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; +static int MIB_kstat_zfs_misc_arcstats_other_size[5]; +static int MIB_kstat_zfs_misc_arcstats_compressed_size[5]; +static int MIB_kstat_zfs_misc_arcstats_uncompressed_size[5]; + +void openzfs_sysctl_init(ZfsArcStats* stats) { + size_t len; + unsigned long long int arcSize; + + len = sizeof(arcSize); + if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arcSize, &len, NULL, 0) == 0 && arcSize != 0) { + stats->enabled = 1; + + len = 5; + sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); + + sysctlnametomib("kstat.zfs.misc.arcstats.c_max", MIB_kstat_zfs_misc_arcstats_c_max, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); + + if (sysctlnametomib("kstat.zfs.misc.arcstats.compressed_size", MIB_kstat_zfs_misc_arcstats_compressed_size, &len) == 0) { + stats->isCompressed = 1; + sysctlnametomib("kstat.zfs.misc.arcstats.uncompressed_size", MIB_kstat_zfs_misc_arcstats_uncompressed_size, &len); + } else { + stats->isCompressed = 0; + } + } else { + stats->enabled = 0; + } +} + +void openzfs_sysctl_updateArcStats(ZfsArcStats* stats) { + size_t len; + + if (stats->enabled) { + len = sizeof(stats->size); + sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(stats->size), &len, NULL, 0); + stats->size /= 1024; + + len = sizeof(stats->max); + sysctl(MIB_kstat_zfs_misc_arcstats_c_max, 5, &(stats->max), &len, NULL, 0); + stats->max /= 1024; + + len = sizeof(stats->MFU); + sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(stats->MFU), &len, NULL, 0); + stats->MFU /= 1024; + + len = sizeof(stats->MRU); + sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(stats->MRU), &len, NULL, 0); + stats->MRU /= 1024; + + len = sizeof(stats->anon); + sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(stats->anon), &len, NULL, 0); + stats->anon /= 1024; + + len = sizeof(stats->header); + sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(stats->header), &len, NULL, 0); + stats->header /= 1024; + + len = sizeof(stats->other); + sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(stats->other), &len, NULL, 0); + stats->other /= 1024; + + if (stats->isCompressed) { + len = sizeof(stats->compressed); + sysctl(MIB_kstat_zfs_misc_arcstats_compressed_size, 5, &(stats->compressed), &len, NULL, 0); + stats->compressed /= 1024; + + len = sizeof(stats->uncompressed); + sysctl(MIB_kstat_zfs_misc_arcstats_uncompressed_size, 5, &(stats->uncompressed), &len, NULL, 0); + stats->uncompressed /= 1024; + } + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.h pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/openzfs_sysctl.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,17 @@ +#ifndef HEADER_openzfs_sysctl +#define HEADER_openzfs_sysctl +/* +htop - generic/openzfs_sysctl.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "zfs/ZfsArcStats.h" + + +void openzfs_sysctl_init(ZfsArcStats* stats); + +void openzfs_sysctl_updateArcStats(ZfsArcStats* stats); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/uname.c pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/uname.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/uname.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/uname.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,98 @@ +/* +htop - generic/uname.c +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +#include "config.h" // IWYU pragma: keep + +#include "generic/uname.h" + +#include +#include +#include + +#include "Macros.h" +#include "XUtils.h" + +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + + +#ifndef OSRELEASEFILE +#define OSRELEASEFILE "/etc/os-release" +#endif + +static void parseOSRelease(char* buffer, size_t bufferLen) { + FILE* stream = fopen(OSRELEASEFILE, "r"); + if (!stream) { + xSnprintf(buffer, bufferLen, "No OS Release"); + return; + } + + char name[64] = {'\0'}; + char version[64] = {'\0'}; + char lineBuffer[256]; + while (fgets(lineBuffer, sizeof(lineBuffer), stream)) { + if (String_startsWith(lineBuffer, "PRETTY_NAME=\"")) { + const char* start = lineBuffer + strlen("PRETTY_NAME=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(buffer, start, MINIMUM(bufferLen, (size_t)(stop - start + 1))); + fclose(stream); + return; + } + if (String_startsWith(lineBuffer, "NAME=\"")) { + const char* start = lineBuffer + strlen("NAME=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(name, start, MINIMUM(sizeof(name), (size_t)(stop - start + 1))); + continue; + } + if (String_startsWith(lineBuffer, "VERSION=\"")) { + const char* start = lineBuffer + strlen("VERSION=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(version, start, MINIMUM(sizeof(version), (size_t)(stop - start + 1))); + continue; + } + } + fclose(stream); + + snprintf(buffer, bufferLen, "%s%s%s", name[0] ? name : "", name[0] && version[0] ? " " : "", version); +} + +char* Generic_uname(void) { + static char savedString[ + /* uname structure fields - manpages recommend sizeof */ + sizeof(((struct utsname*)0)->sysname) + + sizeof(((struct utsname*)0)->release) + + sizeof(((struct utsname*)0)->machine) + + 16/*markup*/ + + 128/*distro*/] = {'\0'}; + static bool loaded_data = false; + + if (!loaded_data) { + struct utsname uname_info; + int uname_result = uname(&uname_info); + + char distro[128]; + parseOSRelease(distro, sizeof(distro)); + + if (uname_result == 0) { + size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine); + if (!String_contains_i(savedString, distro) && sizeof(savedString) > written) + snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro); + } else { + snprintf(savedString, sizeof(savedString), "%s", distro); + } + + loaded_data = true; + } + + return savedString; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/uname.h pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/uname.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/generic/uname.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/generic/uname.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,12 @@ +#ifndef HEADER_uname +#define HEADER_uname +/* +htop - generic/uname.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +char* Generic_uname(void); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/.github/FUNDING.yml pcp-5.3.2/vendor/github.com/htop-dev/htop/.github/FUNDING.yml --- pcp-5.3.1/vendor/github.com/htop-dev/htop/.github/FUNDING.yml 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/.github/FUNDING.yml 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1 @@ +open_collective: htop diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/.github/workflows/ci.yml pcp-5.3.2/vendor/github.com/htop-dev/htop/.github/workflows/ci.yml --- pcp-5.3.1/vendor/github.com/htop-dev/htop/.github/workflows/ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/.github/workflows/ci.yml 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,171 @@ +name: CI + +on: [ push, pull_request ] + +env: + # Enable format attributes in ncurses headers + # Enable fortified memory/string handling + CPPFLAGS: -DGCC_PRINTF -DGCC_SCANF -D_FORTIFY_SOURCE=2 + +jobs: + build-ubuntu-latest-minimal-gcc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends libncursesw5-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-werror --enable-linux-affinity --disable-unicode --disable-sensors + - name: Enable compatibility modes + run: | + sed -i 's/#define HAVE_FSTATAT 1/#undef HAVE_FSTATAT/g' config.h + sed -i 's/#define HAVE_OPENAT 1/#undef HAVE_OPENAT/g' config.h + sed -i 's/#define HAVE_READLINKAT 1/#undef HAVE_READLINKAT/g' config.h + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-werror --enable-linux-affinity --disable-unicode --disable-sensors" + + build-ubuntu-latest-minimal-clang: + runs-on: ubuntu-latest + env: + CC: clang-12 + steps: + - uses: actions/checkout@v2 + - name: install clang repo + run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add - + sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y + sudo apt-get update -q + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends clang-12 libncursesw5-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-werror --enable-linux-affinity --disable-unicode --disable-sensors + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-werror --enable-linux-affinity --disable-unicode --disable-sensors" + + build-ubuntu-latest-full-featured-gcc: + runs-on: ubuntu-latest + # Enable LTO, might trigger additional warnings on advanced inlining + env: + CFLAGS: -O3 -g -flto + LDFLAGS: -O3 -g -flto -Wl,--as-needed + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities' + + build-ubuntu-latest-full-featured-clang: + runs-on: ubuntu-latest + env: + CC: clang-12 + steps: + - uses: actions/checkout@v2 + - name: install clang repo + run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add - + sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y + sudo apt-get update -q + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends clang-12 libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-delayacct --enable-sensors --enable-capabilities' + + build-ubuntu-latest-gcc-static: + runs-on: ubuntu-latest + # Enable LTO, might trigger additional warnings on advanced inlining + env: + CFLAGS: -O3 -g -flto + LDFLAGS: -O3 -g -flto + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends libncursesw5-dev libtinfo-dev libgpm-dev libsensors4-dev libcap-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --disable-delayacct --enable-sensors --enable-capabilities + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --disable-delayacct --enable-sensors --enable-capabilities' + + build-ubuntu-latest-pcp: + # Turns out 'ubuntu-latest' can be older than 20.04, we want PCP v5+ + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends libpcp3-dev libncursesw5-dev libtinfo-dev libgpm-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + # Until Ubuntu catches up with pcp-5.2.3+, cannot use -werror due to: + # passing argument 2 of ‘pmLookupName’ from incompatible pointer type + run: ./configure --enable-pcp --enable-unicode + - name: Build + run: make -k + + build-ubuntu-latest-clang-analyzer: + runs-on: ubuntu-latest + env: + CC: clang-12 + steps: + - uses: actions/checkout@v2 + - name: install clang repo + run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add - + sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main' -y + sudo apt-get update -q + - name: Install Dependencies + run: sudo apt-get install --no-install-recommends clang-12 clang-tools-12 libncursesw5-dev libnl-3-dev libnl-genl-3-dev libsensors4-dev libcap-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: scan-build-12 -analyze-headers --status-bugs ./configure --enable-debug --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-delayacct --enable-sensors --enable-capabilities + - name: Build + run: scan-build-12 -analyze-headers --status-bugs make -j"$(nproc)" + + build-macos-latest-clang: + runs-on: macOS-latest + env: + CC: clang + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: brew install automake + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-werror + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-werror" + + whitespace_check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: check-whitespaces + run: git diff-tree --check $(git hash-object -t tree /dev/null) HEAD diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/.gitignore pcp-5.3.2/vendor/github.com/htop-dev/htop/.gitignore --- pcp-5.3.1/vendor/github.com/htop-dev/htop/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/.gitignore 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,52 @@ +# the binaries: +htop +pcp-htop + +# all object files +*.o + +# skip all backups +*.bak +*~ +.*.sw? + +# skip coverage files +*.gcda +*/*.gcda +*.gcno +*/*.gcno +*.h.gch +*/.dirstamp + +# automake/autoconf related files +.deps/ +Makefile +Makefile.in +INSTALL +aclocal.m4 +autom4te.cache/ +compile +conf*/ +config.guess +config.h +config.h.in +config.log +config.status +config.cache +config.sub +configure +depcomp +htop.1 +install-sh +libtool +ltmain.sh +m4/ +missing +stamp-h1 + +# files related to valgrind/callgrind +callgrind.out.* + +# IDE workspace configurations +/.idea/ +/.vscode/ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Hashtable.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Hashtable.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Hashtable.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Hashtable.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,322 @@ +/* +htop - Hashtable.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "Hashtable.h" + +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "XUtils.h" + + +typedef struct HashtableItem_ { + ht_key_t key; + size_t probe; + void* value; +} HashtableItem; + +struct Hashtable_ { + size_t size; + HashtableItem* buckets; + size_t items; + bool owner; +}; + + +#ifndef NDEBUG + +static void Hashtable_dump(const Hashtable* this) { + fprintf(stderr, "Hashtable %p: size=%zu items=%zu owner=%s\n", + (const void*)this, + this->size, + this->items, + this->owner ? "yes" : "no"); + + size_t items = 0; + for (size_t i = 0; i < this->size; i++) { + fprintf(stderr, " item %5zu: key = %5u probe = %2zu value = %p\n", + i, + this->buckets[i].key, + this->buckets[i].probe, + this->buckets[i].value ? (const void*)this->buckets[i].value : "(nil)"); + + if (this->buckets[i].value) + items++; + } + + fprintf(stderr, "Hashtable %p: items=%zu counted=%zu\n", + (const void*)this, + this->items, + items); +} + +static bool Hashtable_isConsistent(const Hashtable* this) { + size_t items = 0; + for (size_t i = 0; i < this->size; i++) { + if (this->buckets[i].value) + items++; + } + bool res = items == this->items; + if (!res) + Hashtable_dump(this); + return res; +} + +size_t Hashtable_count(const Hashtable* this) { + size_t items = 0; + for (size_t i = 0; i < this->size; i++) { + if (this->buckets[i].value) + items++; + } + assert(items == this->items); + return items; +} + +#endif /* NDEBUG */ + +/* https://oeis.org/A014234 */ +static const uint64_t OEISprimes[] = { + 2, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, + 16381, 32749, 65521, 131071, 262139, 524287, 1048573, + 2097143, 4194301, 8388593, 16777213, 33554393, + 67108859, 134217689, 268435399, 536870909, 1073741789, + 2147483647, 4294967291, 8589934583, 17179869143, + 34359738337, 68719476731, 137438953447 +}; + +static size_t nextPrime(size_t n) { + /* on 32-bit make sure we do not return primes not fitting in size_t */ + for (size_t i = 0; i < ARRAYSIZE(OEISprimes) && OEISprimes[i] < SIZE_MAX; i++) { + if (n <= OEISprimes[i]) + return OEISprimes[i]; + } + + CRT_fatalError("Hashtable: no prime found"); +} + +Hashtable* Hashtable_new(size_t size, bool owner) { + Hashtable* this; + + this = xMalloc(sizeof(Hashtable)); + this->items = 0; + this->size = size ? nextPrime(size) : 13; + this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem)); + this->owner = owner; + + assert(Hashtable_isConsistent(this)); + return this; +} + +void Hashtable_delete(Hashtable* this) { + Hashtable_clear(this); + + free(this->buckets); + free(this); +} + +void Hashtable_clear(Hashtable* this) { + assert(Hashtable_isConsistent(this)); + + if (this->owner) + for (size_t i = 0; i < this->size; i++) + free(this->buckets[i].value); + + memset(this->buckets, 0, this->size * sizeof(HashtableItem)); + this->items = 0; + + assert(Hashtable_isConsistent(this)); +} + +static void insert(Hashtable* this, ht_key_t key, void* value) { + size_t index = key % this->size; + size_t probe = 0; +#ifndef NDEBUG + size_t origIndex = index; +#endif + + for (;;) { + if (!this->buckets[index].value) { + this->items++; + this->buckets[index].key = key; + this->buckets[index].probe = probe; + this->buckets[index].value = value; + return; + } + + if (this->buckets[index].key == key) { + if (this->owner && this->buckets[index].value != value) + free(this->buckets[index].value); + this->buckets[index].value = value; + return; + } + + /* Robin Hood swap */ + if (probe > this->buckets[index].probe) { + HashtableItem tmp = this->buckets[index]; + + this->buckets[index].key = key; + this->buckets[index].probe = probe; + this->buckets[index].value = value; + + key = tmp.key; + probe = tmp.probe; + value = tmp.value; + } + + index = (index + 1) % this->size; + probe++; + + assert(index != origIndex); + } +} + +void Hashtable_setSize(Hashtable* this, size_t size) { + + assert(Hashtable_isConsistent(this)); + + if (size <= this->items) + return; + + HashtableItem* oldBuckets = this->buckets; + size_t oldSize = this->size; + + this->size = nextPrime(size); + this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem)); + this->items = 0; + + /* rehash */ + for (size_t i = 0; i < oldSize; i++) { + if (!oldBuckets[i].value) + continue; + + insert(this, oldBuckets[i].key, oldBuckets[i].value); + } + + free(oldBuckets); + + assert(Hashtable_isConsistent(this)); +} + +void Hashtable_put(Hashtable* this, ht_key_t key, void* value) { + + assert(Hashtable_isConsistent(this)); + assert(this->size > 0); + assert(value); + + /* grow on load-factor > 0.7 */ + if (10 * this->items > 7 * this->size) { + if (SIZE_MAX / 2 < this->size) + CRT_fatalError("Hashtable: size overflow"); + + Hashtable_setSize(this, 2 * this->size); + } + + insert(this, key, value); + + assert(Hashtable_isConsistent(this)); + assert(Hashtable_get(this, key) != NULL); + assert(this->size > this->items); +} + +void* Hashtable_remove(Hashtable* this, ht_key_t key) { + size_t index = key % this->size; + size_t probe = 0; +#ifndef NDEBUG + size_t origIndex = index; +#endif + + assert(Hashtable_isConsistent(this)); + + void* res = NULL; + + while (this->buckets[index].value) { + if (this->buckets[index].key == key) { + if (this->owner) { + free(this->buckets[index].value); + } else { + res = this->buckets[index].value; + } + + size_t next = (index + 1) % this->size; + + while (this->buckets[next].value && this->buckets[next].probe > 0) { + this->buckets[index] = this->buckets[next]; + this->buckets[index].probe -= 1; + + index = next; + next = (index + 1) % this->size; + } + + /* set empty after backward shifting */ + this->buckets[index].value = NULL; + this->items--; + + break; + } + + if (this->buckets[index].probe < probe) + break; + + index = (index + 1) % this->size; + probe++; + + assert(index != origIndex); + } + + assert(Hashtable_isConsistent(this)); + assert(Hashtable_get(this, key) == NULL); + + /* shrink on load-factor < 0.125 */ + if (8 * this->items < this->size) + Hashtable_setSize(this, this->size / 2); + + return res; +} + +void* Hashtable_get(Hashtable* this, ht_key_t key) { + size_t index = key % this->size; + size_t probe = 0; + void* res = NULL; +#ifndef NDEBUG + size_t origIndex = index; +#endif + + assert(Hashtable_isConsistent(this)); + + while (this->buckets[index].value) { + if (this->buckets[index].key == key) { + res = this->buckets[index].value; + break; + } + + if (this->buckets[index].probe < probe) + break; + + index = (index + 1) != this->size ? (index + 1) : 0; + probe++; + + assert(index != origIndex); + } + + return res; +} + +void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) { + assert(Hashtable_isConsistent(this)); + for (size_t i = 0; i < this->size; i++) { + HashtableItem* walk = &this->buckets[i]; + if (walk->value) + f(walk->key, walk->value, userData); + } + assert(Hashtable_isConsistent(this)); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Hashtable.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Hashtable.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Hashtable.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Hashtable.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,42 @@ +#ifndef HEADER_Hashtable +#define HEADER_Hashtable +/* +htop - Hashtable.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + + +typedef unsigned int ht_key_t; + +typedef void(*Hashtable_PairFunction)(ht_key_t key, void* value, void* userdata); + +typedef struct Hashtable_ Hashtable; + +#ifndef NDEBUG + +size_t Hashtable_count(const Hashtable* this); + +#endif /* NDEBUG */ + +Hashtable* Hashtable_new(size_t size, bool owner); + +void Hashtable_delete(Hashtable* this); + +void Hashtable_clear(Hashtable* this); + +void Hashtable_setSize(Hashtable* this, size_t size); + +void Hashtable_put(Hashtable* this, ht_key_t key, void* value); + +void* Hashtable_remove(Hashtable* this, ht_key_t key); + +void* Hashtable_get(Hashtable* this, ht_key_t key); + +void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Header.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Header.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Header.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Header.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,249 @@ +/* +htop - Header.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Header.h" + +#include +#include +#include +#include + +#include "CRT.h" +#include "CPUMeter.h" +#include "DynamicMeter.h" +#include "Macros.h" +#include "Object.h" +#include "Platform.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +Header* Header_new(ProcessList* pl, Settings* settings, int nrColumns) { + Header* this = xCalloc(1, sizeof(Header)); + this->columns = xCalloc(nrColumns, sizeof(Vector*)); + this->settings = settings; + this->pl = pl; + this->nrColumns = nrColumns; + Header_forEachColumn(this, i) { + this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE); + } + return this; +} + +void Header_delete(Header* this) { + Header_forEachColumn(this, i) { + Vector_delete(this->columns[i]); + } + free(this->columns); + free(this); +} + +void Header_populateFromSettings(Header* this) { + Header_forEachColumn(this, col) { + const MeterColumnSettings* colSettings = &this->settings->columns[col]; + for (int i = 0; i < colSettings->len; i++) { + if (!Header_addMeterByName(this, colSettings->names[i], col)) { + continue; + } + if (colSettings->modes[i] != 0) { + Header_setMode(this, i, colSettings->modes[i], col); + } + } + } + Header_calculateHeight(this); +} + +void Header_writeBackToSettings(const Header* this) { + Header_forEachColumn(this, col) { + MeterColumnSettings* colSettings = &this->settings->columns[col]; + + String_freeArray(colSettings->names); + free(colSettings->modes); + + const Vector* vec = this->columns[col]; + int len = Vector_size(vec); + + colSettings->names = xCalloc(len + 1, sizeof(char*)); + colSettings->modes = xCalloc(len, sizeof(int)); + colSettings->len = len; + + for (int i = 0; i < len; i++) { + const Meter* meter = (Meter*) Vector_get(vec, i); + char* name; + if (meter->param && As_Meter(meter) == &DynamicMeter_class) { + const char* dynamic = DynamicMeter_lookup(this->pl->dynamicMeters, meter->param); + xAsprintf(&name, "%s(%s)", As_Meter(meter)->name, dynamic); + } else if (meter->param && As_Meter(meter) == &CPUMeter_class) { + xAsprintf(&name, "%s(%u)", As_Meter(meter)->name, meter->param); + } else { + xAsprintf(&name, "%s", As_Meter(meter)->name); + } + colSettings->names[i] = name; + colSettings->modes[i] = meter->mode; + } + } +} + +bool Header_addMeterByName(Header* this, const char* name, int column) { + Vector* meters = this->columns[column]; + + char* paren = strchr(name, '('); + unsigned int param = 0; + if (paren) { + char* end, dynamic[32] = {0}; + int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter + if (!ok) { + if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter + if ((end = strrchr(dynamic, ')')) == NULL) + return false; // indicate htoprc parse failure + *end = '\0'; + if (!DynamicMeter_search(this->pl->dynamicMeters, dynamic, ¶m)) + return false; // indicates name lookup failure + } + } + *paren = '\0'; + } + for (const MeterClass* const* type = Platform_meterTypes; *type; type++) { + if (String_eq(name, (*type)->name)) { + Meter* meter = Meter_new(this->pl, param, *type); + Vector_add(meters, meter); + break; + } + } + + if (paren) + *paren = '('; + + return true; +} + +void Header_setMode(Header* this, int i, MeterModeId mode, int column) { + Vector* meters = this->columns[column]; + + if (i >= Vector_size(meters)) + return; + + Meter* meter = (Meter*) Vector_get(meters, i); + Meter_setMode(meter, mode); +} + +Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, int column) { + Vector* meters = this->columns[column]; + + Meter* meter = Meter_new(this->pl, param, type); + Vector_add(meters, meter); + return meter; +} + +int Header_size(const Header* this, int column) { + const Vector* meters = this->columns[column]; + return Vector_size(meters); +} + +MeterModeId Header_readMeterMode(const Header* this, int i, int column) { + const Vector* meters = this->columns[column]; + + const Meter* meter = (const Meter*) Vector_get(meters, i); + return meter->mode; +} + +void Header_reinit(Header* this) { + Header_forEachColumn(this, col) { + for (int i = 0; i < Vector_size(this->columns[col]); i++) { + Meter* meter = (Meter*) Vector_get(this->columns[col], i); + if (Meter_initFn(meter)) { + Meter_init(meter); + } + } + } +} + +void Header_draw(const Header* this) { + const int height = this->height; + const int pad = this->pad; + attrset(CRT_colors[RESET_COLOR]); + for (int y = 0; y < height; y++) { + mvhline(y, 0, ' ', COLS); + } + const int width = COLS / this->nrColumns - pad; + int x = pad; + + Header_forEachColumn(this, col) { + Vector* meters = this->columns[col]; + for (int y = (pad / 2), i = 0; i < Vector_size(meters); i++) { + Meter* meter = (Meter*) Vector_get(meters, i); + + int actualWidth; + if (meter->mode == TEXT_METERMODE) + actualWidth = meter->columnWidthCount * width + (meter->columnWidthCount - 1) * (2 * pad + 1); + else + actualWidth = width; + + meter->draw(meter, x, y, actualWidth); + y += meter->h; + } + x += width + pad; + } +} + +void Header_updateData(Header* this) { + Header_forEachColumn(this, col) { + Vector* meters = this->columns[col]; + int items = Vector_size(meters); + for (int i = 0; i < items; i++) { + Meter* meter = (Meter*) Vector_get(meters, i); + Meter_updateValues(meter); + } + } +} + +/* + * Calculate how many columns the current meter is allowed to span, + * by counting how many columns to the right are empty or contain a BlankMeter. + * Returns the number of columns to span, i.e. if the direct neighbor is occupied 1. + */ +static int calcColumnWidthCount(const Header* this, const Meter* curMeter, const int pad, const int curColumn, const int curHeight) { + for (int i = curColumn + 1; i < this->nrColumns; i++) { + const Vector* meters = this->columns[i]; + + int height = pad; + for (int j = 0; j < Vector_size(meters); j++) { + const Meter* meter = (const Meter*) Vector_get(meters, j); + + if (height >= curHeight + curMeter->h) + break; + + height += meter->h; + if (height <= curHeight) + continue; + + if (!Object_isA((const Object*) meter, (const ObjectClass*) &BlankMeter_class)) + return i - curColumn; + } + } + + return this->nrColumns - curColumn; +} + +int Header_calculateHeight(Header* this) { + const int pad = this->settings->headerMargin ? 2 : 0; + int maxHeight = pad; + + Header_forEachColumn(this, col) { + const Vector* meters = this->columns[col]; + int height = pad; + for (int i = 0; i < Vector_size(meters); i++) { + Meter* meter = (Meter*) Vector_get(meters, i); + meter->columnWidthCount = calcColumnWidthCount(this, meter, pad, col, height); + height += meter->h; + } + maxHeight = MAXIMUM(maxHeight, height); + } + this->height = maxHeight; + this->pad = pad; + return maxHeight; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Header.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Header.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Header.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Header.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,53 @@ +#ifndef HEADER_Header +#define HEADER_Header +/* +htop - Header.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" +#include "ProcessList.h" +#include "Settings.h" +#include "Vector.h" + + +typedef struct Header_ { + Vector** columns; + Settings* settings; + ProcessList* pl; + int nrColumns; + int pad; + int height; +} Header; + +#define Header_forEachColumn(this_, i_) for (int (i_)=0; (i_) < (this_)->nrColumns; ++(i_)) + +Header* Header_new(ProcessList* pl, Settings* settings, int nrColumns); + +void Header_delete(Header* this); + +void Header_populateFromSettings(Header* this); + +void Header_writeBackToSettings(const Header* this); + +bool Header_addMeterByName(Header* this, const char* name, int column); + +void Header_setMode(Header* this, int i, MeterModeId mode, int column); + +Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, int column); + +int Header_size(const Header* this, int column); + +MeterModeId Header_readMeterMode(const Header* this, int i, int column); + +void Header_reinit(Header* this); + +void Header_draw(const Header* this); + +void Header_updateData(Header* this); + +int Header_calculateHeight(Header* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/HostnameMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/HostnameMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/HostnameMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/HostnameMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,38 @@ +/* +htop - HostnameMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "HostnameMeter.h" + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" + + +static const int HostnameMeter_attributes[] = { + HOSTNAME +}; + +static void HostnameMeter_updateValues(Meter* this) { + Platform_getHostname(this->txtBuffer, sizeof(this->txtBuffer)); +} + +const MeterClass HostnameMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = HostnameMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = HostnameMeter_attributes, + .name = "Hostname", + .uiName = "Hostname", + .caption = "Hostname: ", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/HostnameMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/HostnameMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/HostnameMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/HostnameMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_HostnameMeter +#define HEADER_HostnameMeter +/* +htop - HostnameMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass HostnameMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.1.in pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.1.in --- pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.1.in 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.1.in 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,567 @@ +.TH "HTOP" "1" "2020" "@PACKAGE_STRING@" "User Commands" +.SH "NAME" +htop \- interactive process viewer +.SH "SYNOPSIS" +.B htop +.RB [ \-dCFhpustvH ] +.SH "DESCRIPTION" +.B htop +is a cross-platform ncurses-based process viewer. +.LP +It is similar to +.BR top , +but allows you to scroll vertically and horizontally, and interact using +a pointing device (mouse). +You can observe all processes running on the system, along with their +command line arguments, as well as view them in a tree format, select +multiple processes and act on them all at once. +.LP +Tasks related to processes (killing, renicing) can be done without +entering their PIDs. +.br +.SH "COMMAND-LINE OPTIONS" +Mandatory arguments to long options are mandatory for short options too. +.TP +\fB\-d \-\-delay=DELAY\fR +Delay between updates, in tenths of a second. If the delay value is +less than 1, it is increased to 1, i.e. 1/10 second. If the delay value +is greater than 100, it is decreased to 100, i.e. 10 seconds. +.TP +\fB\-C \-\-no-color \-\-no-colour\fR +Start +.B htop +in monochrome mode +.TP +\fB\-F \-\-filter=FILTER +Filter processes by command +.TP +\fB\-h \-\-help +Display a help message and exit +.TP +\fB\-p \-\-pid=PID,PID...\fR +Show only the given PIDs +.TP +\fB\-s \-\-sort\-key COLUMN\fR +Sort by this column (use \-\-sort\-key help for a column list). +This will force a list view unless you specify -t at the same time. +.TP +\fB\-u \-\-user=USERNAME\fR +Show only the processes of a given user +.TP +\fB\-U \-\-no-unicode\fR +Do not use unicode but ASCII characters for graph meters +.TP +\fB\-M \-\-no-mouse\fR +Disable support of mouse control +.TP +\fB\-\-readonly\fR +Disable all system and process changing features +.TP +\fB\-V \-\-version +Output version information and exit +.TP +\fB\-t \-\-tree +Show processes in tree view. This can be used to force a tree view when +requesting a sort order with -s. +.TP +\fB\-H \-\-highlight-changes=DELAY\fR +Highlight new and old processes +.TP +\fB \-\-drop-capabilities[=off|basic|strict]\fR +Linux only; requires libcap support. +.br +Drop unneeded Linux capabilities. +In strict mode features like killing, changing process priorities, and reading +process delay accounting information will not work, due to less capabilities +held. +.SH "INTERACTIVE COMMANDS" +The following commands are supported while in +.BR htop : +.TP 5 +.B Up, Alt-k +Select (highlight) the previous process in the process list. Scroll the list +if necessary. +.TP +.B Down, Alt-j +Select (highlight) the next process in the process list. Scroll the list if +necessary. +.TP +.B Left, Alt-h +Scroll the process list left. +.TP +.B Right, Alt-l +Scroll the process list right. +.TP +.B PgUp, PgDn +Scroll the process list up or down one window. +.TP +.B Home +Scroll to the top of the process list and select the first process. +.TP +.B End +Scroll to the bottom of the process list and select the last process. +.TP +.B Ctrl-A, ^ +Scroll left to the beginning of the process entry (i.e. beginning of line). +.TP +.B Ctrl-E, $ +Scroll right to the end of the process entry (i.e. end of line). +.TP +.B Space +Tag or untag a process. Commands that can operate on multiple processes, +like "kill", will then apply over the list of tagged processes, instead +of the currently highlighted one. +.TP +.B c +Tag the current process and its children. Commands that can operate on multiple +processes, like "kill", will then apply over the list of tagged processes, +instead of the currently highlighted one. +.TP +.B U +Untag all processes (remove all tags added with the Space or c keys). +.TP +.B s +Trace process system calls: if strace(1) is installed, pressing this key +will attach it to the currently selected process, presenting a live +update of system calls issued by the process. +.TP +.B l +Display open files for a process: if lsof(1) is installed, pressing this key +will display the list of file descriptors opened by the process. +.TP +.B w +Display the command line of the selected process in a separate screen, wrapped +onto multiple lines as needed. +.TP +.B x +Display the active file locks of the selected process in a separate screen. +.TP +.B F1, h, ? +Go to the help screen +.TP +.B F2, S +Go to the setup screen, where you can configure the meters displayed at the top +of the screen, set various display options, choose among color schemes, and +select which columns are displayed, in which order. +.TP +.B F3, / +Incrementally search the command lines of all the displayed processes. The +currently selected (highlighted) command will update as you type. While in +search mode, pressing F3 will cycle through matching occurrences. +Pressing Shift-F3 will cycle backwards. + +Alternatively the search can be started by simply typing the command +you are looking for, although for the first character normal key +bindings take precedence. +.TP +.B F4, \\\\ +Incremental process filtering: type in part of a process command line and +only processes whose names match will be shown. To cancel filtering, +enter the Filter option again and press Esc. +.TP +.B F5, t +Tree view: organize processes by parenthood, and layout the relations +between them as a tree. Toggling the key will switch between tree and +your previously selected sort view. Selecting a sort view will exit +tree view. +.TP +.B F6, <, > +Selects a field for sorting, also accessible through < and >. +The current sort field is indicated by a highlight in the header. +.TP +.B F7, ] +Increase the selected process's priority (subtract from 'nice' value). +This can only be done by the superuser. +.TP +.B F8, [ +Decrease the selected process's priority (add to 'nice' value) +.TP +.B F9, k +"Kill" process: sends a signal which is selected in a menu, to one or a group +of processes. If processes were tagged, sends the signal to all tagged processes. +If none is tagged, sends to the currently selected process. +.TP +.B F10, q +Quit +.TP +.B I +Invert the sort order: if sort order is increasing, switch to decreasing, and +vice-versa. +.TP +.B +, \-, * +When in tree view mode, expand or collapse subtree. When a subtree is collapsed +a "+" sign shows to the left of the process name. +Pressing "*" will expand or collapse all children of PIDs without parents, so +typically PID 1 (init) and PID 2 (kthreadd on Linux, if kernel threads are shown). +.TP +.B a (on multiprocessor machines) +Set CPU affinity: mark which CPUs a process is allowed to use. +.TP +.B u +Show only processes owned by a specified user. +.TP +.B N +Sort by PID. +.TP +.B M +Sort by memory usage (top compatibility key). +.TP +.B P +Sort by processor usage (top compatibility key). +.TP +.B T +Sort by time (top compatibility key). +.TP +.B F +"Follow" process: if the sort order causes the currently selected process +to move in the list, make the selection bar follow it. This is useful for +monitoring a process: this way, you can keep a process always visible on +screen. When a movement key is used, "follow" loses effect. +.TP +.B K +Hide kernel threads: prevent the threads belonging the kernel to be +displayed in the process list. (This is a toggle key.) +.TP +.B H +Hide user threads: on systems that represent them differently than ordinary +processes (such as recent NPTL-based systems), this can hide threads from +userspace processes in the process list. (This is a toggle key.) +.TP +.B p +Show full paths to running programs, where applicable. (This is a toggle key.) +.TP +.B Z +Pause/resume process updates. +.TP +.B m +Merge exe, comm and cmdline, where applicable. (This is a toggle key.) +.TP +.B Ctrl-L +Refresh: redraw screen and recalculate values. +.TP +.B Numbers +PID search: type in process ID and the selection highlight will be moved to it. +.PD +.SH "COLUMNS" +The following columns can display data about each process. A value of '\-' in +all the rows indicates that a column is unsupported on your system, or +currently unimplemented in +.BR htop . +The names below are the ones used in the +"Available Columns" section of the setup screen. If a different name is +shown in +.BR htop 's +main screen, it is shown below in parenthesis. +.TP 5 +.B Command +The full command line of the process (i.e. program name and arguments). + +If the option 'Merge exe, comm and cmdline in Command' (toggled by the 'm' key) +is active, the executable path (/proc/[pid]/exe) and the command name +(/proc/[pid]/comm) are also shown merged with the command line, if available. + +The program basename is highlighted if set in the configuration. Additional +highlighting can be configured for stale executables (cf. Exe column below). +.TP +.B Comm +The command name of the process obtained from /proc/[pid]/comm, if readable. +.TP +.B Exe +The abbreviated basename of the executable of the process, obtained from +/proc/[pid]/exe, if readable. htop is able to read this file on linux for ALL +the processes only if it has the capability CAP_SYS_PTRACE or root privileges. + +The basename is marked in red if the executable used to run the process has +been replaced or deleted on disk since the process started. This additional +markup can be configured. +.TP +.B PID +The process ID. +.TP +.B STATE (S) +The state of the process: + \fBS\fR for sleeping (idle) + \fBR\fR for running + \fBD\fR for disk sleep (uninterruptible) + \fBZ\fR for zombie (waiting for parent to read its exit status) + \fBT\fR for traced or suspended (e.g by SIGTSTP) + \fBW\fR for paging +.TP +.B PPID +The parent process ID. +.TP +.B PGRP +The process's group ID. +.TP +.B SESSION (SID) +The process's session ID. +.TP +.B TTY +The controlling terminal of the process. +.TP +.B TPGID +The process ID of the foreground process group of the controlling terminal. +.TP +.B MINFLT +The number of page faults happening in the main memory. +.TP +.B CMINFLT +The number of minor faults for the process's waited-for children (see MINFLT above). +.TP +.B MAJFLT +The number of page faults happening out of the main memory. +.TP +.B CMAJFLT +The number of major faults for the process's waited-for children (see MAJFLT above). +.TP +.B UTIME (UTIME+) +The user CPU time, which is the amount of time the process has spent executing +on the CPU in user mode (i.e. everything but system calls), measured in clock +ticks. +.TP +.B STIME (STIME+) +The system CPU time, which is the amount of time the kernel has spent +executing system calls on behalf of the process, measured in clock ticks. +.TP +.B CUTIME (CUTIME+) +The children's user CPU time, which is the amount of time the process's +waited-for children have spent executing in user mode (see UTIME above). +.TP +.B CSTIME (CSTIME+) +The children's system CPU time, which is the amount of time the kernel has spent +executing system calls on behalf of all the process's waited-for children (see +STIME above). +.TP +.B PRIORITY (PRI) +The kernel's internal priority for the process, usually just its nice value +plus twenty. Different for real-time processes. +.TP +.B NICE (NI) +The nice value of a process, from 19 (low priority) to -20 (high priority). A +high value means the process is being nice, letting others have a higher +relative priority. The usual OS permission restrictions for adjusting priority apply. +.TP +.B STARTTIME (START) +The time the process was started. +.TP +.B PROCESSOR (CPU) +The ID of the CPU the process last executed on. +.TP +.B M_VIRT (VIRT) +The size of the virtual memory of the process. +.TP +.B M_RESIDENT (RES) +The resident set size (text + data + stack) of the process (i.e. the size of the +process's used physical memory). +.TP +.B M_SHARE (SHR) +The size of the process's shared pages. +.TP +.B M_TRS (CODE) +The text resident set size of the process (i.e. the size of the process's +executable instructions). +.TP +.B M_DRS (DATA) +The data resident set size (data + stack) of the process (i.e. the size of anything +except the process's executable instructions). +.TP +.B M_LRS (LIB) +The library size of the process. +.TP +.B M_DT (DIRTY) +The size of the dirty pages of the process. +.TP +.B M_SWAP (SWAP) +The size of the process's swapped pages. +.TP +.B M_PSS (PSS) +The proportional set size, same as M_RESIDENT but each page is divided by the +number of processes sharing it. +.TP +.B M_M_PSSWP (PSSWP) +The proportional swap share of this mapping, unlike M_SWAP this does not take +into account swapped out page of underlying shmem objects. +.TP +.B ST_UID (UID) +The user ID of the process owner. +.TP +.B PERCENT_CPU (CPU%) +The percentage of the CPU time that the process is currently using. +This is the default way to represent CPU usage in Linux. Each process can +consume up to 100% which means the full capacity of the core it is running +on. This is sometimes called "Irix mode" e.g. in +.BR top (1). +.TP +.B PERCENT_NORM_CPU (NCPU%) +The percentage of the CPU time that the process is currently using normalized +by CPU count. This is sometimes called "Solaris mode" e.g. in +.BR top (1). +.TP +.B PERCENT_MEM (MEM%) +The percentage of memory the process is currently using (based on the process's +resident memory size, see M_RESIDENT above). +.TP +.B USER +The username of the process owner, or the user ID if the name can't be +determined. +.TP +.B TIME (TIME+) +The time, measured in clock ticks that the process has spent in user and system +time (see UTIME, STIME above). +.TP +.B NLWP +The number of Light-Weight Processes (=threads) in the process. +.TP +.B TGID +The thread group ID. +.TP +.B CTID +OpenVZ container ID, a.k.a virtual environment ID. +.TP +.B VPID +OpenVZ process ID. +.TP +.B VXID +VServer process ID. +.TP +.B RCHAR (RD_CHAR) +The number of bytes the process has read. +.TP +.B WCHAR (WR_CHAR) +The number of bytes the process has written. +.TP +.B SYSCR (RD_SYSC) +The number of read(2) syscalls for the process. +.TP +.B SYSCW (WR_SYSC) +The number of write(2) syscalls for the process. +.TP +.B RBYTES (IO_RBYTES) +Bytes of read(2) I/O for the process. +.TP +.B WBYTES (IO_WBYTES) +Bytes of write(2) I/O for the process. +.TP +.B CNCLWB (IO_CANCEL) +Bytes of cancelled write(2) I/O. +.TP +.B IO_READ_RATE (DISK READ) +The I/O rate of read(2) in bytes per second, for the process. +.TP +.B IO_WRITE_RATE (DISK WRITE) +The I/O rate of write(2) in bytes per second, for the process. +.TP +.B IO_RATE (DISK R/W) +The I/O rate, IO_READ_RATE + IO_WRITE_RATE (see above). +.TP +.B CGROUP +Which cgroup the process is in. +.TP +.B OOM +OOM killer score. +.TP +.B CTXT +Incremental sum of voluntary and nonvoluntary context switches. +.TP +.B IO_PRIORITY (IO) +The I/O scheduling class followed by the priority if the class supports it: + \fBR\fR for Realtime + \fBB\fR for Best-effort + \fBid\fR for Idle +.TP +.B PERCENT_CPU_DELAY (CPUD%) +The percentage of time spent waiting for a CPU (while runnable). Requires CAP_NET_ADMIN. +.TP +.B PERCENT_IO_DELAY (IOD%) +The percentage of time spent waiting for the completion of synchronous block I/O. Requires CAP_NET_ADMIN. +.TP +.B PERCENT_SWAP_DELAY (SWAPD%) +The percentage of time spent swapping in pages. Requires CAP_NET_ADMIN. +.TP +.B COMM +The command name for the process. Requires Linux kernel 2.6.33 or newer. +.TP +.B EXE +The executable file of the process as reported by the kernel. Requires CAP_SYS_PTRACE and PTRACE_MODE_READ_FSCRED. +.TP +.B All other flags +Currently unsupported (always displays '-'). +.SH "EXTERNAL LIBRARIES" +While +.B htop +depends on most of the libraries it uses at build time there are two +noteworthy exceptions to this rule. These exceptions both relate to +data displayed in meters displayed in the header of +.B htop +and were intentionally created as optional runtime dependencies instead. +These exceptions are described below: +.TP +.B libsystemd +The bindings for libsystemd are used in the SystemD meter to determine +the number of active services and the overall system state. Looking for +the functions to determine these information at runtime allows for +builds to support these meters without forcing the package manager +to install these libraries on systems that otherwise don't use systemd. + +Summary: no build time dependency, optional runtime dependency on +.B libsystemd +via dynamic loading, with +.B systemctl(1) +fallback. +.TP +.B libsensors +The bindings for libsensors are used for the CPU temperature readings +in the CPU usage meters if displaying the temperature is enabled through +the setup screen. In order for +.B htop +to show these temperatures correctly though, a proper configuration +of libsensors through its usual configuration files is assumed and that +all CPU cores correspond to temperature sensors from the +.B coretemp +driver with core 0 corresponding to a sensor labelled "Core 0". The +package temperature may be given as "Package id 0". If missing it is +inferred as the maximum value from the available per-core readings. + +Summary: build time dependency on +.B libsensors(3) +C header files, optional runtime dependency on +.B libsensors(3) +via dynamic loading. +.SH "CONFIG FILE" +By default +.B htop +reads its configuration from the XDG-compliant path +.IR ~/.config/htop/htoprc . +The configuration file is overwritten by +.BR htop 's +in-program Setup configuration, so it should not be hand-edited. +If no user configuration exists +.B htop +tries to read the system-wide configuration from +.I @sysconfdir@/htoprc +and as a last resort, falls back to its hard coded defaults. +.LP +You may override the location of the configuration file using the $HTOPRC +environment variable (so you can have multiple configurations for different +machines that share the same home directory, for example). +.SH "MEMORY SIZES" +Memory sizes in +.B htop +are displayed in a human-readable form. +Sizes are printed in powers of 1024. (e.g., 1023M = 1072693248 Bytes) +.LP +The decision to use this convention was made in order to conserve screen +space and make memory size representations consistent throughout +.BR htop . +.SH "SEE ALSO" +.BR proc (5), +.BR top (1), +.BR free (1), +.BR ps (1), +.BR uptime (1) +and +.BR limits.conf (5). +.SH "AUTHORS" +.B htop +was originally developed by Hisham Muhammad. +Nowadays it is maintained by the community at . diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.c pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,16 @@ +/* +htop - htop.c +(C) 2004-2011 Hisham H. Muhammad +(C) 2020-2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "CommandLine.h" + + +int main(int argc, char** argv) { + return CommandLine_run(PACKAGE, argc, argv); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.desktop pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.desktop --- pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.desktop 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.desktop 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,67 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Htop +GenericName=Process Viewer +GenericName[ca]=Visualitzador de processos +GenericName[da]=Procesfremviser +GenericName[de]=Prozessanzeige +GenericName[en_GB]=Process Viewer +GenericName[es]=Visor de procesos +GenericName[fi]=Prosessikatselin +GenericName[fr]=Visualiseur de processus +GenericName[gl]=Visor de procesos +GenericName[it]=Visore dei processi +GenericName[ko]=프로세스 뷰어 +GenericName[nb]=Prosessviser +GenericName[nl]=Viewer van processen +GenericName[nn]=Prosessvisar +GenericName[pl]=Przeglądarka procesów +GenericName[pt]=Visualizador de Processos +GenericName[pt_BR]=Visualizador de processos +GenericName[ru]=Монитор процессов +GenericName[sk]=Prehliadač procesov +GenericName[sl]=Pregledovalnik opravil +GenericName[sr@ijekavian]=Приказивач процеса +GenericName[sr@ijekavianlatin]=Prikazivač procesa +GenericName[sr@latin]=Prikazivač procesa +GenericName[sr]=Приказивач процеса +GenericName[sv]=Processvisning +GenericName[tr]=Süreç Görüntüleyici +GenericName[uk]=Перегляд процесів +GenericName[zh_CN]=进程查看器 +GenericName[zh_TW]=行程檢視器 +Comment=Show System Processes +Comment[ca]=Visualitzeu els processos del sistema +Comment[da]=Vis systemprocesser +Comment[de]=Systemprozesse anzeigen +Comment[en_GB]=Show System Processes +Comment[es]=Mostrar procesos del sistema +Comment[fi]=Katsele järjestelmän prosesseja +Comment[fr]=Affiche les processus système +Comment[gl]=Mostrar os procesos do sistema. +Comment[it]=Mostra processi di sistema +Comment[ko]=시스템 프로세스 보기 +Comment[nb]=Vis systemprosesser +Comment[nl]=Systeemprocessen tonen +Comment[nn]=Vis systemprosessar +Comment[pl]=Pokaż procesy systemowe +Comment[pt]=Mostrar os Processos do Sistema +Comment[pt_BR]=Mostra os processos do sistema +Comment[ru]=Просмотр списка процессов в системе +Comment[sk]=Zobraziť systémové procesy +Comment[sl]=Prikaz sistemskih opravil +Comment[sr@ijekavian]=Приказ системских процеса +Comment[sr@ijekavianlatin]=Prikaz sistemskih procesa +Comment[sr@latin]=Prikaz sistemskih procesa +Comment[sr]=Приказ системских процеса +Comment[sv]=Visa systemprocesser +Comment[tr]=Sistem Süreçlerini Göster +Comment[uk]=Перегляд системних процесів +Comment[zh_CN]=显示系统进程 +Comment[zh_TW]=顯示系統行程 +Icon=htop +Exec=htop +Terminal=true +Categories=System;Monitor;ConsoleOnly; +Keywords=system;process;task Binary files /tmp/tmp1ea27_2w/GSxjPL7CB1/pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.png and /tmp/tmp1ea27_2w/a5K_Oe80wg/pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.png differ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.svg pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.svg --- pcp-5.3.1/vendor/github.com/htop-dev/htop/htop.svg 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/htop.svg 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/IncSet.c pcp-5.3.2/vendor/github.com/htop-dev/htop/IncSet.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/IncSet.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/IncSet.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,234 @@ +/* +htop - IncSet.c +(C) 2005-2012 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "IncSet.h" + +#include +#include +#include + +#include "CRT.h" +#include "ListItem.h" +#include "Object.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static void IncMode_reset(IncMode* mode) { + mode->index = 0; + mode->buffer[0] = 0; +} + +void IncSet_reset(IncSet* this, IncType type) { + IncMode_reset(&this->modes[type]); +} + +void IncSet_setFilter(IncSet* this, const char* filter) { + IncMode* mode = &this->modes[INC_FILTER]; + size_t len = String_safeStrncpy(mode->buffer, filter, sizeof(mode->buffer)); + mode->index = len; + this->filtering = true; +} + +static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL}; +static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "}; +static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR}; + +static inline void IncMode_initSearch(IncMode* search) { + memset(search, 0, sizeof(IncMode)); + search->bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents); + search->isFilter = false; +} + +static const char* const filterFunctions[] = {"Done ", "Clear ", " Filter: ", NULL}; +static const char* const filterKeys[] = {"Enter", "Esc", " "}; +static const int filterEvents[] = {13, 27, ERR}; + +static inline void IncMode_initFilter(IncMode* filter) { + memset(filter, 0, sizeof(IncMode)); + filter->bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents); + filter->isFilter = true; +} + +static inline void IncMode_done(IncMode* mode) { + FunctionBar_delete(mode->bar); +} + +IncSet* IncSet_new(FunctionBar* bar) { + IncSet* this = xMalloc(sizeof(IncSet)); + IncMode_initSearch(&(this->modes[INC_SEARCH])); + IncMode_initFilter(&(this->modes[INC_FILTER])); + this->active = NULL; + this->defaultBar = bar; + this->filtering = false; + this->found = false; + return this; +} + +void IncSet_delete(IncSet* this) { + IncMode_done(&(this->modes[0])); + IncMode_done(&(this->modes[1])); + free(this); +} + +static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) { + const Object* selected = Panel_getSelected(panel); + Panel_prune(panel); + if (this->filtering) { + int n = 0; + const char* incFilter = this->modes[INC_FILTER].buffer; + for (int i = 0; i < Vector_size(lines); i++) { + ListItem* line = (ListItem*)Vector_get(lines, i); + if (String_contains_i(line->value, incFilter)) { + Panel_add(panel, (Object*)line); + if (selected == (Object*)line) { + Panel_setSelected(panel, n); + } + + n++; + } + } + } else { + for (int i = 0; i < Vector_size(lines); i++) { + Object* line = Vector_get(lines, i); + Panel_add(panel, line); + if (selected == line) { + Panel_setSelected(panel, i); + } + } + } +} + +static bool search(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) { + int size = Panel_size(panel); + for (int i = 0; i < size; i++) { + if (String_contains_i(getPanelValue(panel, i), mode->buffer)) { + Panel_setSelected(panel, i); + return true; + } + } + + return false; +} + +static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue, int step) { + int size = Panel_size(panel); + int here = Panel_getSelectedIndex(panel); + int i = here; + for (;;) { + i += step; + if (i == size) { + i = 0; + } + if (i == -1) { + i = size - 1; + } + if (i == here) { + return false; + } + + if (String_contains_i(getPanelValue(panel, i), mode->buffer)) { + Panel_setSelected(panel, i); + return true; + } + } +} + +bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) { + if (ch == ERR) + return true; + + IncMode* mode = this->active; + int size = Panel_size(panel); + bool filterChanged = false; + bool doSearch = true; + if (ch == KEY_F(3) || ch == KEY_F(15)) { + if (size == 0) + return true; + + IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1); + doSearch = false; + } else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) { + if (mode->index < INCMODE_MAX) { + mode->buffer[mode->index] = ch; + mode->index++; + mode->buffer[mode->index] = 0; + if (mode->isFilter) { + filterChanged = true; + if (mode->index == 1) { + this->filtering = true; + } + } + } + } else if (ch == KEY_BACKSPACE || ch == 127) { + if (mode->index > 0) { + mode->index--; + mode->buffer[mode->index] = 0; + if (mode->isFilter) { + filterChanged = true; + if (mode->index == 0) { + this->filtering = false; + IncMode_reset(mode); + } + } + } else { + doSearch = false; + } + } else if (ch == KEY_RESIZE) { + doSearch = (mode->index > 0); + } else { + if (mode->isFilter) { + filterChanged = true; + if (ch == 27) { + this->filtering = false; + IncMode_reset(mode); + } + } else { + if (ch == 27) { + IncMode_reset(mode); + } + } + this->active = NULL; + Panel_setDefaultBar(panel); + doSearch = false; + } + if (doSearch) { + this->found = search(mode, panel, getPanelValue); + } + if (filterChanged && lines) { + updateWeakPanel(this, panel, lines); + } + return filterChanged; +} + +const char* IncSet_getListItemValue(Panel* panel, int i) { + const ListItem* l = (const ListItem*) Panel_get(panel, i); + return l ? l->value : ""; +} + +void IncSet_activate(IncSet* this, IncType type, Panel* panel) { + this->active = &(this->modes[type]); + panel->currentBar = this->active->bar; +} + +void IncSet_drawBar(const IncSet* this) { + if (this->active) { + FunctionBar_drawExtra(this->active->bar, this->active->buffer, (this->active->isFilter || this->found) ? -1 : CRT_colors[FAILED_SEARCH], true); + } else { + FunctionBar_draw(this->defaultBar); + } +} + +int IncSet_synthesizeEvent(IncSet* this, int x) { + if (this->active) { + return FunctionBar_synthesizeEvent(this->active->bar, x); + } else { + return FunctionBar_synthesizeEvent(this->defaultBar, x); + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/IncSet.h pcp-5.3.2/vendor/github.com/htop-dev/htop/IncSet.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/IncSet.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/IncSet.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,64 @@ +#ifndef HEADER_IncSet +#define HEADER_IncSet +/* +htop - IncSet.h +(C) 2005-2012 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + +#include "FunctionBar.h" +#include "Panel.h" +#include "Vector.h" + + +#define INCMODE_MAX 40 + +typedef enum { + INC_SEARCH = 0, + INC_FILTER = 1 +} IncType; + +typedef struct IncMode_ { + char buffer[INCMODE_MAX + 1]; + int index; + FunctionBar* bar; + bool isFilter; +} IncMode; + +typedef struct IncSet_ { + IncMode modes[2]; + IncMode* active; + FunctionBar* defaultBar; + bool filtering; + bool found; +} IncSet; + +static inline const char* IncSet_filter(const IncSet* this) { + return this->filtering ? this->modes[INC_FILTER].buffer : NULL; +} + +void IncSet_setFilter(IncSet* this, const char* filter); + +typedef const char* (*IncMode_GetPanelValue)(Panel*, int); + +void IncSet_reset(IncSet* this, IncType type); + +IncSet* IncSet_new(FunctionBar* bar); + +void IncSet_delete(IncSet* this); + +bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines); + +const char* IncSet_getListItemValue(Panel* panel, int i); + +void IncSet_activate(IncSet* this, IncType type, Panel* panel); + +void IncSet_drawBar(const IncSet* this); + +int IncSet_synthesizeEvent(IncSet* this, int x); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/InfoScreen.c pcp-5.3.2/vendor/github.com/htop-dev/htop/InfoScreen.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/InfoScreen.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/InfoScreen.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,183 @@ +#include "config.h" // IWYU pragma: keep + +#include "InfoScreen.h" + +#include +#include +#include + +#include "CRT.h" +#include "IncSet.h" +#include "ListItem.h" +#include "Object.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static const char* const InfoScreenFunctions[] = {"Search ", "Filter ", "Refresh", "Done ", NULL}; + +static const char* const InfoScreenKeys[] = {"F3", "F4", "F5", "Esc"}; + +static const int InfoScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; + +InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader) { + this->process = process; + if (!bar) { + bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents); + } + this->display = Panel_new(0, 1, COLS, height, Class(ListItem), false, bar); + this->inc = IncSet_new(bar); + this->lines = Vector_new(Vector_type(this->display->items), true, DEFAULT_SIZE); + Panel_setHeader(this->display, panelHeader); + return this; +} + +InfoScreen* InfoScreen_done(InfoScreen* this) { + Panel_delete((Object*)this->display); + IncSet_delete(this->inc); + Vector_delete(this->lines); + return this; +} + +void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + + char title[COLS + 1]; + int len = vsnprintf(title, sizeof(title), fmt, ap); + va_end(ap); + + if (len > COLS) { + memset(&title[COLS - 3], '.', 3); + } + + attrset(CRT_colors[METER_TEXT]); + mvhline(0, 0, ' ', COLS); + mvaddstr(0, 0, title); + attrset(CRT_colors[DEFAULT_COLOR]); + Panel_draw(this->display, true, true, true, false); + + IncSet_drawBar(this->inc); +} + +void InfoScreen_addLine(InfoScreen* this, const char* line) { + Vector_add(this->lines, (Object*) ListItem_new(line, 0)); + const char* incFilter = IncSet_filter(this->inc); + if (!incFilter || String_contains_i(line, incFilter)) { + Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines) - 1)); + } +} + +void InfoScreen_appendLine(InfoScreen* this, const char* line) { + ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1); + ListItem_append(last, line); + const char* incFilter = IncSet_filter(this->inc); + if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter)) { + Panel_add(this->display, (Object*)last); + } +} + +void InfoScreen_run(InfoScreen* this) { + Panel* panel = this->display; + + if (As_InfoScreen(this)->scan) + InfoScreen_scan(this); + + InfoScreen_draw(this); + + bool looping = true; + while (looping) { + + Panel_draw(panel, false, true, true, false); + IncSet_drawBar(this->inc); + + if (this->inc->active) { + (void) move(LINES - 1, CRT_cursorX); + } +#ifdef HAVE_SET_ESCDELAY + set_escdelay(25); +#endif + int ch = getch(); + + if (ch == ERR) { + if (As_InfoScreen(this)->onErr) { + InfoScreen_onErr(this); + continue; + } + } + +#ifdef HAVE_GETMOUSE + if (ch == KEY_MOUSE) { + MEVENT mevent; + int ok = getmouse(&mevent); + if (ok == OK) { + if (mevent.bstate & BUTTON1_RELEASED) { + if (mevent.y >= panel->y && mevent.y < LINES - 1) { + Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1); + ch = 0; + } else if (mevent.y == LINES - 1) { + ch = IncSet_synthesizeEvent(this->inc, mevent.x); + } + } + #if NCURSES_MOUSE_VERSION > 1 + else if (mevent.bstate & BUTTON4_PRESSED) { + ch = KEY_WHEELUP; + } else if (mevent.bstate & BUTTON5_PRESSED) { + ch = KEY_WHEELDOWN; + } + #endif + } + } +#endif + + if (this->inc->active) { + IncSet_handleKey(this->inc, ch, panel, IncSet_getListItemValue, this->lines); + continue; + } + + switch(ch) { + case ERR: + continue; + case KEY_F(3): + case '/': + IncSet_activate(this->inc, INC_SEARCH, panel); + break; + case KEY_F(4): + case '\\': + IncSet_activate(this->inc, INC_FILTER, panel); + break; + case KEY_F(5): + clear(); + if (As_InfoScreen(this)->scan) { + Vector_prune(this->lines); + InfoScreen_scan(this); + } + + InfoScreen_draw(this); + break; + case '\014': // Ctrl+L + clear(); + InfoScreen_draw(this); + break; + case 27: + case 'q': + case KEY_F(10): + looping = false; + break; + case KEY_RESIZE: + Panel_resize(panel, COLS, LINES - 2); + if (As_InfoScreen(this)->scan) { + Vector_prune(this->lines); + InfoScreen_scan(this); + } + + InfoScreen_draw(this); + break; + default: + if (As_InfoScreen(this)->onKey && InfoScreen_onKey(this, ch)) { + continue; + } + Panel_onKey(panel, ch); + } + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/InfoScreen.h pcp-5.3.2/vendor/github.com/htop-dev/htop/InfoScreen.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/InfoScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/InfoScreen.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,55 @@ +#ifndef HEADER_InfoScreen +#define HEADER_InfoScreen + +#include + +#include "FunctionBar.h" +#include "IncSet.h" +#include "Macros.h" +#include "Object.h" +#include "Panel.h" +#include "Process.h" +#include "Vector.h" + + +typedef struct InfoScreen_ { + Object super; + const Process* process; + Panel* display; + IncSet* inc; + Vector* lines; +} InfoScreen; + +typedef void(*InfoScreen_Scan)(InfoScreen*); +typedef void(*InfoScreen_Draw)(InfoScreen*); +typedef void(*InfoScreen_OnErr)(InfoScreen*); +typedef bool(*InfoScreen_OnKey)(InfoScreen*, int); + +typedef struct InfoScreenClass_ { + const ObjectClass super; + const InfoScreen_Scan scan; + const InfoScreen_Draw draw; + const InfoScreen_OnErr onErr; + const InfoScreen_OnKey onKey; +} InfoScreenClass; + +#define As_InfoScreen(this_) ((const InfoScreenClass*)(((InfoScreen*)(this_))->super.klass)) +#define InfoScreen_scan(this_) As_InfoScreen(this_)->scan((InfoScreen*)(this_)) +#define InfoScreen_draw(this_) As_InfoScreen(this_)->draw((InfoScreen*)(this_)) +#define InfoScreen_onErr(this_) As_InfoScreen(this_)->onErr((InfoScreen*)(this_)) +#define InfoScreen_onKey(this_, ch_) As_InfoScreen(this_)->onKey((InfoScreen*)(this_), ch_) + +InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBar* bar, int height, const char* panelHeader); + +InfoScreen* InfoScreen_done(InfoScreen* this); + +ATTR_FORMAT(printf, 2, 3) +void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...); + +void InfoScreen_addLine(InfoScreen* this, const char* line); + +void InfoScreen_appendLine(InfoScreen* this, const char* line); + +void InfoScreen_run(InfoScreen* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/iwyu/htop.imp pcp-5.3.2/vendor/github.com/htop-dev/htop/iwyu/htop.imp --- pcp-5.3.1/vendor/github.com/htop-dev/htop/iwyu/htop.imp 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/iwyu/htop.imp 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,20 @@ +[ + { include: ["", "private", "\"ProvideCurses.h\"", "public"] }, + { include: ["", "private", "\"ProvideCurses.h\"", "public"] }, + { include: ["", "private", "\"ProvideCurses.h\"", "public"] }, + { include: ["", "private", "\"ProvideCurses.h\"", "public"] }, + + { include: ["", "private", "", "public"] }, + + { include: ["", "private", "", "public"] }, + + { include: ["", "private", "", "public"] }, + + { include: ["", "private", "", "public"] }, + + { include: ["", "private", "", "public"] }, + + { include: ["", "private", "", "public"] }, + + { include: ["", "private", "", "public"] }, +] diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/iwyu/run_iwyu.sh pcp-5.3.2/vendor/github.com/htop-dev/htop/iwyu/run_iwyu.sh --- pcp-5.3.1/vendor/github.com/htop-dev/htop/iwyu/run_iwyu.sh 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/iwyu/run_iwyu.sh 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,14 @@ +#!/bin/sh + +SCRIPT=$(readlink -f "$0") +SCRIPTDIR=$(dirname "$SCRIPT") +SOURCEDIR="$SCRIPTDIR/.." + +PKG_NL3=$(pkg-config --cflags libnl-3.0) + +IWYU=${IWYU:-iwyu} + +cd "$SOURCEDIR" || exit + +make clean +make -k -s CC="$IWYU" CFLAGS="-Xiwyu --no_comments -Xiwyu --no_fwd_decl -Xiwyu --mapping_file='$SCRIPTDIR/htop.imp' $PKG_NL3" diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/HugePageMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/HugePageMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/HugePageMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/HugePageMeter.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,107 @@ +/* +htop - HugePageMeter.c +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "linux/HugePageMeter.h" + +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "ProcessList.h" +#include "RichString.h" +#include "linux/LinuxProcessList.h" + + +static const char* HugePageMeter_active_labels[4] = { NULL, NULL, NULL, NULL }; + +static const int HugePageMeter_attributes[] = { + HUGEPAGE_1, + HUGEPAGE_2, + HUGEPAGE_3, + HUGEPAGE_4, +}; + +static const char* const HugePageMeter_labels[] = { + " 64K:", " 128K:", " 256K:", " 512K:", + " 1M:", " 2M:", " 4M:", " 8M:", " 16M:", " 32M:", " 64M:", " 128M:", " 256M:", " 512M:", + " 1G:", " 2G:", " 4G:", " 8G:", " 16G:", " 32G:", " 64G:", " 128G:", " 256G:", " 512G:", +}; + +static void HugePageMeter_updateValues(Meter* this) { + assert(ARRAYSIZE(HugePageMeter_labels) == HTOP_HUGEPAGE_COUNT); + + char* buffer = this->txtBuffer; + size_t size = sizeof(this->txtBuffer); + int written; + memory_t usedTotal = 0; + unsigned nextUsed = 0; + + const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl; + this->total = lpl->totalHugePageMem; + this->values[0] = 0; + HugePageMeter_active_labels[0] = " used:"; + for (unsigned i = 1; i < ARRAYSIZE(HugePageMeter_active_labels); i++) { + this->values[i] = NAN; + HugePageMeter_active_labels[i] = NULL; + } + for (unsigned i = 0; i < HTOP_HUGEPAGE_COUNT; i++) { + memory_t value = lpl->usedHugePageMem[i]; + if (value != MEMORY_MAX) { + this->values[nextUsed] = value; + usedTotal += value; + HugePageMeter_active_labels[nextUsed] = HugePageMeter_labels[i]; + if (++nextUsed == ARRAYSIZE(HugePageMeter_active_labels)) { + break; + } + } + } + + written = Meter_humanUnit(buffer, usedTotal, size); + METER_BUFFER_CHECK(buffer, size, written); + + METER_BUFFER_APPEND_CHR(buffer, size, '/'); + + Meter_humanUnit(buffer, this->total, size); +} + +static void HugePageMeter_display(const Object* cast, RichString* out) { + char buffer[50]; + const Meter* this = (const Meter*)cast; + + RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + + for (unsigned i = 0; i < ARRAYSIZE(HugePageMeter_active_labels); i++) { + if (isnan(this->values[i])) { + break; + } + RichString_appendAscii(out, CRT_colors[METER_TEXT], HugePageMeter_active_labels[i]); + Meter_humanUnit(buffer, this->values[i], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[HUGEPAGE_1 + i], buffer); + } +} + +const MeterClass HugePageMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = HugePageMeter_display, + }, + .updateValues = HugePageMeter_updateValues, + .defaultMode = BAR_METERMODE, + .maxItems = ARRAYSIZE(HugePageMeter_active_labels), + .total = 100.0, + .attributes = HugePageMeter_attributes, + .name = "HugePages", + .uiName = "HugePages", + .caption = "HP" +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/HugePageMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/HugePageMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/HugePageMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/HugePageMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_HugePageMeter +#define HEADER_HugePageMeter +/* +htop - HugePageMeter.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass HugePageMeter_class; + +#endif /* HEADER_HugePageMeter */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/IOPriority.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/IOPriority.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/IOPriority.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/IOPriority.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,38 @@ +#ifndef HEADER_IOPriority +#define HEADER_IOPriority +/* +htop - IOPriority.h +(C) 2004-2012 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. + +Based on ionice, +Copyright (C) 2005 Jens Axboe +Released under the terms of the GNU General Public License version 2 +*/ + +enum { + IOPRIO_CLASS_NONE, + IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE, + IOPRIO_CLASS_IDLE, +}; + +#define IOPRIO_WHO_PROCESS 1 + +#define IOPRIO_CLASS_SHIFT (13) +#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) + +#define IOPriority_class(ioprio_) ((int) ((ioprio_) >> IOPRIO_CLASS_SHIFT) ) +#define IOPriority_data(ioprio_) ((int) ((ioprio_) & IOPRIO_PRIO_MASK) ) + +typedef int IOPriority; + +#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | (data_)) + +#define IOPriority_error 0xffffffff + +#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0) +#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 7) + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,57 @@ +/* +htop - IOPriorityPanel.c +(C) 2004-2012 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "linux/IOPriorityPanel.h" + +#include +#include + +#include "FunctionBar.h" +#include "ListItem.h" +#include "Object.h" +#include "XUtils.h" +#include "IOPriority.h" + + +Panel* IOPriorityPanel_new(IOPriority currPrio) { + Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Set ", "Cancel ")); + + Panel_setHeader(this, "IO Priority:"); + Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None)); + if (currPrio == IOPriority_None) { + Panel_setSelected(this, 0); + } + static const struct { + int klass; + const char* name; + } classes[] = { + { .klass = IOPRIO_CLASS_RT, .name = "Realtime" }, + { .klass = IOPRIO_CLASS_BE, .name = "Best-effort" }, + { .klass = 0, .name = NULL } + }; + for (int c = 0; classes[c].name; c++) { + for (int i = 0; i < 8; i++) { + char name[50]; + xSnprintf(name, sizeof(name), "%s %d %s", classes[c].name, i, i == 0 ? "(High)" : (i == 7 ? "(Low)" : "")); + IOPriority ioprio = IOPriority_tuple(classes[c].klass, i); + Panel_add(this, (Object*) ListItem_new(name, ioprio)); + if (currPrio == ioprio) { + Panel_setSelected(this, Panel_size(this) - 1); + } + } + } + Panel_add(this, (Object*) ListItem_new("Idle", IOPriority_Idle)); + if (currPrio == IOPriority_Idle) { + Panel_setSelected(this, Panel_size(this) - 1); + } + return this; +} + +IOPriority IOPriorityPanel_getIOPriority(Panel* this) { + const ListItem* selected = (ListItem*) Panel_getSelected(this); + return selected ? selected->key : IOPriority_None; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/IOPriorityPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,17 @@ +#ifndef HEADER_IOPriorityPanel +#define HEADER_IOPriorityPanel +/* +htop - IOPriorityPanel.h +(C) 2004-2012 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" +#include "linux/IOPriority.h" + +Panel* IOPriorityPanel_new(IOPriority currPrio); + +IOPriority IOPriorityPanel_getIOPriority(Panel* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LibSensors.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LibSensors.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LibSensors.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LibSensors.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,248 @@ +#include "linux/LibSensors.h" + +#ifdef HAVE_SENSORS_SENSORS_H + +#include +#include +#include +#include + +#include "XUtils.h" + + +#ifdef BUILD_STATIC + +#define sym_sensors_init sensors_init +#define sym_sensors_cleanup sensors_cleanup +#define sym_sensors_get_detected_chips sensors_get_detected_chips +#define sym_sensors_get_features sensors_get_features +#define sym_sensors_get_subfeature sensors_get_subfeature +#define sym_sensors_get_value sensors_get_value + +#else + +static int (*sym_sensors_init)(FILE*); +static void (*sym_sensors_cleanup)(void); +static const sensors_chip_name* (*sym_sensors_get_detected_chips)(const sensors_chip_name*, int*); +static const sensors_feature* (*sym_sensors_get_features)(const sensors_chip_name*, int*); +static const sensors_subfeature* (*sym_sensors_get_subfeature)(const sensors_chip_name*, const sensors_feature*, sensors_subfeature_type); +static int (*sym_sensors_get_value)(const sensors_chip_name*, int, double*); + +static void* dlopenHandle = NULL; + +#endif /* BUILD_STATIC */ + +int LibSensors_init(FILE* input) { +#ifdef BUILD_STATIC + + return sym_sensors_init(input); + +#else + + if (!dlopenHandle) { + /* Find the unversioned libsensors.so (symlink) and prefer that, but Debian has .so.5 and Fedora .so.4 without + matching symlinks (unless people install the -dev packages) */ + dlopenHandle = dlopen("libsensors.so", RTLD_LAZY); + if (!dlopenHandle) + dlopenHandle = dlopen("libsensors.so.5", RTLD_LAZY); + if (!dlopenHandle) + dlopenHandle = dlopen("libsensors.so.4", RTLD_LAZY); + if (!dlopenHandle) + goto dlfailure; + + /* Clear any errors */ + dlerror(); + + #define resolve(symbolname) do { \ + *(void **)(&sym_##symbolname) = dlsym(dlopenHandle, #symbolname); \ + if (!sym_##symbolname || dlerror() != NULL) \ + goto dlfailure; \ + } while(0) + + resolve(sensors_init); + resolve(sensors_cleanup); + resolve(sensors_get_detected_chips); + resolve(sensors_get_features); + resolve(sensors_get_subfeature); + resolve(sensors_get_value); + + #undef resolve + } + + return sym_sensors_init(input); + + +dlfailure: + if (dlopenHandle) { + dlclose(dlopenHandle); + dlopenHandle = NULL; + } + return -1; + +#endif /* BUILD_STATIC */ +} + +void LibSensors_cleanup(void) { +#ifdef BUILD_STATIC + + sym_sensors_cleanup(); + +#else + + if (dlopenHandle) { + sym_sensors_cleanup(); + + dlclose(dlopenHandle); + dlopenHandle = NULL; + } + +#endif /* BUILD_STATIC */ +} + +static int tempDriverPriority(const sensors_chip_name* chip) { + static const struct TempDriverDefs { + const char* prefix; + int priority; + } tempDrivers[] = { + { "coretemp", 0 }, + { "via_cputemp", 0 }, + { "cpu_thermal", 0 }, + { "k10temp", 0 }, + { "zenpower", 0 }, + /* Low priority drivers */ + { "acpitz", 1 }, + }; + + for (size_t i = 0; i < ARRAYSIZE(tempDrivers); i++) + if (String_eq(chip->prefix, tempDrivers[i].prefix)) + return tempDrivers[i].priority; + + return -1; +} + +void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) { + assert(cpuCount > 0 && cpuCount < 16384); + double data[cpuCount + 1]; + for (size_t i = 0; i < cpuCount + 1; i++) + data[i] = NAN; + +#ifndef BUILD_STATIC + if (!dlopenHandle) + goto out; +#endif /* !BUILD_STATIC */ + + unsigned int coreTempCount = 0; + int topPriority = 99; + + int n = 0; + for (const sensors_chip_name* chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) { + const int priority = tempDriverPriority(chip); + if (priority < 0) + continue; + + if (priority > topPriority) + continue; + + if (priority < topPriority) { + /* Clear data from lower priority sensor */ + for (size_t i = 0; i < cpuCount + 1; i++) + data[i] = NAN; + } + + topPriority = priority; + + int m = 0; + for (const sensors_feature* feature = sym_sensors_get_features(chip, &m); feature; feature = sym_sensors_get_features(chip, &m)) { + if (feature->type != SENSORS_FEATURE_TEMP) + continue; + + if (!feature->name || !String_startsWith(feature->name, "temp")) + continue; + + unsigned long int tempID = strtoul(feature->name + strlen("temp"), NULL, 10); + if (tempID == 0 || tempID == ULONG_MAX) + continue; + + /* Feature name IDs start at 1, adjust to start at 0 to match data indices */ + tempID--; + + if (tempID > cpuCount) + continue; + + const sensors_subfeature* subFeature = sym_sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT); + if (!subFeature) + continue; + + double temp; + int r = sym_sensors_get_value(chip, subFeature->number, &temp); + if (r != 0) + continue; + + /* If already set, e.g. Ryzen reporting platform temperature for each die, use the bigger one */ + if (isnan(data[tempID])) { + data[tempID] = temp; + if (tempID > 0) + coreTempCount++; + } else { + data[tempID] = MAXIMUM(data[tempID], temp); + } + } + } + + /* Adjust data for chips not providing a platform temperature */ + if (coreTempCount + 1 == cpuCount || coreTempCount + 1 == cpuCount / 2) { + memmove(&data[1], &data[0], cpuCount * sizeof(*data)); + data[0] = NAN; + coreTempCount++; + + /* Check for further adjustments */ + } + + /* Only package temperature - copy to all cores */ + if (coreTempCount == 0 && !isnan(data[0])) { + for (unsigned int i = 1; i <= cpuCount; i++) + data[i] = data[0]; + + /* No further adjustments */ + goto out; + } + + /* No package temperature - set to max core temperature */ + if (isnan(data[0]) && coreTempCount != 0) { + double maxTemp = NAN; + for (unsigned int i = 1; i <= cpuCount; i++) { + if (isnan(data[i])) + continue; + + maxTemp = MAXIMUM(maxTemp, data[i]); + } + + data[0] = maxTemp; + + /* Check for further adjustments */ + } + + /* Only temperature for core 0, maybe Ryzen - copy to all other cores */ + if (coreTempCount == 1 && !isnan(data[1])) { + for (unsigned int i = 2; i <= cpuCount; i++) + data[i] = data[1]; + + /* No further adjustments */ + goto out; + } + + /* Half the temperatures, probably HT/SMT - copy to second half */ + const unsigned int delta = cpuCount / 2; + if (coreTempCount == delta) { + memcpy(&data[delta + 1], &data[1], delta * sizeof(*data)); + + /* No further adjustments */ + goto out; + } + +out: + for (unsigned int i = 0; i <= cpuCount; i++) + cpus[i].temperature = data[i]; +} + +#endif /* HAVE_SENSORS_SENSORS_H */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LibSensors.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LibSensors.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LibSensors.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LibSensors.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,16 @@ +#ifndef HEADER_LibSensors +#define HEADER_LibSensors + +#include "config.h" // IWYU pragma: keep + +#include + +#include "linux/LinuxProcessList.h" + + +int LibSensors_init(FILE* input); +void LibSensors_cleanup(void); + +void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount); + +#endif /* HEADER_LibSensors */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcess.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,367 @@ +/* +htop - LinuxProcess.c +(C) 2014 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "linux/LinuxProcess.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Process.h" +#include "ProvideCurses.h" +#include "RichString.h" +#include "XUtils.h" +#include "linux/IOPriority.h" + + +/* semi-global */ +int pageSize; +int pageSizeKB; + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging, I idle)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, + [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [CMINFLT] = { .name = "CMINFLT", .title = " CMINFLT ", .description = "Children processes' minor faults", .flags = 0, .defaultSortDesc = true, }, + [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [CMAJFLT] = { .name = "CMAJFLT", .title = " CMAJFLT ", .description = "Children processes' major faults", .flags = 0, .defaultSortDesc = true, }, + [UTIME] = { .name = "UTIME", .title = " UTIME+ ", .description = "User CPU time - time the process spent executing in user mode", .flags = 0, .defaultSortDesc = true, }, + [STIME] = { .name = "STIME", .title = " STIME+ ", .description = "System CPU time - time the kernel spent running system calls for this process", .flags = 0, .defaultSortDesc = true, }, + [CUTIME] = { .name = "CUTIME", .title = " CUTIME+ ", .description = "Children processes' user CPU time", .flags = 0, .defaultSortDesc = true, }, + [CSTIME] = { .name = "CSTIME", .title = " CSTIME+ ", .description = "Children processes' system CPU time", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [M_SHARE] = { .name = "M_SHARE", .title = " SHR ", .description = "Size of the process's shared pages", .flags = 0, .defaultSortDesc = true, }, + [M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the text segment of the process", .flags = 0, .defaultSortDesc = true, }, + [M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, }, + [M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (calculated from memory maps)", .flags = PROCESS_FLAG_LINUX_LRS_FIX, .defaultSortDesc = true, }, + [M_DT] = { .name = "M_DT", .title = " DIRTY ", .description = "Size of the dirty pages of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, +#ifdef HAVE_OPENVZ + [CTID] = { .name = "CTID", .title = " CTID ", .description = "OpenVZ container ID (a.k.a. virtual environment ID)", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, + [VPID] = { .name = "VPID", .title = "VPID", .description = "OpenVZ process ID", .flags = PROCESS_FLAG_LINUX_OPENVZ, .pidColumn = true, }, +#endif +#ifdef HAVE_VSERVER + [VXID] = { .name = "VXID", .title = " VXID ", .description = "VServer process ID", .flags = PROCESS_FLAG_LINUX_VSERVER, }, +#endif + [RCHAR] = { .name = "RCHAR", .title = "RCHAR ", .description = "Number of bytes the process has read", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [WCHAR] = { .name = "WCHAR", .title = "WCHAR ", .description = "Number of bytes the process has written", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [SYSCR] = { .name = "SYSCR", .title = " READ_SYSC ", .description = "Number of read(2) syscalls for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [SYSCW] = { .name = "SYSCW", .title = " WRITE_SYSC ", .description = "Number of write(2) syscalls for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [RBYTES] = { .name = "RBYTES", .title = " IO_R ", .description = "Bytes of read(2) I/O for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [WBYTES] = { .name = "WBYTES", .title = " IO_W ", .description = "Bytes of write(2) I/O for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [CNCLWB] = { .name = "CNCLWB", .title = " IO_C ", .description = "Bytes of cancelled write(2) I/O", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [IO_READ_RATE] = { .name = "IO_READ_RATE", .title = " DISK READ ", .description = "The I/O rate of read(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [IO_WRITE_RATE] = { .name = "IO_WRITE_RATE", .title = " DISK WRITE ", .description = "The I/O rate of write(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [IO_RATE] = { .name = "IO_RATE", .title = " DISK R/W ", .description = "Total I/O rate in bytes per second", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [CGROUP] = { .name = "CGROUP", .title = " CGROUP ", .description = "Which cgroup the process is in", .flags = PROCESS_FLAG_LINUX_CGROUP, }, + [OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, .defaultSortDesc = true, }, + [IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, }, +#ifdef HAVE_DELAYACCT + [PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, }, + [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, }, + [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, }, +#endif + [M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, + [M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, + [M_PSSWP] = { .name = "M_PSSWP", .title = " PSSWP ", .description = "shows proportional swap share of this mapping, unlike \"Swap\", this does not take into account swapped out page of underlying shmem objects", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, + [CTXT] = { .name = "CTXT", .title = " CTXT ", .description = "Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches)", .flags = PROCESS_FLAG_LINUX_CTXT, .defaultSortDesc = true, }, + [SECATTR] = { .name = "SECATTR", .title = " Security Attribute ", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, }, + [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process from /proc/[pid]/comm", .flags = 0, }, + [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process from /proc/[pid]/exe", .flags = 0, }, + [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, +}; + +Process* LinuxProcess_new(const Settings* settings) { + LinuxProcess* this = xCalloc(1, sizeof(LinuxProcess)); + Object_setClass(this, Class(LinuxProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + LinuxProcess* this = (LinuxProcess*) cast; + Process_done((Process*)cast); + free(this->cgroup); +#ifdef HAVE_OPENVZ + free(this->ctid); +#endif + free(this->secattr); + free(this); +} + +/* +[1] Note that before kernel 2.6.26 a process that has not asked for +an io priority formally uses "none" as scheduling class, but the +io scheduler will treat such processes as if it were in the best +effort class. The priority within the best effort class will be +dynamically derived from the cpu nice level of the process: +io_priority = (cpu_nice + 20) / 5. -- From ionice(1) man page +*/ +static int LinuxProcess_effectiveIOPriority(const LinuxProcess* this) { + if (IOPriority_class(this->ioPriority) == IOPRIO_CLASS_NONE) { + return IOPriority_tuple(IOPRIO_CLASS_BE, (this->super.nice + 20) / 5); + } + + return this->ioPriority; +} + +#ifdef __ANDROID__ +#define SYS_ioprio_get __NR_ioprio_get +#define SYS_ioprio_set __NR_ioprio_set +#endif + +IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this) { + IOPriority ioprio = 0; +// Other OSes masquerading as Linux (NetBSD?) don't have this syscall +#ifdef SYS_ioprio_get + ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, this->super.pid); +#endif + this->ioPriority = ioprio; + return ioprio; +} + +bool LinuxProcess_setIOPriority(Process* this, Arg ioprio) { +// Other OSes masquerading as Linux (NetBSD?) don't have this syscall +#ifdef SYS_ioprio_set + syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, this->pid, ioprio.i); +#endif + return (LinuxProcess_updateIOPriority((LinuxProcess*)this) == ioprio.i); +} + +#ifdef HAVE_DELAYACCT +static void LinuxProcess_printDelay(float delay_percent, char* buffer, int n) { + if (isnan(delay_percent)) { + xSnprintf(buffer, n, " N/A "); + } else { + xSnprintf(buffer, n, "%4.1f ", delay_percent); + } +} +#endif + +static void LinuxProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const LinuxProcess* lp = (const LinuxProcess*) this; + bool coloring = this->settings->highlightMegabytes; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + size_t n = sizeof(buffer) - 1; + switch (field) { + case CMINFLT: Process_printCount(str, lp->cminflt, coloring); return; + case CMAJFLT: Process_printCount(str, lp->cmajflt, coloring); return; + case M_DRS: Process_printBytes(str, lp->m_drs * pageSize, coloring); return; + case M_DT: Process_printBytes(str, lp->m_dt * pageSize, coloring); return; + case M_LRS: + if (lp->m_lrs) { + Process_printBytes(str, lp->m_lrs * pageSize, coloring); + return; + } + + attr = CRT_colors[PROCESS_SHADOW]; + xSnprintf(buffer, n, " N/A "); + break; + case M_TRS: Process_printBytes(str, lp->m_trs * pageSize, coloring); return; + case M_SHARE: Process_printBytes(str, lp->m_share * pageSize, coloring); return; + case M_PSS: Process_printKBytes(str, lp->m_pss, coloring); return; + case M_SWAP: Process_printKBytes(str, lp->m_swap, coloring); return; + case M_PSSWP: Process_printKBytes(str, lp->m_psswp, coloring); return; + case UTIME: Process_printTime(str, lp->utime, coloring); return; + case STIME: Process_printTime(str, lp->stime, coloring); return; + case CUTIME: Process_printTime(str, lp->cutime, coloring); return; + case CSTIME: Process_printTime(str, lp->cstime, coloring); return; + case RCHAR: Process_printBytes(str, lp->io_rchar, coloring); return; + case WCHAR: Process_printBytes(str, lp->io_wchar, coloring); return; + case SYSCR: Process_printCount(str, lp->io_syscr, coloring); return; + case SYSCW: Process_printCount(str, lp->io_syscw, coloring); return; + case RBYTES: Process_printBytes(str, lp->io_read_bytes, coloring); return; + case WBYTES: Process_printBytes(str, lp->io_write_bytes, coloring); return; + case CNCLWB: Process_printBytes(str, lp->io_cancelled_write_bytes, coloring); return; + case IO_READ_RATE: Process_printRate(str, lp->io_rate_read_bps, coloring); return; + case IO_WRITE_RATE: Process_printRate(str, lp->io_rate_write_bps, coloring); return; + case IO_RATE: { + double totalRate; + if (!isnan(lp->io_rate_read_bps) && !isnan(lp->io_rate_write_bps)) + totalRate = lp->io_rate_read_bps + lp->io_rate_write_bps; + else if (!isnan(lp->io_rate_read_bps)) + totalRate = lp->io_rate_read_bps; + else if (!isnan(lp->io_rate_write_bps)) + totalRate = lp->io_rate_write_bps; + else + totalRate = NAN; + Process_printRate(str, totalRate, coloring); + return; + } + #ifdef HAVE_OPENVZ + case CTID: xSnprintf(buffer, n, "%-8s ", lp->ctid ? lp->ctid : ""); break; + case VPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, lp->vpid); break; + #endif + #ifdef HAVE_VSERVER + case VXID: xSnprintf(buffer, n, "%5u ", lp->vxid); break; + #endif + case CGROUP: xSnprintf(buffer, n, "%-10s ", lp->cgroup ? lp->cgroup : ""); break; + case OOM: xSnprintf(buffer, n, "%4u ", lp->oom); break; + case IO_PRIORITY: { + int klass = IOPriority_class(lp->ioPriority); + if (klass == IOPRIO_CLASS_NONE) { + // see note [1] above + xSnprintf(buffer, n, "B%1d ", (int) (this->nice + 20) / 5); + } else if (klass == IOPRIO_CLASS_BE) { + xSnprintf(buffer, n, "B%1d ", IOPriority_data(lp->ioPriority)); + } else if (klass == IOPRIO_CLASS_RT) { + attr = CRT_colors[PROCESS_HIGH_PRIORITY]; + xSnprintf(buffer, n, "R%1d ", IOPriority_data(lp->ioPriority)); + } else if (klass == IOPRIO_CLASS_IDLE) { + attr = CRT_colors[PROCESS_LOW_PRIORITY]; + xSnprintf(buffer, n, "id "); + } else { + xSnprintf(buffer, n, "?? "); + } + break; + } + #ifdef HAVE_DELAYACCT + case PERCENT_CPU_DELAY: LinuxProcess_printDelay(lp->cpu_delay_percent, buffer, n); break; + case PERCENT_IO_DELAY: LinuxProcess_printDelay(lp->blkio_delay_percent, buffer, n); break; + case PERCENT_SWAP_DELAY: LinuxProcess_printDelay(lp->swapin_delay_percent, buffer, n); break; + #endif + case CTXT: + if (lp->ctxt_diff > 1000) { + attr |= A_BOLD; + } + xSnprintf(buffer, n, "%5lu ", lp->ctxt_diff); + break; + case SECATTR: snprintf(buffer, n, "%-30s ", lp->secattr ? lp->secattr : "?"); break; + default: + Process_writeField(this, str, field); + return; + } + RichString_appendAscii(str, attr, buffer); +} + +static double adjustNaN(double num) { + if (isnan(num)) + return -0.0005; + + return num; +} + +static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const LinuxProcess* p1 = (const LinuxProcess*)v1; + const LinuxProcess* p2 = (const LinuxProcess*)v2; + + switch (key) { + case M_DRS: + return SPACESHIP_NUMBER(p1->m_drs, p2->m_drs); + case M_DT: + return SPACESHIP_NUMBER(p1->m_dt, p2->m_dt); + case M_LRS: + return SPACESHIP_NUMBER(p1->m_lrs, p2->m_lrs); + case M_TRS: + return SPACESHIP_NUMBER(p1->m_trs, p2->m_trs); + case M_SHARE: + return SPACESHIP_NUMBER(p1->m_share, p2->m_share); + case M_PSS: + return SPACESHIP_NUMBER(p1->m_pss, p2->m_pss); + case M_SWAP: + return SPACESHIP_NUMBER(p1->m_swap, p2->m_swap); + case M_PSSWP: + return SPACESHIP_NUMBER(p1->m_psswp, p2->m_psswp); + case UTIME: + return SPACESHIP_NUMBER(p1->utime, p2->utime); + case CUTIME: + return SPACESHIP_NUMBER(p1->cutime, p2->cutime); + case STIME: + return SPACESHIP_NUMBER(p1->stime, p2->stime); + case CSTIME: + return SPACESHIP_NUMBER(p1->cstime, p2->cstime); + case RCHAR: + return SPACESHIP_NUMBER(p1->io_rchar, p2->io_rchar); + case WCHAR: + return SPACESHIP_NUMBER(p1->io_wchar, p2->io_wchar); + case SYSCR: + return SPACESHIP_NUMBER(p1->io_syscr, p2->io_syscr); + case SYSCW: + return SPACESHIP_NUMBER(p1->io_syscw, p2->io_syscw); + case RBYTES: + return SPACESHIP_NUMBER(p1->io_read_bytes, p2->io_read_bytes); + case WBYTES: + return SPACESHIP_NUMBER(p1->io_write_bytes, p2->io_write_bytes); + case CNCLWB: + return SPACESHIP_NUMBER(p1->io_cancelled_write_bytes, p2->io_cancelled_write_bytes); + case IO_READ_RATE: + return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps), adjustNaN(p2->io_rate_read_bps)); + case IO_WRITE_RATE: + return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_write_bps)); + case IO_RATE: + return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps) + adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_read_bps) + adjustNaN(p2->io_rate_write_bps)); + #ifdef HAVE_OPENVZ + case CTID: + return SPACESHIP_NULLSTR(p1->ctid, p2->ctid); + case VPID: + return SPACESHIP_NUMBER(p1->vpid, p2->vpid); + #endif + #ifdef HAVE_VSERVER + case VXID: + return SPACESHIP_NUMBER(p1->vxid, p2->vxid); + #endif + case CGROUP: + return SPACESHIP_NULLSTR(p1->cgroup, p2->cgroup); + case OOM: + return SPACESHIP_NUMBER(p1->oom, p2->oom); + #ifdef HAVE_DELAYACCT + case PERCENT_CPU_DELAY: + return SPACESHIP_NUMBER(p1->cpu_delay_percent, p2->cpu_delay_percent); + case PERCENT_IO_DELAY: + return SPACESHIP_NUMBER(p1->blkio_delay_percent, p2->blkio_delay_percent); + case PERCENT_SWAP_DELAY: + return SPACESHIP_NUMBER(p1->swapin_delay_percent, p2->swapin_delay_percent); + #endif + case IO_PRIORITY: + return SPACESHIP_NUMBER(LinuxProcess_effectiveIOPriority(p1), LinuxProcess_effectiveIOPriority(p2)); + case CTXT: + return SPACESHIP_NUMBER(p1->ctxt_diff, p2->ctxt_diff); + case SECATTR: + return SPACESHIP_NULLSTR(p1->secattr, p2->secattr); + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass LinuxProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = LinuxProcess_writeField, + .compareByKey = LinuxProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,122 @@ +#ifndef HEADER_LinuxProcess +#define HEADER_LinuxProcess +/* +htop - LinuxProcess.h +(C) 2014 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include + +#include "linux/IOPriority.h" +#include "Object.h" +#include "Process.h" +#include "Settings.h" + + +#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100 +#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200 +#define PROCESS_FLAG_LINUX_VSERVER 0x00000400 +#define PROCESS_FLAG_LINUX_CGROUP 0x00000800 +#define PROCESS_FLAG_LINUX_OOM 0x00001000 +#define PROCESS_FLAG_LINUX_SMAPS 0x00002000 +#define PROCESS_FLAG_LINUX_CTXT 0x00004000 +#define PROCESS_FLAG_LINUX_SECATTR 0x00008000 +#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000 +#define PROCESS_FLAG_LINUX_DELAYACCT 0x00040000 + +typedef struct LinuxProcess_ { + Process super; + IOPriority ioPriority; + unsigned long int cminflt; + unsigned long int cmajflt; + unsigned long long int utime; + unsigned long long int stime; + unsigned long long int cutime; + unsigned long long int cstime; + long m_share; + long m_pss; + long m_swap; + long m_psswp; + long m_trs; + long m_drs; + long m_lrs; + long m_dt; + + /* Data read (in bytes) */ + unsigned long long io_rchar; + + /* Data written (in bytes) */ + unsigned long long io_wchar; + + /* Number of read(2) syscalls */ + unsigned long long io_syscr; + + /* Number of write(2) syscalls */ + unsigned long long io_syscw; + + /* Storage data read (in bytes) */ + unsigned long long io_read_bytes; + + /* Storage data written (in bytes) */ + unsigned long long io_write_bytes; + + /* Storage data cancelled (in bytes) */ + unsigned long long io_cancelled_write_bytes; + + /* Point in time of last io scan (in milliseconds elapsed since the Epoch) */ + unsigned long long io_last_scan_time_ms; + + /* Storage data read (in bytes per second) */ + double io_rate_read_bps; + + /* Storage data written (in bytes per second) */ + double io_rate_write_bps; + + #ifdef HAVE_OPENVZ + char* ctid; + pid_t vpid; + #endif + #ifdef HAVE_VSERVER + unsigned int vxid; + #endif + char* cgroup; + unsigned int oom; + #ifdef HAVE_DELAYACCT + unsigned long long int delay_read_time; + unsigned long long cpu_delay_total; + unsigned long long blkio_delay_total; + unsigned long long swapin_delay_total; + float cpu_delay_percent; + float blkio_delay_percent; + float swapin_delay_percent; + #endif + unsigned long ctxt_total; + unsigned long ctxt_diff; + char* secattr; + unsigned long long int last_mlrs_calctime; +} LinuxProcess; + +extern int pageSize; + +extern int pageSizeKB; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +extern const ProcessClass LinuxProcess_class; + +Process* LinuxProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this); + +bool LinuxProcess_setIOPriority(Process* this, Arg ioprio); + +bool Process_isThread(const Process* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,2013 @@ +/* +htop - LinuxProcessList.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "linux/LinuxProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DELAYACCT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "Compat.h" +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "Process.h" +#include "Settings.h" +#include "XUtils.h" +#include "linux/LinuxProcess.h" +#include "linux/Platform.h" // needed for GNU/hurd to get PATH_MAX + +#if defined(MAJOR_IN_MKDEV) +#include +#elif defined(MAJOR_IN_SYSMACROS) +#include +#endif + +#ifdef HAVE_SENSORS_SENSORS_H +#include "LibSensors.h" +#endif + + +static long long btime = -1; + +static long jiffy; + +static FILE* fopenat(openat_arg_t openatArg, const char* pathname, const char* mode) { + assert(String_eq(mode, "r")); /* only currently supported mode */ + + int fd = Compat_openat(openatArg, pathname, O_RDONLY); + if (fd < 0) + return NULL; + + FILE* stream = fdopen(fd, mode); + if (!stream) + close(fd); + + return stream; +} + +static int sortTtyDrivers(const void* va, const void* vb) { + const TtyDriver* a = (const TtyDriver*) va; + const TtyDriver* b = (const TtyDriver*) vb; + + int r = SPACESHIP_NUMBER(a->major, b->major); + if (r) + return r; + + return SPACESHIP_NUMBER(a->minorFrom, b->minorFrom); +} + +static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) { + TtyDriver* ttyDrivers; + + char buf[16384]; + ssize_t r = xReadfile(PROCTTYDRIVERSFILE, buf, sizeof(buf)); + if (r < 0) + return; + + int numDrivers = 0; + int allocd = 10; + ttyDrivers = xMallocArray(allocd, sizeof(TtyDriver)); + char* at = buf; + while (*at != '\0') { + at = strchr(at, ' '); // skip first token + while (*at == ' ') at++; // skip spaces + const char* token = at; // mark beginning of path + at = strchr(at, ' '); // find end of path + *at = '\0'; at++; // clear and skip + ttyDrivers[numDrivers].path = xStrdup(token); // save + while (*at == ' ') at++; // skip spaces + token = at; // mark beginning of major + at = strchr(at, ' '); // find end of major + *at = '\0'; at++; // clear and skip + ttyDrivers[numDrivers].major = atoi(token); // save + while (*at == ' ') at++; // skip spaces + token = at; // mark beginning of minorFrom + while (*at >= '0' && *at <= '9') at++; //find end of minorFrom + if (*at == '-') { // if has range + *at = '\0'; at++; // clear and skip + ttyDrivers[numDrivers].minorFrom = atoi(token); // save + token = at; // mark beginning of minorTo + at = strchr(at, ' '); // find end of minorTo + *at = '\0'; at++; // clear and skip + ttyDrivers[numDrivers].minorTo = atoi(token); // save + } else { // no range + *at = '\0'; at++; // clear and skip + ttyDrivers[numDrivers].minorFrom = atoi(token); // save + ttyDrivers[numDrivers].minorTo = atoi(token); // save + } + at = strchr(at, '\n'); // go to end of line + at++; // skip + numDrivers++; + if (numDrivers == allocd) { + allocd += 10; + ttyDrivers = xReallocArray(ttyDrivers, allocd, sizeof(TtyDriver)); + } + } + numDrivers++; + ttyDrivers = xRealloc(ttyDrivers, sizeof(TtyDriver) * numDrivers); + ttyDrivers[numDrivers - 1].path = NULL; + qsort(ttyDrivers, numDrivers - 1, sizeof(TtyDriver), sortTtyDrivers); + this->ttyDrivers = ttyDrivers; +} + +#ifdef HAVE_DELAYACCT + +static void LinuxProcessList_initNetlinkSocket(LinuxProcessList* this) { + this->netlink_socket = nl_socket_alloc(); + if (this->netlink_socket == NULL) { + return; + } + if (nl_connect(this->netlink_socket, NETLINK_GENERIC) < 0) { + return; + } + this->netlink_family = genl_ctrl_resolve(this->netlink_socket, TASKSTATS_GENL_NAME); +} + +#endif + +static void LinuxProcessList_updateCPUcount(ProcessList* super, FILE* stream) { + LinuxProcessList* this = (LinuxProcessList*) super; + + unsigned int cpus = 0; + char buffer[PROC_LINE_LENGTH + 1]; + while (fgets(buffer, sizeof(buffer), stream)) { + if (String_startsWith(buffer, "cpu")) { + cpus++; + } + } + + if (cpus == 0) + CRT_fatalError("No cpu entry in " PROCSTATFILE); + if (cpus == 1) + CRT_fatalError("No cpu aggregate or cpuN entry in " PROCSTATFILE); + + /* Subtract aggregate cpu entry */ + cpus--; + + if (cpus != super->cpuCount || !this->cpus) { + super->cpuCount = MAXIMUM(cpus, 1); + free(this->cpus); + this->cpus = xCalloc(cpus + 1, sizeof(CPUData)); + } +} + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + LinuxProcessList* this = xCalloc(1, sizeof(LinuxProcessList)); + ProcessList* pl = &(this->super); + + ProcessList_init(pl, Class(LinuxProcess), usersTable, dynamicMeters, pidMatchList, userId); + LinuxProcessList_initTtyDrivers(this); + + // Initialize page size + pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + CRT_fatalError("Cannot get pagesize by sysconf(_SC_PAGESIZE)"); + pageSizeKB = pageSize / ONE_K; + + // Initialize clock ticks + jiffy = sysconf(_SC_CLK_TCK); + if (jiffy == -1) + CRT_fatalError("Cannot get clock ticks by sysconf(_SC_CLK_TCK)"); + + // Test /proc/PID/smaps_rollup availability (faster to parse, Linux 4.14+) + this->haveSmapsRollup = (access(PROCDIR "/self/smaps_rollup", R_OK) == 0); + + // Read btime (the kernel boot time, as number of seconds since the epoch) + FILE* statfile = fopen(PROCSTATFILE, "r"); + if (statfile == NULL) + CRT_fatalError("Cannot open " PROCSTATFILE); + while (true) { + char buffer[PROC_LINE_LENGTH + 1]; + if (fgets(buffer, sizeof(buffer), statfile) == NULL) + break; + if (String_startsWith(buffer, "btime ") == false) + continue; + if (sscanf(buffer, "btime %lld\n", &btime) == 1) + break; + CRT_fatalError("Failed to parse btime from " PROCSTATFILE); + } + + if (btime == -1) + CRT_fatalError("No btime in " PROCSTATFILE); + + rewind(statfile); + + // Initialize CPU count + LinuxProcessList_updateCPUcount(pl, statfile); + + fclose(statfile); + + return pl; +} + +void ProcessList_delete(ProcessList* pl) { + LinuxProcessList* this = (LinuxProcessList*) pl; + ProcessList_done(pl); + free(this->cpus); + if (this->ttyDrivers) { + for (int i = 0; this->ttyDrivers[i].path; i++) { + free(this->ttyDrivers[i].path); + } + free(this->ttyDrivers); + } + #ifdef HAVE_DELAYACCT + if (this->netlink_socket) { + nl_close(this->netlink_socket); + nl_socket_free(this->netlink_socket); + } + #endif + free(this); +} + +static inline unsigned long long LinuxProcessList_adjustTime(unsigned long long t) { + return t * 100 / jiffy; +} + +static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, char* command, size_t commLen) { + LinuxProcess* lp = (LinuxProcess*) process; + + char buf[MAX_READ + 1]; + ssize_t r = xReadfileat(procFd, "stat", buf, sizeof(buf)); + if (r < 0) + return false; + + /* (1) pid - %d */ + assert(process->pid == atoi(buf)); + char* location = strchr(buf, ' '); + if (!location) + return false; + + /* (2) comm - (%s) */ + location += 2; + char* end = strrchr(location, ')'); + if (!end) + return false; + + String_safeStrncpy(command, location, MINIMUM((size_t)(end - location + 1), commLen)); + + location = end + 2; + + /* (3) state - %c */ + process->state = location[0]; + location += 2; + + /* (4) ppid - %d */ + process->ppid = strtol(location, &location, 10); + location += 1; + + /* (5) pgrp - %d */ + process->pgrp = strtol(location, &location, 10); + location += 1; + + /* (6) session - %d */ + process->session = strtol(location, &location, 10); + location += 1; + + /* (7) tty_nr - %d */ + process->tty_nr = strtoul(location, &location, 10); + location += 1; + + /* (8) tpgid - %d */ + process->tpgid = strtol(location, &location, 10); + location += 1; + + /* Skip (9) flags - %u */ + location = strchr(location, ' ') + 1; + + /* (10) minflt - %lu */ + process->minflt = strtoull(location, &location, 10); + location += 1; + + /* (11) cminflt - %lu */ + lp->cminflt = strtoull(location, &location, 10); + location += 1; + + /* (12) majflt - %lu */ + process->majflt = strtoull(location, &location, 10); + location += 1; + + /* (13) cmajflt - %lu */ + lp->cmajflt = strtoull(location, &location, 10); + location += 1; + + /* (14) utime - %lu */ + lp->utime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); + location += 1; + + /* (15) stime - %lu */ + lp->stime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); + location += 1; + + /* (16) cutime - %ld */ + lp->cutime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); + location += 1; + + /* (17) cstime - %ld */ + lp->cstime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); + location += 1; + + /* (18) priority - %ld */ + process->priority = strtol(location, &location, 10); + location += 1; + + /* (19) nice - %ld */ + process->nice = strtol(location, &location, 10); + location += 1; + + /* (20) num_threads - %ld */ + process->nlwp = strtol(location, &location, 10); + location += 1; + + /* Skip (21) itrealvalue - %ld */ + location = strchr(location, ' ') + 1; + + /* (22) starttime - %llu */ + if (process->starttime_ctime == 0) { + process->starttime_ctime = btime + LinuxProcessList_adjustTime(strtoll(location, &location, 10)) / 100; + } else { + location = strchr(location, ' '); + } + location += 1; + + /* Skip (23) - (38) */ + for (int i = 0; i < 16; i++) { + location = strchr(location, ' ') + 1; + } + + assert(location != NULL); + + /* (39) processor - %d */ + process->processor = strtol(location, &location, 10); + + /* Ignore further fields */ + + process->time = lp->utime + lp->stime; + + return true; +} + + +static bool LinuxProcessList_updateUser(ProcessList* processList, Process* process, openat_arg_t procFd) { + struct stat sstat; +#ifdef HAVE_OPENAT + int statok = fstat(procFd, &sstat); +#else + int statok = stat(procFd, &sstat); +#endif + if (statok == -1) + return false; + + if (process->st_uid != sstat.st_uid) { + process->st_uid = sstat.st_uid; + process->user = UsersTable_getRef(processList->usersTable, sstat.st_uid); + } + + return true; +} + +static void LinuxProcessList_readIoFile(LinuxProcess* process, openat_arg_t procFd, unsigned long long realtimeMs) { + char buffer[1024]; + ssize_t r = xReadfileat(procFd, "io", buffer, sizeof(buffer)); + if (r < 0) { + process->io_rate_read_bps = NAN; + process->io_rate_write_bps = NAN; + process->io_rchar = ULLONG_MAX; + process->io_wchar = ULLONG_MAX; + process->io_syscr = ULLONG_MAX; + process->io_syscw = ULLONG_MAX; + process->io_read_bytes = ULLONG_MAX; + process->io_write_bytes = ULLONG_MAX; + process->io_cancelled_write_bytes = ULLONG_MAX; + process->io_last_scan_time_ms = realtimeMs; + return; + } + + unsigned long long last_read = process->io_read_bytes; + unsigned long long last_write = process->io_write_bytes; + char* buf = buffer; + const char* line; + while ((line = strsep(&buf, "\n")) != NULL) { + switch (line[0]) { + case 'r': + if (line[1] == 'c' && String_startsWith(line + 2, "har: ")) { + process->io_rchar = strtoull(line + 7, NULL, 10); + } else if (String_startsWith(line + 1, "ead_bytes: ")) { + process->io_read_bytes = strtoull(line + 12, NULL, 10); + process->io_rate_read_bps = (process->io_read_bytes - last_read) * /*ms to s*/1000 / (realtimeMs - process->io_last_scan_time_ms); + } + break; + case 'w': + if (line[1] == 'c' && String_startsWith(line + 2, "har: ")) { + process->io_wchar = strtoull(line + 7, NULL, 10); + } else if (String_startsWith(line + 1, "rite_bytes: ")) { + process->io_write_bytes = strtoull(line + 13, NULL, 10); + process->io_rate_write_bps = (process->io_write_bytes - last_write) * /*ms to s*/1000 / (realtimeMs - process->io_last_scan_time_ms); + } + break; + case 's': + if (line[4] == 'r' && String_startsWith(line + 1, "yscr: ")) { + process->io_syscr = strtoull(line + 7, NULL, 10); + } else if (String_startsWith(line + 1, "yscw: ")) { + process->io_syscw = strtoull(line + 7, NULL, 10); + } + break; + case 'c': + if (String_startsWith(line + 1, "ancelled_write_bytes: ")) { + process->io_cancelled_write_bytes = strtoull(line + 23, NULL, 10); + } + } + } + + process->io_last_scan_time_ms = realtimeMs; +} + +typedef struct LibraryData_ { + uint64_t size; + bool exec; +} LibraryData; + +static inline uint64_t fast_strtoull_dec(char** str, int maxlen) { + register uint64_t result = 0; + + if (!maxlen) + --maxlen; + + while (maxlen-- && **str >= '0' && **str <= '9') { + result *= 10; + result += **str - '0'; + (*str)++; + } + + return result; +} + +static inline uint64_t fast_strtoull_hex(char** str, int maxlen) { + register uint64_t result = 0; + register int nibble, letter; + const long valid_mask = 0x03FF007E; + + if (!maxlen) + --maxlen; + + while (maxlen--) { + nibble = (unsigned char)**str; + if (!(valid_mask & (1 << (nibble & 0x1F)))) + break; + if ((nibble < '0') || (nibble & ~0x20) > 'F') + break; + letter = (nibble & 0x40) ? 'A' - '9' - 1 : 0; + nibble &=~0x20; // to upper + nibble ^= 0x10; // switch letters and digits + nibble -= letter; + nibble &= 0x0f; + result <<= 4; + result += (uint64_t)nibble; + (*str)++; + } + + return result; +} + +static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED ht_key_t key, void* value, void* data) { + if (!data) + return; + + if (!value) + return; + + const LibraryData* v = (const LibraryData*)value; + uint64_t* d = (uint64_t*)data; + if (!v->exec) + return; + + *d += v->size; +} + +static void LinuxProcessList_readMaps(LinuxProcess* process, openat_arg_t procFd, bool calcSize, bool checkDeletedLib) { + Process* proc = (Process*)process; + + proc->usesDeletedLib = false; + + FILE* mapsfile = fopenat(procFd, "maps", "r"); + if (!mapsfile) + return; + + Hashtable* ht = NULL; + if (calcSize) + ht = Hashtable_new(64, true); + + char buffer[1024]; + while (fgets(buffer, sizeof(buffer), mapsfile)) { + uint64_t map_start; + uint64_t map_end; + bool map_execute; + unsigned int map_devmaj; + unsigned int map_devmin; + uint64_t map_inode; + + // Short circuit test: Look for a slash + if (!strchr(buffer, '/')) + continue; + + // Parse format: "%Lx-%Lx %4s %x %2x:%2x %Ld" + char* readptr = buffer; + + map_start = fast_strtoull_hex(&readptr, 16); + if ('-' != *readptr++) + continue; + + map_end = fast_strtoull_hex(&readptr, 16); + if (' ' != *readptr++) + continue; + + map_execute = (readptr[2] == 'x'); + readptr += 4; + if (' ' != *readptr++) + continue; + + while(*readptr > ' ') + readptr++; // Skip parsing this hex value + if (' ' != *readptr++) + continue; + + map_devmaj = fast_strtoull_hex(&readptr, 4); + if (':' != *readptr++) + continue; + + map_devmin = fast_strtoull_hex(&readptr, 4); + if (' ' != *readptr++) + continue; + + //Minor shortcut: Once we know there's no file for this region, we skip + if (!map_devmaj && !map_devmin) + continue; + + map_inode = fast_strtoull_dec(&readptr, 20); + if (!map_inode) + continue; + + if (calcSize) { + LibraryData* libdata = Hashtable_get(ht, map_inode); + if (!libdata) { + libdata = xCalloc(1, sizeof(LibraryData)); + Hashtable_put(ht, map_inode, libdata); + } + + libdata->size += map_end - map_start; + libdata->exec |= map_execute; + } + + if (checkDeletedLib && map_execute && !proc->usesDeletedLib) { + while (*readptr == ' ') + readptr++; + + if (*readptr != '/') + continue; + + if (String_startsWith(readptr, "/memfd:")) + continue; + + if (strstr(readptr, " (deleted)\n")) { + proc->usesDeletedLib = true; + if (!calcSize) + break; + } + } + } + + fclose(mapsfile); + + if (calcSize) { + uint64_t total_size = 0; + Hashtable_foreach(ht, LinuxProcessList_calcLibSize_helper, &total_size); + + Hashtable_delete(ht); + + process->m_lrs = total_size / pageSize; + } +} + +static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t procFd) { + FILE* statmfile = fopenat(procFd, "statm", "r"); + if (!statmfile) + return false; + + long int dummy; + + int r = fscanf(statmfile, "%ld %ld %ld %ld %ld %ld %ld", + &process->super.m_virt, + &process->super.m_resident, + &process->m_share, + &process->m_trs, + &dummy, /* unused since Linux 2.6; always 0 */ + &process->m_drs, + &process->m_dt); + fclose(statmfile); + + if (r == 7) { + process->super.m_virt *= pageSizeKB; + process->super.m_resident *= pageSizeKB; + } + + return r == 7; +} + +static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, openat_arg_t procFd, bool haveSmapsRollup) { + //http://elixir.free-electrons.com/linux/v4.10/source/fs/proc/task_mmu.c#L719 + //kernel will return data in chunks of size PAGE_SIZE or less. + FILE* f = fopenat(procFd, haveSmapsRollup ? "smaps_rollup" : "smaps", "r"); + if (!f) + return false; + + process->m_pss = 0; + process->m_swap = 0; + process->m_psswp = 0; + + char buffer[256]; + while (fgets(buffer, sizeof(buffer), f)) { + if (!strchr(buffer, '\n')) { + // Partial line, skip to end of this line + while (fgets(buffer, sizeof(buffer), f)) { + if (strchr(buffer, '\n')) { + break; + } + } + continue; + } + + if (String_startsWith(buffer, "Pss:")) { + process->m_pss += strtol(buffer + 4, NULL, 10); + } else if (String_startsWith(buffer, "Swap:")) { + process->m_swap += strtol(buffer + 5, NULL, 10); + } else if (String_startsWith(buffer, "SwapPss:")) { + process->m_psswp += strtol(buffer + 8, NULL, 10); + } + } + + fclose(f); + return true; +} + +#ifdef HAVE_OPENVZ + +static void LinuxProcessList_readOpenVZData(LinuxProcess* process, openat_arg_t procFd) { + if (access(PROCDIR "/vz", R_OK) != 0) { + free(process->ctid); + process->ctid = NULL; + process->vpid = process->super.pid; + return; + } + + FILE* file = fopenat(procFd, "status", "r"); + if (!file) { + free(process->ctid); + process->ctid = NULL; + process->vpid = process->super.pid; + return; + } + + bool foundEnvID = false; + bool foundVPid = false; + char linebuf[256]; + while (fgets(linebuf, sizeof(linebuf), file) != NULL) { + if (strchr(linebuf, '\n') == NULL) { + // Partial line, skip to end of this line + while (fgets(linebuf, sizeof(linebuf), file) != NULL) { + if (strchr(linebuf, '\n') != NULL) { + break; + } + } + continue; + } + + char* name_value_sep = strchr(linebuf, ':'); + if (name_value_sep == NULL) { + continue; + } + + int field; + if (0 == strncasecmp(linebuf, "envID", name_value_sep - linebuf)) { + field = 1; + } else if (0 == strncasecmp(linebuf, "VPid", name_value_sep - linebuf)) { + field = 2; + } else { + continue; + } + + do { + name_value_sep++; + } while (*name_value_sep != '\0' && *name_value_sep <= 32); + + char* value_end = name_value_sep; + + while(*value_end > 32) { + value_end++; + } + + if (name_value_sep == value_end) { + continue; + } + + *value_end = '\0'; + + switch(field) { + case 1: + foundEnvID = true; + if (!String_eq(name_value_sep, process->ctid ? process->ctid : "")) + free_and_xStrdup(&process->ctid, name_value_sep); + break; + case 2: + foundVPid = true; + process->vpid = strtoul(name_value_sep, NULL, 0); + break; + default: + //Sanity Check: Should never reach here, or the implementation is missing something! + assert(false && "OpenVZ handling: Unimplemented case for field handling reached."); + } + } + + fclose(file); + + if (!foundEnvID) { + free(process->ctid); + process->ctid = NULL; + } + + if (!foundVPid) { + process->vpid = process->super.pid; + } +} + +#endif + +static void LinuxProcessList_readCGroupFile(LinuxProcess* process, openat_arg_t procFd) { + FILE* file = fopenat(procFd, "cgroup", "r"); + if (!file) { + if (process->cgroup) { + free(process->cgroup); + process->cgroup = NULL; + } + return; + } + char output[PROC_LINE_LENGTH + 1]; + output[0] = '\0'; + char* at = output; + int left = PROC_LINE_LENGTH; + while (!feof(file) && left > 0) { + char buffer[PROC_LINE_LENGTH + 1]; + const char* ok = fgets(buffer, PROC_LINE_LENGTH, file); + if (!ok) + break; + + char* group = strchr(buffer, ':'); + if (!group) + break; + + if (at != output) { + *at = ';'; + at++; + left--; + } + int wrote = snprintf(at, left, "%s", group); + left -= wrote; + } + fclose(file); + free_and_xStrdup(&process->cgroup, output); +} + +#ifdef HAVE_VSERVER + +static void LinuxProcessList_readVServerData(LinuxProcess* process, openat_arg_t procFd) { + FILE* file = fopenat(procFd, "status", "r"); + if (!file) + return; + + char buffer[PROC_LINE_LENGTH + 1]; + process->vxid = 0; + while (fgets(buffer, PROC_LINE_LENGTH, file)) { + if (String_startsWith(buffer, "VxID:")) { + int vxid; + int ok = sscanf(buffer, "VxID:\t%32d", &vxid); + if (ok >= 1) { + process->vxid = vxid; + } + } + #if defined HAVE_ANCIENT_VSERVER + else if (String_startsWith(buffer, "s_context:")) { + int vxid; + int ok = sscanf(buffer, "s_context:\t%32d", &vxid); + if (ok >= 1) { + process->vxid = vxid; + } + } + #endif + } + fclose(file); +} + +#endif + +static void LinuxProcessList_readOomData(LinuxProcess* process, openat_arg_t procFd) { + FILE* file = fopenat(procFd, "oom_score", "r"); + if (!file) + return; + + char buffer[PROC_LINE_LENGTH + 1]; + if (fgets(buffer, PROC_LINE_LENGTH, file)) { + unsigned int oom; + int ok = sscanf(buffer, "%u", &oom); + if (ok >= 1) { + process->oom = oom; + } + } + fclose(file); +} + +static void LinuxProcessList_readCtxtData(LinuxProcess* process, openat_arg_t procFd) { + FILE* file = fopenat(procFd, "status", "r"); + if (!file) + return; + + char buffer[PROC_LINE_LENGTH + 1]; + unsigned long ctxt = 0; + while (fgets(buffer, PROC_LINE_LENGTH, file)) { + if (String_startsWith(buffer, "voluntary_ctxt_switches:")) { + unsigned long vctxt; + int ok = sscanf(buffer, "voluntary_ctxt_switches:\t%lu", &vctxt); + if (ok >= 1) { + ctxt += vctxt; + } + } else if (String_startsWith(buffer, "nonvoluntary_ctxt_switches:")) { + unsigned long nvctxt; + int ok = sscanf(buffer, "nonvoluntary_ctxt_switches:\t%lu", &nvctxt); + if (ok >= 1) { + ctxt += nvctxt; + } + } + } + fclose(file); + process->ctxt_diff = (ctxt > process->ctxt_total) ? (ctxt - process->ctxt_total) : 0; + process->ctxt_total = ctxt; +} + +static void LinuxProcessList_readSecattrData(LinuxProcess* process, openat_arg_t procFd) { + FILE* file = fopenat(procFd, "attr/current", "r"); + if (!file) { + free(process->secattr); + process->secattr = NULL; + return; + } + + char buffer[PROC_LINE_LENGTH + 1]; + const char* res = fgets(buffer, sizeof(buffer), file); + fclose(file); + if (!res) { + free(process->secattr); + process->secattr = NULL; + return; + } + char* newline = strchr(buffer, '\n'); + if (newline) { + *newline = '\0'; + } + if (process->secattr && String_eq(process->secattr, buffer)) { + return; + } + free_and_xStrdup(&process->secattr, buffer); +} + +static void LinuxProcessList_readCwd(LinuxProcess* process, openat_arg_t procFd) { + char pathBuffer[PATH_MAX + 1] = {0}; + +#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT) + ssize_t r = readlinkat(procFd, "cwd", pathBuffer, sizeof(pathBuffer) - 1); +#else + char filename[MAX_NAME + 1]; + xSnprintf(filename, sizeof(filename), "%s/cwd", procFd); + ssize_t r = readlink(filename, pathBuffer, sizeof(pathBuffer) - 1); +#endif + + if (r < 0) { + free(process->super.procCwd); + process->super.procCwd = NULL; + return; + } + + pathBuffer[r] = '\0'; + + if (process->super.procCwd && String_eq(process->super.procCwd, pathBuffer)) + return; + + free_and_xStrdup(&process->super.procCwd, pathBuffer); +} + +#ifdef HAVE_DELAYACCT + +static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) { + struct nlmsghdr* nlhdr; + struct nlattr* nlattrs[TASKSTATS_TYPE_MAX + 1]; + const struct nlattr* nlattr; + struct taskstats stats; + int rem; + LinuxProcess* lp = (LinuxProcess*) linuxProcess; + + nlhdr = nlmsg_hdr(nlmsg); + + if (genlmsg_parse(nlhdr, 0, nlattrs, TASKSTATS_TYPE_MAX, NULL) < 0) { + return NL_SKIP; + } + + if ((nlattr = nlattrs[TASKSTATS_TYPE_AGGR_PID]) || (nlattr = nlattrs[TASKSTATS_TYPE_NULL])) { + memcpy(&stats, nla_data(nla_next(nla_data(nlattr), &rem)), sizeof(stats)); + assert(lp->super.pid == (pid_t)stats.ac_pid); + + unsigned long long int timeDelta = stats.ac_etime * 1000 - lp->delay_read_time; + #define BOUNDS(x) (isnan(x) ? 0.0 : ((x) > 100) ? 100.0 : (x)) + #define DELTAPERC(x,y) BOUNDS((float) ((x) - (y)) / timeDelta * 100) + lp->cpu_delay_percent = DELTAPERC(stats.cpu_delay_total, lp->cpu_delay_total); + lp->blkio_delay_percent = DELTAPERC(stats.blkio_delay_total, lp->blkio_delay_total); + lp->swapin_delay_percent = DELTAPERC(stats.swapin_delay_total, lp->swapin_delay_total); + #undef DELTAPERC + #undef BOUNDS + + lp->swapin_delay_total = stats.swapin_delay_total; + lp->blkio_delay_total = stats.blkio_delay_total; + lp->cpu_delay_total = stats.cpu_delay_total; + lp->delay_read_time = stats.ac_etime * 1000; + } + return NL_OK; +} + +static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProcess* process) { + struct nl_msg* msg; + + if (!this->netlink_socket) { + LinuxProcessList_initNetlinkSocket(this); + if (!this->netlink_socket) { + goto delayacct_failure; + } + } + + if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) { + goto delayacct_failure; + } + + if (! (msg = nlmsg_alloc())) { + goto delayacct_failure; + } + + if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) { + nlmsg_free(msg); + } + + if (nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, process->super.pid) < 0) { + nlmsg_free(msg); + } + + if (nl_send_sync(this->netlink_socket, msg) < 0) { + goto delayacct_failure; + } + + if (nl_recvmsgs_default(this->netlink_socket) < 0) { + goto delayacct_failure; + } + + return; + +delayacct_failure: + process->swapin_delay_percent = NAN; + process->blkio_delay_percent = NAN; + process->cpu_delay_percent = NAN; +} + +#endif + +static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t procFd) { + char command[4096 + 1]; // max cmdline length on Linux + ssize_t amtRead = xReadfileat(procFd, "cmdline", command, sizeof(command)); + if (amtRead < 0) + return false; + + if (amtRead == 0) { + if (process->state != 'Z') { + process->isKernelThread = true; + } + Process_updateCmdline(process, NULL, 0, 0); + return true; + } + + int tokenEnd = 0; + int tokenStart = 0; + int lastChar = 0; + bool argSepNUL = false; + bool argSepSpace = false; + + for (int i = 0; i < amtRead; i++) { + /* newline used as delimiter - when forming the mergedCommand, newline is + * converted to space by Process_makeCommandStr */ + if (command[i] == '\0') { + command[i] = '\n'; + } else { + /* Record some information for the argument parsing heuristic below. */ + if (tokenEnd) + argSepNUL = true; + if (command[i] <= ' ') + argSepSpace = true; + } + + if (command[i] == '\n') { + if (tokenEnd == 0) { + tokenEnd = i; + } + } else { + /* htop considers the next character after the last / that is before + * basenameOffset, as the start of the basename in cmdline - see + * Process_writeCommand */ + if (!tokenEnd && command[i] == '/') { + tokenStart = i + 1; + } + lastChar = i; + } + } + + command[lastChar + 1] = '\0'; + + if (!argSepNUL && argSepSpace) { + /* Argument parsing heuristic. + * + * This heuristic is used for processes that rewrite their command line. + * Normally the command line is split by using NUL bytes between each argument. + * But some programs like chrome flatten this using spaces. + * + * This heuristic tries its best to undo this loss of information. + * To achieve this, we treat every character <= 32 as argument separators + * (i.e. all of ASCII control sequences and space). + * We then search for the basename of the cmdline in the first argument we found that way. + * As path names may contain we try to cross-validate if the path we got that way exists. + */ + + tokenStart = tokenEnd = 0; + + // From initial scan we know there's at least one space. + // Check if that's part of a filename for an existing file. + if (Compat_faccessat(AT_FDCWD, command, F_OK, AT_SYMLINK_NOFOLLOW) != 0) { + // If we reach here the path does not exist. + // Thus begin searching for the part of it that actually is. + + int tokenArg0Start = 0; + + for (int i = 0; i <= lastChar; i++) { + /* Any ASCII control or space used as delimiter */ + char tmpCommandChar = command[i]; + + if (command[i] <= ' ') { + if (!tokenEnd) { + command[i] = '\0'; + + bool found = Compat_faccessat(AT_FDCWD, command, F_OK, AT_SYMLINK_NOFOLLOW) == 0; + + // Restore if this wasn't it + command[i] = found ? '\n' : tmpCommandChar; + + if (found) + tokenEnd = i; + if (!tokenArg0Start) + tokenArg0Start = tokenStart; + } else { + // Split on every further separator, regardless of path correctness + command[i] = '\n'; + } + } else if (!tokenEnd) { + if (command[i] == '/' || (command[i] == '\\' && (!tokenStart || command[tokenStart - 1] == '\\'))) { + tokenStart = i + 1; + } else if (command[i] == ':' && (command[i + 1] != '/' && command[i + 1] != '\\')) { + tokenEnd = i; + } + } + } + + if (!tokenEnd) { + tokenStart = tokenArg0Start; + + // No token delimiter found, forcibly split + for (int i = 0; i <= lastChar; i++) { + if (command[i] <= ' ') { + command[i] = '\n'; + if (!tokenEnd) { + tokenEnd = i; + } + } + } + } + } + + /* Some command lines are hard to parse, like + * file.so [kdeinit5] file local:/run/user/1000/klauncherdqbouY.1.slave-socket local:/run/user/1000/kded5TwsDAx.1.slave-socket + * Reset if start is behind end. + */ + if (tokenStart >= tokenEnd) + tokenStart = tokenEnd = 0; + } + + if (tokenEnd == 0) { + tokenEnd = lastChar + 1; + } + + Process_updateCmdline(process, command, tokenStart, tokenEnd); + + /* /proc/[pid]/comm could change, so should be updated */ + if ((amtRead = xReadfileat(procFd, "comm", command, sizeof(command))) > 0) { + command[amtRead - 1] = '\0'; + Process_updateComm(process, command); + } else if (process->procComm) { + Process_updateComm(process, NULL); + } + + char filename[MAX_NAME + 1]; + + /* execve could change /proc/[pid]/exe, so procExe should be updated */ +#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT) + amtRead = readlinkat(procFd, "exe", filename, sizeof(filename) - 1); +#else + char path[4096]; + xSnprintf(path, sizeof(path), "%s/exe", procFd); + amtRead = readlink(path, filename, sizeof(filename) - 1); +#endif + if (amtRead > 0) { + filename[amtRead] = 0; + if (!process->procExe || + (!process->procExeDeleted && !String_eq(filename, process->procExe)) || + (process->procExeDeleted && !String_startsWith(filename, process->procExe))) { + + const char* deletedMarker = " (deleted)"; + const size_t markerLen = strlen(deletedMarker); + const size_t filenameLen = strlen(filename); + + if (filenameLen > markerLen) { + bool oldExeDeleted = process->procExeDeleted; + + process->procExeDeleted = String_eq(filename + filenameLen - markerLen, deletedMarker); + + if (process->procExeDeleted) + filename[filenameLen - markerLen] = '\0'; + + process->mergedCommand.exeChanged |= oldExeDeleted ^ process->procExeDeleted; + } + + Process_updateExe(process, filename); + } + } else if (process->procExe) { + Process_updateExe(process, NULL); + process->procExeDeleted = false; + } + + return true; +} + +static char* LinuxProcessList_updateTtyDevice(TtyDriver* ttyDrivers, unsigned long int tty_nr) { + unsigned int maj = major(tty_nr); + unsigned int min = minor(tty_nr); + + int i = -1; + for (;;) { + i++; + if ((!ttyDrivers[i].path) || maj < ttyDrivers[i].major) { + break; + } + if (maj > ttyDrivers[i].major) { + continue; + } + if (min < ttyDrivers[i].minorFrom) { + break; + } + if (min > ttyDrivers[i].minorTo) { + continue; + } + unsigned int idx = min - ttyDrivers[i].minorFrom; + struct stat sstat; + char* fullPath; + for (;;) { + xAsprintf(&fullPath, "%s/%d", ttyDrivers[i].path, idx); + int err = stat(fullPath, &sstat); + if (err == 0 && major(sstat.st_rdev) == maj && minor(sstat.st_rdev) == min) { + return fullPath; + } + free(fullPath); + + xAsprintf(&fullPath, "%s%d", ttyDrivers[i].path, idx); + err = stat(fullPath, &sstat); + if (err == 0 && major(sstat.st_rdev) == maj && minor(sstat.st_rdev) == min) { + return fullPath; + } + free(fullPath); + + if (idx == min) { + break; + } + + idx = min; + } + int err = stat(ttyDrivers[i].path, &sstat); + if (err == 0 && tty_nr == sstat.st_rdev) { + return xStrdup(ttyDrivers[i].path); + } + } + char* out; + xAsprintf(&out, "/dev/%u:%u", maj, min); + return out; +} + +static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_t parentFd, const char* dirname, const Process* parent, double period) { + ProcessList* pl = (ProcessList*) this; + const struct dirent* entry; + const Settings* settings = pl->settings; + +#ifdef HAVE_OPENAT + int dirFd = openat(parentFd, dirname, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); + if (dirFd < 0) + return false; + DIR* dir = fdopendir(dirFd); +#else + char dirFd[4096]; + xSnprintf(dirFd, sizeof(dirFd), "%s/%s", parentFd, dirname); + DIR* dir = opendir(dirFd); +#endif + if (!dir) { + Compat_openatArgClose(dirFd); + return false; + } + + unsigned int cpus = pl->cpuCount; + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + while ((entry = readdir(dir)) != NULL) { + const char* name = entry->d_name; + + // Ignore all non-directories + if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN) { + continue; + } + + // The RedHat kernel hides threads with a dot. + // I believe this is non-standard. + if (name[0] == '.') { + name++; + } + + // Just skip all non-number directories. + if (name[0] < '0' || name[0] > '9') { + continue; + } + + // filename is a number: process directory + int pid; + { + char* endptr; + unsigned long parsedPid = strtoul(name, &endptr, 10); + if (parsedPid == 0 || parsedPid == ULONG_MAX || *endptr != '\0') + continue; + pid = parsedPid; + } + + // Skip task directory of main thread + if (parent && pid == parent->pid) + continue; + + bool preExisting; + Process* proc = ProcessList_getProcess(pl, pid, &preExisting, LinuxProcess_new); + LinuxProcess* lp = (LinuxProcess*) proc; + + proc->tgid = parent ? parent->pid : pid; + proc->isUserlandThread = proc->pid != proc->tgid; + +#ifdef HAVE_OPENAT + int procFd = openat(dirFd, entry->d_name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); + if (procFd < 0) + goto errorReadingProcess; +#else + char procFd[4096]; + xSnprintf(procFd, sizeof(procFd), "%s/%s", dirFd, entry->d_name); +#endif + + LinuxProcessList_recurseProcTree(this, procFd, "task", proc, period); + + /* + * These conditions will not trigger on first occurrence, cause we need to + * add the process to the ProcessList and do all one time scans + * (e.g. parsing the cmdline to detect a kernel thread) + * But it will short-circuit subsequent scans. + */ + if (preExisting && hideKernelThreads && Process_isKernelThread(proc)) { + proc->updated = true; + proc->show = false; + pl->kernelThreads++; + pl->totalTasks++; + Compat_openatArgClose(procFd); + continue; + } + if (preExisting && hideUserlandThreads && Process_isUserlandThread(proc)) { + proc->updated = true; + proc->show = false; + pl->userlandThreads++; + pl->totalTasks++; + Compat_openatArgClose(procFd); + continue; + } + + if (settings->flags & PROCESS_FLAG_IO) + LinuxProcessList_readIoFile(lp, procFd, pl->realtimeMs); + + if (!LinuxProcessList_readStatmFile(lp, procFd)) + goto errorReadingProcess; + + { + bool prev = proc->usesDeletedLib; + + if ((lp->m_lrs == 0 && (settings->flags & PROCESS_FLAG_LINUX_LRS_FIX)) || + (settings->highlightDeletedExe && !proc->procExeDeleted && !proc->isKernelThread && !proc->isUserlandThread)) { + // Check if we really should recalculate the M_LRS value for this process + uint64_t passedTimeInMs = pl->realtimeMs - lp->last_mlrs_calctime; + + uint64_t recheck = ((uint64_t)rand()) % 2048; + + if (passedTimeInMs > 2000 || passedTimeInMs > recheck) { + lp->last_mlrs_calctime = pl->realtimeMs; + LinuxProcessList_readMaps(lp, procFd, settings->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe); + } + } else { + /* Copy from process structure in threads and reset if setting got disabled */ + proc->usesDeletedLib = (proc->isUserlandThread && parent) ? parent->usesDeletedLib : false; + } + + proc->mergedCommand.exeChanged |= prev ^ proc->usesDeletedLib; + } + + if ((settings->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) { + if (!parent) { + // Read smaps file of each process only every second pass to improve performance + static int smaps_flag = 0; + if ((pid & 1) == smaps_flag) { + LinuxProcessList_readSmapsFile(lp, procFd, this->haveSmapsRollup); + } + if (pid == 1) { + smaps_flag = !smaps_flag; + } + } else { + lp->m_pss = ((const LinuxProcess*)parent)->m_pss; + } + } + + char statCommand[MAX_NAME + 1]; + unsigned long long int lasttimes = (lp->utime + lp->stime); + unsigned long int tty_nr = proc->tty_nr; + if (! LinuxProcessList_readStatFile(proc, procFd, statCommand, sizeof(statCommand))) + goto errorReadingProcess; + + if (tty_nr != proc->tty_nr && this->ttyDrivers) { + free(proc->tty_name); + proc->tty_name = LinuxProcessList_updateTtyDevice(this->ttyDrivers, proc->tty_nr); + } + + if (settings->flags & PROCESS_FLAG_LINUX_IOPRIO) { + LinuxProcess_updateIOPriority(lp); + } + + /* period might be 0 after system sleep */ + float percent_cpu = (period < 1E-6) ? 0.0F : ((lp->utime + lp->stime - lasttimes) / period * 100.0); + proc->percent_cpu = CLAMP(percent_cpu, 0.0F, cpus * 100.0F); + proc->percent_mem = proc->m_resident / (double)(pl->totalMem) * 100.0; + + if (! LinuxProcessList_updateUser(pl, proc, procFd)) + goto errorReadingProcess; + + if (!preExisting) { + + #ifdef HAVE_OPENVZ + if (settings->flags & PROCESS_FLAG_LINUX_OPENVZ) { + LinuxProcessList_readOpenVZData(lp, procFd); + } + #endif + + #ifdef HAVE_VSERVER + if (settings->flags & PROCESS_FLAG_LINUX_VSERVER) { + LinuxProcessList_readVServerData(lp, procFd); + } + #endif + + if (! LinuxProcessList_readCmdlineFile(proc, procFd)) { + goto errorReadingProcess; + } + + Process_fillStarttimeBuffer(proc); + + ProcessList_add(pl, proc); + } else { + if (settings->updateProcessNames && proc->state != 'Z') { + if (! LinuxProcessList_readCmdlineFile(proc, procFd)) { + goto errorReadingProcess; + } + } + } + + #ifdef HAVE_DELAYACCT + if (settings->flags & PROCESS_FLAG_LINUX_DELAYACCT) { + LinuxProcessList_readDelayAcctData(this, lp); + } + #endif + + if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) { + LinuxProcessList_readCGroupFile(lp, procFd); + } + + if (settings->flags & PROCESS_FLAG_LINUX_OOM) { + LinuxProcessList_readOomData(lp, procFd); + } + + if (settings->flags & PROCESS_FLAG_LINUX_CTXT) { + LinuxProcessList_readCtxtData(lp, procFd); + } + + if (settings->flags & PROCESS_FLAG_LINUX_SECATTR) { + LinuxProcessList_readSecattrData(lp, procFd); + } + + if (settings->flags & PROCESS_FLAG_CWD) { + LinuxProcessList_readCwd(lp, procFd); + } + + if (proc->state == 'Z' && !proc->cmdline && statCommand[0]) { + Process_updateCmdline(proc, statCommand, 0, strlen(statCommand)); + } else if (Process_isThread(proc)) { + if ((settings->showThreadNames || Process_isKernelThread(proc)) && statCommand[0]) { + Process_updateCmdline(proc, statCommand, 0, strlen(statCommand)); + } + + if (Process_isKernelThread(proc)) { + pl->kernelThreads++; + } else { + pl->userlandThreads++; + } + } + + /* Set at the end when we know if a new entry is a thread */ + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc))); + + pl->totalTasks++; + /* runningTasks is set in LinuxProcessList_scanCPUTime() from /proc/stat */ + proc->updated = true; + Compat_openatArgClose(procFd); + continue; + + // Exception handler. + +errorReadingProcess: + { +#ifdef HAVE_OPENAT + if (procFd >= 0) + close(procFd); +#endif + + if (preExisting) { + ProcessList_remove(pl, proc); + } else { + Process_delete((Object*)proc); + } + } + } + closedir(dir); + return true; +} + +static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) { + memory_t availableMem = 0; + memory_t freeMem = 0; + memory_t totalMem = 0; + memory_t buffersMem = 0; + memory_t cachedMem = 0; + memory_t sharedMem = 0; + memory_t swapTotalMem = 0; + memory_t swapCacheMem = 0; + memory_t swapFreeMem = 0; + memory_t sreclaimableMem = 0; + + FILE* file = fopen(PROCMEMINFOFILE, "r"); + if (!file) + CRT_fatalError("Cannot open " PROCMEMINFOFILE); + + char buffer[128]; + while (fgets(buffer, sizeof(buffer), file)) { + + #define tryRead(label, variable) \ + if (String_startsWith(buffer, label)) { \ + memory_t parsed_; \ + if (sscanf(buffer + strlen(label), "%llu kB", &parsed_) == 1) { \ + (variable) = parsed_; \ + } \ + break; \ + } + + switch (buffer[0]) { + case 'M': + tryRead("MemAvailable:", availableMem); + tryRead("MemFree:", freeMem); + tryRead("MemTotal:", totalMem); + break; + case 'B': + tryRead("Buffers:", buffersMem); + break; + case 'C': + tryRead("Cached:", cachedMem); + break; + case 'S': + switch (buffer[1]) { + case 'h': + tryRead("Shmem:", sharedMem); + break; + case 'w': + tryRead("SwapTotal:", swapTotalMem); + tryRead("SwapCached:", swapCacheMem); + tryRead("SwapFree:", swapFreeMem); + break; + case 'R': + tryRead("SReclaimable:", sreclaimableMem); + break; + } + break; + } + + #undef tryRead + } + + fclose(file); + + /* + * Compute memory partition like procps(free) + * https://gitlab.com/procps-ng/procps/-/blob/master/proc/sysinfo.c + * + * Adjustments: + * - Shmem in part of Cached (see https://lore.kernel.org/patchwork/patch/648763/), + * do not show twice by subtracting from Cached and do not subtract twice from used. + */ + this->totalMem = totalMem; + this->cachedMem = cachedMem + sreclaimableMem - sharedMem; + this->sharedMem = sharedMem; + const memory_t usedDiff = freeMem + cachedMem + sreclaimableMem + buffersMem; + this->usedMem = (totalMem >= usedDiff) ? totalMem - usedDiff : totalMem - freeMem; + this->buffersMem = buffersMem; + this->availableMem = availableMem != 0 ? MINIMUM(availableMem, totalMem) : freeMem; + this->totalSwap = swapTotalMem; + this->usedSwap = swapTotalMem - swapFreeMem - swapCacheMem; + this->cachedSwap = swapCacheMem; +} + +static void LinuxProcessList_scanHugePages(LinuxProcessList* this) { + this->totalHugePageMem = 0; + for (unsigned i = 0; i < HTOP_HUGEPAGE_COUNT; i++) { + this->usedHugePageMem[i] = MEMORY_MAX; + } + + DIR* dir = opendir("/sys/kernel/mm/hugepages"); + if (!dir) + return; + + const struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + const char* name = entry->d_name; + + /* Ignore all non-directories */ + if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN) + continue; + + if (!String_startsWith(name, "hugepages-")) + continue; + + char* endptr; + unsigned long int hugePageSize = strtoul(name + strlen("hugepages-"), &endptr, 10); + if (!endptr || *endptr != 'k') + continue; + + char content[64]; + char hugePagePath[128]; + ssize_t r; + + xSnprintf(hugePagePath, sizeof(hugePagePath), "/sys/kernel/mm/hugepages/%s/nr_hugepages", name); + r = xReadfile(hugePagePath, content, sizeof(content)); + if (r <= 0) + continue; + + memory_t total = strtoull(content, NULL, 10); + if (total == 0) + continue; + + xSnprintf(hugePagePath, sizeof(hugePagePath), "/sys/kernel/mm/hugepages/%s/free_hugepages", name); + r = xReadfile(hugePagePath, content, sizeof(content)); + if (r <= 0) + continue; + + memory_t free = strtoull(content, NULL, 10); + + int shift = ffsl(hugePageSize) - 1 - (HTOP_HUGEPAGE_BASE_SHIFT - 10); + assert(shift >= 0 && shift < HTOP_HUGEPAGE_COUNT); + + this->totalHugePageMem += total * hugePageSize; + this->usedHugePageMem[shift] = (total - free) * hugePageSize; + } + + closedir(dir); +} + +static inline void LinuxProcessList_scanZramInfo(LinuxProcessList* this) { + memory_t totalZram = 0; + memory_t usedZramComp = 0; + memory_t usedZramOrig = 0; + + char mm_stat[34]; + char disksize[34]; + + unsigned int i = 0; + for (;;) { + xSnprintf(mm_stat, sizeof(mm_stat), "/sys/block/zram%u/mm_stat", i); + xSnprintf(disksize, sizeof(disksize), "/sys/block/zram%u/disksize", i); + i++; + FILE* disksize_file = fopen(disksize, "r"); + FILE* mm_stat_file = fopen(mm_stat, "r"); + if (disksize_file == NULL || mm_stat_file == NULL) { + if (disksize_file) { + fclose(disksize_file); + } + if (mm_stat_file) { + fclose(mm_stat_file); + } + break; + } + memory_t size = 0; + memory_t orig_data_size = 0; + memory_t compr_data_size = 0; + + if (!fscanf(disksize_file, "%llu\n", &size) || + !fscanf(mm_stat_file, " %llu %llu", &orig_data_size, &compr_data_size)) { + fclose(disksize_file); + fclose(mm_stat_file); + break; + } + + totalZram += size; + usedZramComp += compr_data_size; + usedZramOrig += orig_data_size; + + fclose(disksize_file); + fclose(mm_stat_file); + } + + this->zram.totalZram = totalZram / 1024; + this->zram.usedZramComp = usedZramComp / 1024; + this->zram.usedZramOrig = usedZramOrig / 1024; +} + +static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + memory_t dbufSize = 0; + memory_t dnodeSize = 0; + memory_t bonusSize = 0; + + FILE* file = fopen(PROCARCSTATSFILE, "r"); + if (file == NULL) { + lpl->zfs.enabled = 0; + return; + } + char buffer[128]; + while (fgets(buffer, 128, file)) { + #define tryRead(label, variable) \ + if (String_startsWith(buffer, label)) { \ + sscanf(buffer + strlen(label), " %*2u %32llu", variable); \ + break; \ + } + #define tryReadFlag(label, variable, flag) \ + if (String_startsWith(buffer, label)) { \ + (flag) = sscanf(buffer + strlen(label), " %*2u %32llu", variable); \ + break; \ + } + + switch (buffer[0]) { + case 'c': + tryRead("c_max", &lpl->zfs.max); + tryReadFlag("compressed_size", &lpl->zfs.compressed, lpl->zfs.isCompressed); + break; + case 'u': + tryRead("uncompressed_size", &lpl->zfs.uncompressed); + break; + case 's': + tryRead("size", &lpl->zfs.size); + break; + case 'h': + tryRead("hdr_size", &lpl->zfs.header); + break; + case 'd': + tryRead("dbuf_size", &dbufSize); + tryRead("dnode_size", &dnodeSize); + break; + case 'b': + tryRead("bonus_size", &bonusSize); + break; + case 'a': + tryRead("anon_size", &lpl->zfs.anon); + break; + case 'm': + tryRead("mfu_size", &lpl->zfs.MFU); + tryRead("mru_size", &lpl->zfs.MRU); + break; + } + #undef tryRead + #undef tryReadFlag + } + fclose(file); + + lpl->zfs.enabled = (lpl->zfs.size > 0 ? 1 : 0); + lpl->zfs.size /= 1024; + lpl->zfs.max /= 1024; + lpl->zfs.MFU /= 1024; + lpl->zfs.MRU /= 1024; + lpl->zfs.anon /= 1024; + lpl->zfs.header /= 1024; + lpl->zfs.other = (dbufSize + dnodeSize + bonusSize) / 1024; + if ( lpl->zfs.isCompressed ) { + lpl->zfs.compressed /= 1024; + lpl->zfs.uncompressed /= 1024; + } +} + +static inline double LinuxProcessList_scanCPUTime(ProcessList* super) { + LinuxProcessList* this = (LinuxProcessList*) super; + + FILE* file = fopen(PROCSTATFILE, "r"); + if (!file) + CRT_fatalError("Cannot open " PROCSTATFILE); + + LinuxProcessList_updateCPUcount(super, file); + + rewind(file); + + unsigned int cpus = super->cpuCount; + for (unsigned int i = 0; i <= cpus; i++) { + char buffer[PROC_LINE_LENGTH + 1]; + unsigned long long int usertime, nicetime, systemtime, idletime; + unsigned long long int ioWait = 0, irq = 0, softIrq = 0, steal = 0, guest = 0, guestnice = 0; + // Depending on your kernel version, + // 5, 7, 8 or 9 of these fields will be set. + // The rest will remain at zero. + const char* ok = fgets(buffer, sizeof(buffer), file); + if (!ok) + break; + + if (i == 0) { + (void) sscanf(buffer, "cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice); + } else { + unsigned int cpuid; + (void) sscanf(buffer, "cpu%4u %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice); + assert(cpuid == i - 1); + } + // Guest time is already accounted in usertime + usertime -= guest; + nicetime -= guestnice; + // Fields existing on kernels >= 2.6 + // (and RHEL's patched kernel 2.4...) + unsigned long long int idlealltime = idletime + ioWait; + unsigned long long int systemalltime = systemtime + irq + softIrq; + unsigned long long int virtalltime = guest + guestnice; + unsigned long long int totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime; + CPUData* cpuData = &(this->cpus[i]); + // Since we do a subtraction (usertime - guest) and cputime64_to_clock_t() + // used in /proc/stat rounds down numbers, it can lead to a case where the + // integer overflow. + cpuData->userPeriod = saturatingSub(usertime, cpuData->userTime); + cpuData->nicePeriod = saturatingSub(nicetime, cpuData->niceTime); + cpuData->systemPeriod = saturatingSub(systemtime, cpuData->systemTime); + cpuData->systemAllPeriod = saturatingSub(systemalltime, cpuData->systemAllTime); + cpuData->idleAllPeriod = saturatingSub(idlealltime, cpuData->idleAllTime); + cpuData->idlePeriod = saturatingSub(idletime, cpuData->idleTime); + cpuData->ioWaitPeriod = saturatingSub(ioWait, cpuData->ioWaitTime); + cpuData->irqPeriod = saturatingSub(irq, cpuData->irqTime); + cpuData->softIrqPeriod = saturatingSub(softIrq, cpuData->softIrqTime); + cpuData->stealPeriod = saturatingSub(steal, cpuData->stealTime); + cpuData->guestPeriod = saturatingSub(virtalltime, cpuData->guestTime); + cpuData->totalPeriod = saturatingSub(totaltime, cpuData->totalTime); + cpuData->userTime = usertime; + cpuData->niceTime = nicetime; + cpuData->systemTime = systemtime; + cpuData->systemAllTime = systemalltime; + cpuData->idleAllTime = idlealltime; + cpuData->idleTime = idletime; + cpuData->ioWaitTime = ioWait; + cpuData->irqTime = irq; + cpuData->softIrqTime = softIrq; + cpuData->stealTime = steal; + cpuData->guestTime = virtalltime; + cpuData->totalTime = totaltime; + } + + double period = (double)this->cpus[0].totalPeriod / cpus; + + char buffer[PROC_LINE_LENGTH + 1]; + while (fgets(buffer, sizeof(buffer), file)) { + if (String_startsWith(buffer, "procs_running")) { + super->runningTasks = strtoul(buffer + strlen("procs_running"), NULL, 10); + break; + } + } + + fclose(file); + + return period; +} + +static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) { + unsigned int cpus = this->super.cpuCount; + int numCPUsWithFrequency = 0; + unsigned long totalFrequency = 0; + + /* + * On some AMD and Intel CPUs read()ing scaling_cur_freq is quite slow (> 1ms). This delay + * accumulates for every core. For details see issue#471. + * If the read on CPU 0 takes longer than 500us bail out and fall back to reading the + * frequencies from /proc/cpuinfo. + * Once the condition has been met, bail out early for the next couple of scans. + */ + static int timeout = 0; + + if (timeout > 0) { + timeout--; + return -1; + } + + for (unsigned int i = 0; i < cpus; ++i) { + char pathBuffer[64]; + xSnprintf(pathBuffer, sizeof(pathBuffer), "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", i); + + struct timespec start; + if (i == 0) + clock_gettime(CLOCK_MONOTONIC, &start); + + FILE* file = fopen(pathBuffer, "r"); + if (!file) + return -errno; + + unsigned long frequency; + if (fscanf(file, "%lu", &frequency) == 1) { + /* convert kHz to MHz */ + frequency = frequency / 1000; + this->cpus[i + 1].frequency = frequency; + numCPUsWithFrequency++; + totalFrequency += frequency; + } + + fclose(file); + + if (i == 0) { + struct timespec end; + clock_gettime(CLOCK_MONOTONIC, &end); + const time_t timeTakenUs = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000; + if (timeTakenUs > 500) { + timeout = 30; + return -1; + } + } + + } + + if (numCPUsWithFrequency > 0) + this->cpus[0].frequency = (double)totalFrequency / numCPUsWithFrequency; + + return 0; +} + +static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) { + FILE* file = fopen(PROCCPUINFOFILE, "r"); + if (file == NULL) + return; + + unsigned int cpus = this->super.cpuCount; + int numCPUsWithFrequency = 0; + double totalFrequency = 0; + int cpuid = -1; + + while (!feof(file)) { + double frequency; + char buffer[PROC_LINE_LENGTH]; + + if (fgets(buffer, PROC_LINE_LENGTH, file) == NULL) + break; + + if ( + (sscanf(buffer, "processor : %d", &cpuid) == 1) || + (sscanf(buffer, "processor: %d", &cpuid) == 1) + ) { + continue; + } else if ( + (sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) || + (sscanf(buffer, "cpu MHz: %lf", &frequency) == 1) || + (sscanf(buffer, "clock : %lfMHz", &frequency) == 1) || + (sscanf(buffer, "clock: %lfMHz", &frequency) == 1) + ) { + if (cpuid < 0 || (unsigned int)cpuid > (cpus - 1)) { + continue; + } + + CPUData* cpuData = &(this->cpus[cpuid + 1]); + /* do not override sysfs data */ + if (isnan(cpuData->frequency)) { + cpuData->frequency = frequency; + } + numCPUsWithFrequency++; + totalFrequency += frequency; + } else if (buffer[0] == '\n') { + cpuid = -1; + } + } + fclose(file); + + if (numCPUsWithFrequency > 0) { + this->cpus[0].frequency = totalFrequency / numCPUsWithFrequency; + } +} + +static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) { + unsigned int cpus = this->super.cpuCount; + + for (unsigned int i = 0; i <= cpus; i++) { + this->cpus[i].frequency = NAN; + } + + if (scanCPUFreqencyFromSysCPUFreq(this) == 0) { + return; + } + + scanCPUFreqencyFromCPUinfo(this); +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + LinuxProcessList* this = (LinuxProcessList*) super; + const Settings* settings = super->settings; + + LinuxProcessList_scanMemoryInfo(super); + LinuxProcessList_scanHugePages(this); + LinuxProcessList_scanZfsArcstats(this); + LinuxProcessList_scanZramInfo(this); + + double period = LinuxProcessList_scanCPUTime(super); + + if (settings->showCPUFrequency) { + LinuxProcessList_scanCPUFrequency(this); + } + + #ifdef HAVE_SENSORS_SENSORS_H + if (settings->showCPUTemperature) + LibSensors_getCPUTemperatures(this->cpus, this->super.cpuCount); + #endif + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + /* PROCDIR is an absolute path */ + assert(PROCDIR[0] == '/'); +#ifdef HAVE_OPENAT + openat_arg_t rootFd = AT_FDCWD; +#else + openat_arg_t rootFd = ""; +#endif + + LinuxProcessList_recurseProcTree(this, rootFd, PROCDIR, NULL, period); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/LinuxProcessList.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,120 @@ +#ifndef HEADER_LinuxProcessList +#define HEADER_LinuxProcessList +/* +htop - LinuxProcessList.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" + +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" +#include "ZramStats.h" +#include "zfs/ZfsArcStats.h" + +#define HTOP_HUGEPAGE_BASE_SHIFT 16 +#define HTOP_HUGEPAGE_COUNT 24 + +typedef struct CPUData_ { + unsigned long long int totalTime; + unsigned long long int userTime; + unsigned long long int systemTime; + unsigned long long int systemAllTime; + unsigned long long int idleAllTime; + unsigned long long int idleTime; + unsigned long long int niceTime; + unsigned long long int ioWaitTime; + unsigned long long int irqTime; + unsigned long long int softIrqTime; + unsigned long long int stealTime; + unsigned long long int guestTime; + + unsigned long long int totalPeriod; + unsigned long long int userPeriod; + unsigned long long int systemPeriod; + unsigned long long int systemAllPeriod; + unsigned long long int idleAllPeriod; + unsigned long long int idlePeriod; + unsigned long long int nicePeriod; + unsigned long long int ioWaitPeriod; + unsigned long long int irqPeriod; + unsigned long long int softIrqPeriod; + unsigned long long int stealPeriod; + unsigned long long int guestPeriod; + + double frequency; + + #ifdef HAVE_SENSORS_SENSORS_H + double temperature; + #endif +} CPUData; + +typedef struct TtyDriver_ { + char* path; + unsigned int major; + unsigned int minorFrom; + unsigned int minorTo; +} TtyDriver; + +typedef struct LinuxProcessList_ { + ProcessList super; + + CPUData* cpus; + TtyDriver* ttyDrivers; + bool haveSmapsRollup; + + #ifdef HAVE_DELAYACCT + struct nl_sock* netlink_socket; + int netlink_family; + #endif + + memory_t totalHugePageMem; + memory_t usedHugePageMem[HTOP_HUGEPAGE_COUNT]; + + memory_t availableMem; + + ZfsArcStats zfs; + ZramStats zram; +} LinuxProcessList; + +#ifndef PROCDIR +#define PROCDIR "/proc" +#endif + +#ifndef PROCCPUINFOFILE +#define PROCCPUINFOFILE PROCDIR "/cpuinfo" +#endif + +#ifndef PROCSTATFILE +#define PROCSTATFILE PROCDIR "/stat" +#endif + +#ifndef PROCMEMINFOFILE +#define PROCMEMINFOFILE PROCDIR "/meminfo" +#endif + +#ifndef PROCARCSTATSFILE +#define PROCARCSTATSFILE PROCDIR "/spl/kstat/zfs/arcstats" +#endif + +#ifndef PROCTTYDRIVERSFILE +#define PROCTTYDRIVERSFILE PROCDIR "/tty/drivers" +#endif + +#ifndef PROC_LINE_LENGTH +#define PROC_LINE_LENGTH 4096 +#endif + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* pl); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/Platform.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,1011 @@ +/* +htop - linux/Platform.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" + +#include "linux/Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "BatteryMeter.h" +#include "ClockMeter.h" +#include "Compat.h" +#include "CPUMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "DiskIOMeter.h" +#include "HostnameMeter.h" +#include "HugePageMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MainPanel.h" +#include "Meter.h" +#include "MemoryMeter.h" +#include "NetworkIOMeter.h" +#include "Object.h" +#include "Panel.h" +#include "PressureStallMeter.h" +#include "ProcessList.h" +#include "ProvideCurses.h" +#include "linux/SELinuxMeter.h" +#include "Settings.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "XUtils.h" +#include "linux/IOPriority.h" +#include "linux/IOPriorityPanel.h" +#include "linux/LinuxProcess.h" +#include "linux/LinuxProcessList.h" +#include "linux/SystemdMeter.h" +#include "linux/ZramMeter.h" +#include "linux/ZramStats.h" +#include "zfs/ZfsArcMeter.h" +#include "zfs/ZfsArcStats.h" +#include "zfs/ZfsCompressedArcMeter.h" + +#ifdef HAVE_LIBCAP +#include +#include +#endif + +#ifdef HAVE_SENSORS_SENSORS_H +#include "LibSensors.h" +#endif + + +#ifdef HAVE_LIBCAP +enum CapMode { + CAP_MODE_OFF, + CAP_MODE_BASIC, + CAP_MODE_STRICT +}; +#endif + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 6 SIGIOT", .number = 6 }, + { .name = " 7 SIGBUS", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGUSR1", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGUSR2", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGSTKFLT", .number = 16 }, + { .name = "17 SIGCHLD", .number = 17 }, + { .name = "18 SIGCONT", .number = 18 }, + { .name = "19 SIGSTOP", .number = 19 }, + { .name = "20 SIGTSTP", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGURG", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGIO", .number = 29 }, + { .name = "29 SIGPOLL", .number = 29 }, + { .name = "30 SIGPWR", .number = 30 }, + { .name = "31 SIGSYS", .number = 31 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +static enum { BAT_PROC, BAT_SYS, BAT_ERR } Platform_Battery_method = BAT_PROC; +static time_t Platform_Battery_cacheTime; +static double Platform_Battery_cachePercent = NAN; +static ACPresence Platform_Battery_cacheIsOnAC; + +#ifdef HAVE_LIBCAP +static enum CapMode Platform_capabilitiesMode = CAP_MODE_BASIC; +#endif + +static Htop_Reaction Platform_actionSetIOPriority(State* st) { + if (Settings_isReadonly()) + return HTOP_OK; + + const LinuxProcess* p = (const LinuxProcess*) Panel_getSelected((Panel*)st->mainPanel); + if (!p) + return HTOP_OK; + + IOPriority ioprio1 = p->ioPriority; + Panel* ioprioPanel = IOPriorityPanel_new(ioprio1); + const void* set = Action_pickFromVector(st, ioprioPanel, 21, true); + if (set) { + IOPriority ioprio2 = IOPriorityPanel_getIOPriority(ioprioPanel); + bool ok = MainPanel_foreachProcess(st->mainPanel, LinuxProcess_setIOPriority, (Arg) { .i = ioprio2 }, NULL); + if (!ok) { + beep(); + } + } + Panel_delete((Object*)ioprioPanel); + return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; +} + +void Platform_setBindings(Htop_Action* keys) { + keys['i'] = Platform_actionSetIOPriority; +} + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &SysArchMeter_class, + &HugePageMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + &PressureStallCPUSomeMeter_class, + &PressureStallIOSomeMeter_class, + &PressureStallIOFullMeter_class, + &PressureStallMemorySomeMeter_class, + &PressureStallMemoryFullMeter_class, + &ZfsArcMeter_class, + &ZfsCompressedArcMeter_class, + &ZramMeter_class, + &DiskIOMeter_class, + &NetworkIOMeter_class, + &SELinuxMeter_class, + &SystemdMeter_class, + NULL +}; + +int Platform_getUptime() { + double uptime = 0; + FILE* fd = fopen(PROCDIR "/uptime", "r"); + if (fd) { + int n = fscanf(fd, "%64lf", &uptime); + fclose(fd); + if (n <= 0) { + return 0; + } + } + return floor(uptime); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + FILE* fd = fopen(PROCDIR "/loadavg", "r"); + if (!fd) + goto err; + + double scanOne, scanFive, scanFifteen; + int r = fscanf(fd, "%lf %lf %lf", &scanOne, &scanFive, &scanFifteen); + fclose(fd); + if (r != 3) + goto err; + + *one = scanOne; + *five = scanFive; + *fifteen = scanFifteen; + return; + +err: + *one = NAN; + *five = NAN; + *fifteen = NAN; +} + +int Platform_getMaxPid() { + FILE* file = fopen(PROCDIR "/sys/kernel/pid_max", "r"); + if (!file) + return -1; + + int maxPid = 4194303; + int match = fscanf(file, "%32d", &maxPid); + (void) match; + fclose(file); + return maxPid; +} + +double Platform_setCPUValues(Meter* this, unsigned int cpu) { + const LinuxProcessList* pl = (const LinuxProcessList*) this->pl; + const CPUData* cpuData = &(pl->cpus[cpu]); + double total = (double) ( cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod); + double percent; + double* v = this->values; + v[CPU_METER_NICE] = cpuData->nicePeriod / total * 100.0; + v[CPU_METER_NORMAL] = cpuData->userPeriod / total * 100.0; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->systemPeriod / total * 100.0; + v[CPU_METER_IRQ] = cpuData->irqPeriod / total * 100.0; + v[CPU_METER_SOFTIRQ] = cpuData->softIrqPeriod / total * 100.0; + v[CPU_METER_STEAL] = cpuData->stealPeriod / total * 100.0; + v[CPU_METER_GUEST] = cpuData->guestPeriod / total * 100.0; + v[CPU_METER_IOWAIT] = cpuData->ioWaitPeriod / total * 100.0; + this->curItems = 8; + if (this->pl->settings->accountGuestInCPUMeter) { + percent = v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6]; + } else { + percent = v[0] + v[1] + v[2] + v[3] + v[4]; + } + } else { + v[2] = cpuData->systemAllPeriod / total * 100.0; + v[3] = (cpuData->stealPeriod + cpuData->guestPeriod) / total * 100.0; + this->curItems = 4; + percent = v[0] + v[1] + v[2] + v[3]; + } + percent = CLAMP(percent, 0.0, 100.0); + if (isnan(percent)) { + percent = 0.0; + } + + v[CPU_METER_FREQUENCY] = cpuData->frequency; + +#ifdef HAVE_SENSORS_SENSORS_H + v[CPU_METER_TEMPERATURE] = cpuData->temperature; +#else + v[CPU_METER_TEMPERATURE] = NAN; +#endif + + return percent; +} + +void Platform_setMemoryValues(Meter* this) { + const ProcessList* pl = this->pl; + const LinuxProcessList* lpl = (const LinuxProcessList*) pl; + + this->total = pl->totalMem > lpl->totalHugePageMem ? pl->totalMem - lpl->totalHugePageMem : pl->totalMem; + this->values[0] = pl->usedMem > lpl->totalHugePageMem ? pl->usedMem - lpl->totalHugePageMem : pl->usedMem; + this->values[1] = pl->buffersMem; + this->values[2] = pl->sharedMem; + this->values[3] = pl->cachedMem; + this->values[4] = pl->availableMem; + + if (lpl->zfs.enabled != 0) { + this->values[0] -= lpl->zfs.size; + this->values[3] += lpl->zfs.size; + } +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = pl->cachedSwap; +} + +void Platform_setZramValues(Meter* this) { + const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl; + this->total = lpl->zram.totalZram; + this->values[0] = lpl->zram.usedZramComp; + this->values[1] = lpl->zram.usedZramOrig; +} + +void Platform_setZfsArcValues(Meter* this) { + const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl; + + ZfsArcMeter_readStats(this, &(lpl->zfs)); +} + +void Platform_setZfsCompressedArcValues(Meter* this) { + const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl; + + ZfsCompressedArcMeter_readStats(this, &(lpl->zfs)); +} + +char* Platform_getProcessEnv(pid_t pid) { + char procname[128]; + xSnprintf(procname, sizeof(procname), PROCDIR "/%d/environ", pid); + FILE* fd = fopen(procname, "r"); + if (!fd) + return NULL; + + char* env = NULL; + + size_t capacity = 0; + size_t size = 0; + ssize_t bytes = 0; + + do { + size += bytes; + capacity += 4096; + env = xRealloc(env, capacity); + } while ((bytes = fread(env + size, 1, capacity - size, fd)) > 0); + + fclose(fd); + + if (bytes < 0) { + free(env); + return NULL; + } + + size += bytes; + + env = xRealloc(env, size + 2); + + env[size] = '\0'; + env[size + 1] = '\0'; + + return env; +} + +/* + * Return the absolute path of a file given its pid&inode number + * + * Based on implementation of lslocks from util-linux: + * https://sources.debian.org/src/util-linux/2.36-3/misc-utils/lslocks.c/#L162 + */ +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + struct stat sb; + const struct dirent* de; + DIR* dirp; + ssize_t len; + int fd; + + char path[PATH_MAX]; + char sym[PATH_MAX]; + char* ret = NULL; + + memset(path, 0, sizeof(path)); + memset(sym, 0, sizeof(sym)); + + xSnprintf(path, sizeof(path), "%s/%d/fd/", PROCDIR, pid); + if (strlen(path) >= (sizeof(path) - 2)) + return NULL; + + if (!(dirp = opendir(path))) + return NULL; + + if ((fd = dirfd(dirp)) < 0 ) + goto out; + + while ((de = readdir(dirp))) { + if (String_eq(de->d_name, ".") || String_eq(de->d_name, "..")) + continue; + + /* care only for numerical descriptors */ + if (!strtoull(de->d_name, (char **) NULL, 10)) + continue; + + if (!Compat_fstatat(fd, path, de->d_name, &sb, 0) && inode != sb.st_ino) + continue; + + if ((len = Compat_readlinkat(fd, path, de->d_name, sym, sizeof(sym) - 1)) < 1) + goto out; + + sym[len] = '\0'; + + ret = xStrdup(sym); + break; + } + +out: + closedir(dirp); + return ret; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + FileLocks_ProcessData* pdata = xCalloc(1, sizeof(FileLocks_ProcessData)); + + FILE* f = fopen(PROCDIR "/locks", "r"); + if (!f) { + pdata->error = true; + return pdata; + } + + char buffer[1024]; + FileLocks_LockData** data_ref = &pdata->locks; + while(fgets(buffer, sizeof(buffer), f)) { + if (!strchr(buffer, '\n')) + continue; + + int lock_id; + char lock_type[16]; + char lock_excl[16]; + char lock_rw[16]; + pid_t lock_pid; + unsigned int lock_dev[2]; + uint64_t lock_inode; + char lock_start[25]; + char lock_end[25]; + + if (10 != sscanf(buffer, "%d: %15s %15s %15s %d %x:%x:%"PRIu64" %24s %24s", + &lock_id, lock_type, lock_excl, lock_rw, &lock_pid, + &lock_dev[0], &lock_dev[1], &lock_inode, + lock_start, lock_end)) + continue; + + if (pid != lock_pid) + continue; + + FileLocks_LockData* ldata = xCalloc(1, sizeof(FileLocks_LockData)); + FileLocks_Data* data = &ldata->data; + data->id = lock_id; + data->locktype = xStrdup(lock_type); + data->exclusive = xStrdup(lock_excl); + data->readwrite = xStrdup(lock_rw); + data->filename = Platform_getInodeFilename(lock_pid, lock_inode); + data->dev[0] = lock_dev[0]; + data->dev[1] = lock_dev[1]; + data->inode = lock_inode; + data->start = strtoull(lock_start, NULL, 10); + if (!String_eq(lock_end, "EOF")) { + data->end = strtoull(lock_end, NULL, 10); + } else { + data->end = ULLONG_MAX; + } + + *data_ref = ldata; + data_ref = &ldata->next; + } + + fclose(f); + return pdata; +} + +void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred) { + *ten = *sixty = *threehundred = 0; + char procname[128]; + xSnprintf(procname, sizeof(procname), PROCDIR "/pressure/%s", file); + FILE* fd = fopen(procname, "r"); + if (!fd) { + *ten = *sixty = *threehundred = NAN; + return; + } + int total = fscanf(fd, "some avg10=%32lf avg60=%32lf avg300=%32lf total=%*f ", ten, sixty, threehundred); + if (!some) { + total = fscanf(fd, "full avg10=%32lf avg60=%32lf avg300=%32lf total=%*f ", ten, sixty, threehundred); + } + (void) total; + assert(total == 3); + fclose(fd); +} + +bool Platform_getDiskIO(DiskIOData* data) { + FILE* fd = fopen(PROCDIR "/diskstats", "r"); + if (!fd) + return false; + + unsigned long long int read_sum = 0, write_sum = 0, timeSpend_sum = 0; + char lineBuffer[256]; + while (fgets(lineBuffer, sizeof(lineBuffer), fd)) { + char diskname[32]; + unsigned long long int read_tmp, write_tmp, timeSpend_tmp; + if (sscanf(lineBuffer, "%*d %*d %31s %*u %*u %llu %*u %*u %*u %llu %*u %*u %llu", diskname, &read_tmp, &write_tmp, &timeSpend_tmp) == 4) { + if (String_startsWith(diskname, "dm-")) + continue; + + /* only count root disks, e.g. do not count IO from sda and sda1 twice */ + if ((diskname[0] == 's' || diskname[0] == 'h') + && diskname[1] == 'd' + && isalpha((unsigned char)diskname[2]) + && isdigit((unsigned char)diskname[3])) + continue; + + /* only count root disks, e.g. do not count IO from mmcblk0 and mmcblk0p1 twice */ + if (diskname[0] == 'm' + && diskname[1] == 'm' + && diskname[2] == 'c' + && diskname[3] == 'b' + && diskname[4] == 'l' + && diskname[5] == 'k' + && isdigit((unsigned char)diskname[6]) + && diskname[7] == 'p') + continue; + + read_sum += read_tmp; + write_sum += write_tmp; + timeSpend_sum += timeSpend_tmp; + } + } + fclose(fd); + /* multiply with sector size */ + data->totalBytesRead = 512 * read_sum; + data->totalBytesWritten = 512 * write_sum; + data->totalMsTimeSpend = timeSpend_sum; + return true; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + FILE* fd = fopen(PROCDIR "/net/dev", "r"); + if (!fd) + return false; + + memset(data, 0, sizeof(NetworkIOData)); + char lineBuffer[512]; + while (fgets(lineBuffer, sizeof(lineBuffer), fd)) { + char interfaceName[32]; + unsigned long long int bytesReceived, packetsReceived, bytesTransmitted, packetsTransmitted; + if (sscanf(lineBuffer, "%31s %llu %llu %*u %*u %*u %*u %*u %*u %llu %llu", + interfaceName, + &bytesReceived, + &packetsReceived, + &bytesTransmitted, + &packetsTransmitted) != 5) + continue; + + if (String_eq(interfaceName, "lo:")) + continue; + + data->bytesReceived += bytesReceived; + data->packetsReceived += packetsReceived; + data->bytesTransmitted += bytesTransmitted; + data->packetsTransmitted += packetsTransmitted; + } + + fclose(fd); + + return true; +} + +// Linux battery reading by Ian P. Hands (iphands@gmail.com, ihands@redhat.com). + +#define MAX_BATTERIES 64 +#define PROC_BATTERY_DIR PROCDIR "/acpi/battery" +#define PROC_POWERSUPPLY_DIR PROCDIR "/acpi/ac_adapter" +#define SYS_POWERSUPPLY_DIR "/sys/class/power_supply" + +// ---------------------------------------- +// READ FROM /proc +// ---------------------------------------- + +static unsigned long int parseBatInfo(const char* fileName, const unsigned short int lineNum, const unsigned short int wordNum) { + const char batteryPath[] = PROC_BATTERY_DIR; + DIR* batteryDir = opendir(batteryPath); + if (!batteryDir) + return 0; + + char* batteries[MAX_BATTERIES]; + unsigned int nBatteries = 0; + memset(batteries, 0, MAX_BATTERIES * sizeof(char*)); + + while (nBatteries < MAX_BATTERIES) { + const struct dirent* dirEntry = readdir(batteryDir); + if (!dirEntry) + break; + + const char* entryName = dirEntry->d_name; + if (!String_startsWith(entryName, "BAT")) + continue; + + batteries[nBatteries] = xStrdup(entryName); + nBatteries++; + } + closedir(batteryDir); + + unsigned long int total = 0; + for (unsigned int i = 0; i < nBatteries; i++) { + char infoPath[30]; + xSnprintf(infoPath, sizeof infoPath, "%s%s/%s", batteryPath, batteries[i], fileName); + + FILE* file = fopen(infoPath, "r"); + if (!file) + break; + + char* line = NULL; + for (unsigned short int j = 0; j < lineNum; j++) { + free(line); + line = String_readLine(file); + if (!line) + break; + } + + fclose(file); + + if (!line) + break; + + char* foundNumStr = String_getToken(line, wordNum); + const unsigned long int foundNum = atoi(foundNumStr); + free(foundNumStr); + free(line); + + total += foundNum; + } + + for (unsigned int i = 0; i < nBatteries; i++) + free(batteries[i]); + + return total; +} + +static ACPresence procAcpiCheck(void) { + ACPresence isOn = AC_ERROR; + const char* power_supplyPath = PROC_POWERSUPPLY_DIR; + DIR* dir = opendir(power_supplyPath); + if (!dir) + return AC_ERROR; + + for (;;) { + const struct dirent* dirEntry = readdir(dir); + if (!dirEntry) + break; + + const char* entryName = dirEntry->d_name; + + if (entryName[0] != 'A') + continue; + + char statePath[256]; + xSnprintf(statePath, sizeof(statePath), "%s/%s/state", power_supplyPath, entryName); + FILE* file = fopen(statePath, "r"); + if (!file) { + isOn = AC_ERROR; + continue; + } + char* line = String_readLine(file); + + fclose(file); + + if (!line) + continue; + + char* isOnline = String_getToken(line, 2); + free(line); + + if (String_eq(isOnline, "on-line")) + isOn = AC_PRESENT; + else + isOn = AC_ABSENT; + free(isOnline); + if (isOn == AC_PRESENT) + break; + } + + closedir(dir); + + return isOn; +} + +static double Platform_Battery_getProcBatInfo(void) { + const unsigned long int totalFull = parseBatInfo("info", 3, 4); + if (totalFull == 0) + return NAN; + + const unsigned long int totalRemain = parseBatInfo("state", 5, 3); + if (totalRemain == 0) + return NAN; + + return totalRemain * 100.0 / (double) totalFull; +} + +static void Platform_Battery_getProcData(double* percent, ACPresence* isOnAC) { + *isOnAC = procAcpiCheck(); + *percent = AC_ERROR != *isOnAC ? Platform_Battery_getProcBatInfo() : NAN; +} + +// ---------------------------------------- +// READ FROM /sys +// ---------------------------------------- + +static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) { + + *percent = NAN; + *isOnAC = AC_ERROR; + + DIR* dir = opendir(SYS_POWERSUPPLY_DIR); + if (!dir) + return; + + unsigned long int totalFull = 0; + unsigned long int totalRemain = 0; + + for (;;) { + const struct dirent* dirEntry = readdir(dir); + if (!dirEntry) + break; + + const char* entryName = dirEntry->d_name; + char filePath[256]; + + xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/type", entryName); + + char type[8]; + ssize_t r = xReadfile(filePath, type, sizeof(type)); + if (r < 3) + continue; + + if (type[0] == 'B' && type[1] == 'a' && type[2] == 't') { + xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/uevent", entryName); + + char buffer[1024]; + r = xReadfile(filePath, buffer, sizeof(buffer)); + if (r < 0) { + closedir(dir); + return; + } + + char* buf = buffer; + const char* line; + bool full = false; + bool now = false; + int fullSize = 0; + double capacityLevel = NAN; + + #define match(str,prefix) \ + (String_startsWith(str,prefix) ? (str) + strlen(prefix) : NULL) + + while ((line = strsep(&buf, "\n")) != NULL) { + const char* ps = match(line, "POWER_SUPPLY_"); + if (!ps) + continue; + const char* capacity = match(ps, "CAPACITY="); + if (capacity) + capacityLevel = atoi(capacity) / 100.0; + const char* energy = match(ps, "ENERGY_"); + if (!energy) + energy = match(ps, "CHARGE_"); + if (!energy) + continue; + const char* value = (!full) ? match(energy, "FULL=") : NULL; + if (value) { + fullSize = atoi(value); + totalFull += fullSize; + full = true; + if (now) + break; + continue; + } + value = (!now) ? match(energy, "NOW=") : NULL; + if (value) { + totalRemain += atoi(value); + now = true; + if (full) + break; + continue; + } + } + + #undef match + + if (!now && full && !isnan(capacityLevel)) + totalRemain += (capacityLevel * fullSize); + + } else if (entryName[0] == 'A') { + if (*isOnAC != AC_ERROR) + continue; + + xSnprintf(filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/online", entryName); + + char buffer[2]; + + r = xReadfile(filePath, buffer, sizeof(buffer)); + if (r < 1) { + closedir(dir); + return; + } + + if (buffer[0] == '0') + *isOnAC = AC_ABSENT; + else if (buffer[0] == '1') + *isOnAC = AC_PRESENT; + } + } + closedir(dir); + + *percent = totalFull > 0 ? ((double) totalRemain * 100.0) / (double) totalFull : NAN; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + time_t now = time(NULL); + // update battery reading is slow. Update it each 10 seconds only. + if (now < Platform_Battery_cacheTime + 10) { + *percent = Platform_Battery_cachePercent; + *isOnAC = Platform_Battery_cacheIsOnAC; + return; + } + + if (Platform_Battery_method == BAT_PROC) { + Platform_Battery_getProcData(percent, isOnAC); + if (isnan(*percent)) + Platform_Battery_method = BAT_SYS; + } + if (Platform_Battery_method == BAT_SYS) { + Platform_Battery_getSysData(percent, isOnAC); + if (isnan(*percent)) + Platform_Battery_method = BAT_ERR; + } + if (Platform_Battery_method == BAT_ERR) { + *percent = NAN; + *isOnAC = AC_ERROR; + } else { + *percent = CLAMP(*percent, 0.0, 100.0); + } + Platform_Battery_cachePercent = *percent; + Platform_Battery_cacheIsOnAC = *isOnAC; + Platform_Battery_cacheTime = now; +} + +void Platform_longOptionsUsage(const char* name) +{ +#ifdef HAVE_LIBCAP + printf( +" --drop-capabilities[=off|basic|strict] Drop Linux capabilities when running as root\n" +" off - do not drop any capabilities\n" +" basic (default) - drop all capabilities not needed by %s\n" +" strict - drop all capabilities except those needed for\n" +" core functionality\n", name); +#else + (void) name; +#endif +} + +bool Platform_getLongOption(int opt, int argc, char** argv) { +#ifndef HAVE_LIBCAP + (void) argc; + (void) argv; +#endif + + switch (opt) { +#ifdef HAVE_LIBCAP + case 160: { + const char* mode = optarg; + if (!mode && optind < argc && argv[optind] != NULL && + (argv[optind][0] != '\0' && argv[optind][0] != '-')) { + mode = argv[optind++]; + } + + if (!mode || String_eq(mode, "basic")) { + Platform_capabilitiesMode = CAP_MODE_BASIC; + } else if (String_eq(mode, "off")) { + Platform_capabilitiesMode = CAP_MODE_OFF; + } else if (String_eq(mode, "strict")) { + Platform_capabilitiesMode = CAP_MODE_STRICT; + } else { + fprintf(stderr, "Error: invalid capabilities mode \"%s\".\n", mode); + exit(1); + } + return true; + } +#endif + + default: + break; + } + return false; +} + +#ifdef HAVE_LIBCAP +static int dropCapabilities(enum CapMode mode) { + + if (mode == CAP_MODE_OFF) + return 0; + + /* capabilities we keep to operate */ + const cap_value_t keepcapsStrict[] = { + CAP_DAC_READ_SEARCH, + CAP_SYS_PTRACE, + }; + const cap_value_t keepcapsBasic[] = { + CAP_DAC_READ_SEARCH, /* read non world-readable process files of other users, like /proc/[pid]/io */ + CAP_KILL, /* send signals to processes of other users */ + CAP_SYS_NICE, /* lower process nice value / change nice value for arbitrary processes */ + CAP_SYS_PTRACE, /* read /proc/[pid]/exe */ +#ifdef HAVE_DELAYACCT + CAP_NET_ADMIN, /* communicate over netlink socket for delay accounting */ +#endif + }; + const cap_value_t* const keepcaps = (mode == CAP_MODE_BASIC) ? keepcapsBasic : keepcapsStrict; + const size_t ncap = (mode == CAP_MODE_BASIC) ? ARRAYSIZE(keepcapsBasic) : ARRAYSIZE(keepcapsStrict); + + cap_t caps = cap_init(); + if (caps == NULL) { + fprintf(stderr, "Error: can not initialize capabilities: %s\n", strerror(errno)); + return -1; + } + + if (cap_clear(caps) < 0) { + fprintf(stderr, "Error: can not clear capabilities: %s\n", strerror(errno)); + cap_free(caps); + return -1; + } + + cap_t currCaps = cap_get_proc(); + if (currCaps == NULL) { + fprintf(stderr, "Error: can not get current process capabilities: %s\n", strerror(errno)); + cap_free(caps); + return -1; + } + + for (size_t i = 0; i < ncap; i++) { + if (!CAP_IS_SUPPORTED(keepcaps[i])) + continue; + + cap_flag_value_t current; + if (cap_get_flag(currCaps, keepcaps[i], CAP_PERMITTED, ¤t) < 0) { + fprintf(stderr, "Error: can not get current value of capability %d: %s\n", keepcaps[i], strerror(errno)); + cap_free(currCaps); + cap_free(caps); + return -1; + } + + if (current != CAP_SET) + continue; + + if (cap_set_flag(caps, CAP_PERMITTED, 1, &keepcaps[i], CAP_SET) < 0) { + fprintf(stderr, "Error: can not set permitted capability %d: %s\n", keepcaps[i], strerror(errno)); + cap_free(currCaps); + cap_free(caps); + return -1; + } + + if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &keepcaps[i], CAP_SET) < 0) { + fprintf(stderr, "Error: can not set effective capability %d: %s\n", keepcaps[i], strerror(errno)); + cap_free(currCaps); + cap_free(caps); + return -1; + } + } + + if (cap_set_proc(caps) < 0) { + fprintf(stderr, "Error: can not set process capabilities: %s\n", strerror(errno)); + cap_free(currCaps); + cap_free(caps); + return -1; + } + + cap_free(currCaps); + cap_free(caps); + + return 0; +} +#endif + +void Platform_init(void) { +#ifdef HAVE_LIBCAP + if (dropCapabilities(Platform_capabilitiesMode) < 0) + exit(1); +#endif + + if (access(PROCDIR, R_OK) != 0) { + fprintf(stderr, "Error: could not read procfs (compiled to look in %s).\n", PROCDIR); + exit(1); + } + +#ifdef HAVE_SENSORS_SENSORS_H + LibSensors_init(NULL); +#endif +} + +void Platform_done(void) { +#ifdef HAVE_SENSORS_SENSORS_H + LibSensors_cleanup(); +#endif +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/Platform.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,118 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - linux/Platform.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include +#include +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + +/* GNU/Hurd does not have PATH_MAX in limits.h */ +#ifndef PATH_MAX + #define PATH_MAX 4096 +#endif + + +extern const ProcessField Platform_defaultFields[]; + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, unsigned int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +void Platform_setZramValues(Meter* this); + +void Platform_setZfsArcValues(Meter* this); + +void Platform_setZfsCompressedArcValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +#ifdef HAVE_LIBCAP + #define PLATFORM_LONG_OPTIONS \ + {"drop-capabilities", optional_argument, 0, 160}, +#else + #define PLATFORM_LONG_OPTIONS +#endif + +void Platform_longOptionsUsage(const char* name); + +bool Platform_getLongOption(int opt, int argc, char** argv); + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,149 @@ +/* +htop - PressureStallMeter.c +(C) 2004-2011 Hisham H. Muhammad +(C) 2019 Ran Benita +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "linux/PressureStallMeter.h" + +#include +#include + +#include "CRT.h" +#include "Meter.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" +#include "XUtils.h" + + +static const int PressureStallMeter_attributes[] = { + PRESSURE_STALL_TEN, + PRESSURE_STALL_SIXTY, + PRESSURE_STALL_THREEHUNDRED +}; + +static void PressureStallMeter_updateValues(Meter* this) { + const char* file; + if (strstr(Meter_name(this), "CPU")) { + file = "cpu"; + } else if (strstr(Meter_name(this), "IO")) { + file = "io"; + } else { + file = "memory"; + } + + bool some; + if (strstr(Meter_name(this), "Some")) { + some = true; + } else { + some = false; + } + + Platform_getPressureStall(file, some, &this->values[0], &this->values[1], &this->values[2]); + + /* only print bar for ten (not sixty and threehundred), cause the sum is meaningless */ + this->curItems = 1; + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s %s %5.2lf%% %5.2lf%% %5.2lf%%", some ? "some" : "full", file, this->values[0], this->values[1], this->values[2]); +} + +static void PressureStallMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + char buffer[20]; + int len; + + len = xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[0]); + RichString_appendnAscii(out, CRT_colors[PRESSURE_STALL_TEN], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[1]); + RichString_appendnAscii(out, CRT_colors[PRESSURE_STALL_SIXTY], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[2]); + RichString_appendnAscii(out, CRT_colors[PRESSURE_STALL_THREEHUNDRED], buffer, len); +} + +const MeterClass PressureStallCPUSomeMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = PressureStallMeter_display, + }, + .updateValues = PressureStallMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 3, + .total = 100.0, + .attributes = PressureStallMeter_attributes, + .name = "PressureStallCPUSome", + .uiName = "PSI some CPU", + .caption = "PSI some CPU: ", + .description = "Pressure Stall Information, some cpu" +}; + +const MeterClass PressureStallIOSomeMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = PressureStallMeter_display, + }, + .updateValues = PressureStallMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 3, + .total = 100.0, + .attributes = PressureStallMeter_attributes, + .name = "PressureStallIOSome", + .uiName = "PSI some IO", + .caption = "PSI some IO: ", + .description = "Pressure Stall Information, some io" +}; + +const MeterClass PressureStallIOFullMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = PressureStallMeter_display, + }, + .updateValues = PressureStallMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 3, + .total = 100.0, + .attributes = PressureStallMeter_attributes, + .name = "PressureStallIOFull", + .uiName = "PSI full IO", + .caption = "PSI full IO: ", + .description = "Pressure Stall Information, full io" +}; + +const MeterClass PressureStallMemorySomeMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = PressureStallMeter_display, + }, + .updateValues = PressureStallMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 3, + .total = 100.0, + .attributes = PressureStallMeter_attributes, + .name = "PressureStallMemorySome", + .uiName = "PSI some memory", + .caption = "PSI some memory: ", + .description = "Pressure Stall Information, some memory" +}; + +const MeterClass PressureStallMemoryFullMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = PressureStallMeter_display, + }, + .updateValues = PressureStallMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 3, + .total = 100.0, + .attributes = PressureStallMeter_attributes, + .name = "PressureStallMemoryFull", + .uiName = "PSI full memory", + .caption = "PSI full memory: ", + .description = "Pressure Stall Information, full memory" +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/PressureStallMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,26 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_PressureStallMeter +#define HEADER_PressureStallMeter +/* +htop - PressureStallMeter.h +(C) 2004-2011 Hisham H. Muhammad +(C) 2019 Ran Benita +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass PressureStallCPUSomeMeter_class; + +extern const MeterClass PressureStallIOSomeMeter_class; + +extern const MeterClass PressureStallIOFullMeter_class; + +extern const MeterClass PressureStallMemorySomeMeter_class; + +extern const MeterClass PressureStallMemoryFullMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,52 @@ +#ifndef HEADER_LinuxProcessField +#define HEADER_LinuxProcessField +/* +htop - linux/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + CMINFLT = 11, \ + CMAJFLT = 13, \ + UTIME = 14, \ + STIME = 15, \ + CUTIME = 16, \ + CSTIME = 17, \ + M_SHARE = 41, \ + M_TRS = 42, \ + M_DRS = 43, \ + M_LRS = 44, \ + M_DT = 45, \ + CTID = 100, \ + VPID = 101, \ + VXID = 102, \ + RCHAR = 103, \ + WCHAR = 104, \ + SYSCR = 105, \ + SYSCW = 106, \ + RBYTES = 107, \ + WBYTES = 108, \ + CNCLWB = 109, \ + IO_READ_RATE = 110, \ + IO_WRITE_RATE = 111, \ + IO_RATE = 112, \ + CGROUP = 113, \ + OOM = 114, \ + IO_PRIORITY = 115, \ + PERCENT_CPU_DELAY = 116, \ + PERCENT_IO_DELAY = 117, \ + PERCENT_SWAP_DELAY = 118, \ + M_PSS = 119, \ + M_SWAP = 120, \ + M_PSSWP = 121, \ + CTXT = 122, \ + SECATTR = 123, \ + \ + DUMMY_BUMP_FIELD = CWD, \ + // End of list + + +#endif /* HEADER_LinuxProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,93 @@ +/* +htop - SELinuxMeter.c +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "linux/SELinuxMeter.h" + +#include "CRT.h" + +#include +#include +#include +#include +#include +#include + +#include "Object.h" +#include "XUtils.h" + + +static const int SELinuxMeter_attributes[] = { + METER_TEXT, +}; + +static bool enabled = false; +static bool enforcing = false; + +static bool hasSELinuxMount(void) { + struct statfs sfbuf; + int r = statfs("/sys/fs/selinux", &sfbuf); + if (r != 0) { + return false; + } + + if ((uint32_t)sfbuf.f_type != /* SELINUX_MAGIC */ 0xf97cff8cU) { + return false; + } + + struct statvfs vfsbuf; + r = statvfs("/sys/fs/selinux", &vfsbuf); + if (r != 0 || (vfsbuf.f_flag & ST_RDONLY)) { + return false; + } + + return true; +} + +static bool isSelinuxEnabled(void) { + return hasSELinuxMount() && (0 == access("/etc/selinux/config", F_OK)); +} + +static bool isSelinuxEnforcing(void) { + if (!enabled) { + return false; + } + + char buf[20]; + ssize_t r = xReadfile("/sys/fs/selinux/enforce", buf, sizeof(buf)); + if (r < 0) + return false; + + int enforce = 0; + if (sscanf(buf, "%d", &enforce) != 1) { + return false; + } + + return !!enforce; +} + +static void SELinuxMeter_updateValues(Meter* this) { + enabled = isSelinuxEnabled(); + enforcing = isSelinuxEnforcing(); + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%s", enabled ? "enabled" : "disabled", enabled ? (enforcing ? "; mode: enforcing" : "; mode: permissive") : ""); +} + +const MeterClass SELinuxMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + }, + .updateValues = SELinuxMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = SELinuxMeter_attributes, + .name = "SELinux", + .uiName = "SELinux", + .description = "SELinux state overview", + .caption = "SELinux: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SELinuxMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_SELinuxMeter +#define HEADER_SELinuxMeter +/* +htop - SELinuxMeter.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass SELinuxMeter_class; + +#endif /* HEADER_SELinuxMeter */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SystemdMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SystemdMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SystemdMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SystemdMeter.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,381 @@ +/* +htop - SystemdMeter.c +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "linux/SystemdMeter.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "RichString.h" +#include "Settings.h" +#include "XUtils.h" + +#if defined(BUILD_STATIC) && defined(HAVE_LIBSYSTEMD) +#include +#endif + + +#ifdef BUILD_STATIC + +#define sym_sd_bus_open_system sd_bus_open_system +#define sym_sd_bus_get_property_string sd_bus_get_property_string +#define sym_sd_bus_get_property_trivial sd_bus_get_property_trivial +#define sym_sd_bus_unref sd_bus_unref + +#else + +typedef void sd_bus; +typedef void sd_bus_error; +static int (*sym_sd_bus_open_system)(sd_bus**); +static int (*sym_sd_bus_get_property_string)(sd_bus*, const char*, const char*, const char*, const char*, sd_bus_error*, char**); +static int (*sym_sd_bus_get_property_trivial)(sd_bus*, const char*, const char*, const char*, const char*, sd_bus_error*, char, void*); +static sd_bus* (*sym_sd_bus_unref)(sd_bus*); +static void* dlopenHandle = NULL; + +#endif /* BUILD_STATIC */ + +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) +static sd_bus* bus = NULL; +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ + + +#define INVALID_VALUE ((unsigned int)-1) + +static char* systemState = NULL; +static unsigned int nFailedUnits = INVALID_VALUE; +static unsigned int nInstalledJobs = INVALID_VALUE; +static unsigned int nNames = INVALID_VALUE; +static unsigned int nJobs = INVALID_VALUE; + +static void SystemdMeter_done(ATTR_UNUSED Meter* this) { + free(systemState); + systemState = NULL; + +#ifdef BUILD_STATIC +# ifdef HAVE_LIBSYSTEMD + if (bus) { + sym_sd_bus_unref(bus); + } + bus = NULL; +# endif /* HAVE_LIBSYSTEMD */ +#else /* BUILD_STATIC */ + if (bus && dlopenHandle) { + sym_sd_bus_unref(bus); + } + bus = NULL; + + if (dlopenHandle) { + dlclose(dlopenHandle); + dlopenHandle = NULL; + } +#endif /* BUILD_STATIC */ +} + +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) +static int updateViaLib(void) { +#ifndef BUILD_STATIC + if (!dlopenHandle) { + dlopenHandle = dlopen("libsystemd.so.0", RTLD_LAZY); + if (!dlopenHandle) + goto dlfailure; + + /* Clear any errors */ + dlerror(); + + #define resolve(symbolname) do { \ + *(void **)(&sym_##symbolname) = dlsym(dlopenHandle, #symbolname); \ + if (!sym_##symbolname || dlerror() != NULL) \ + goto dlfailure; \ + } while(0) + + resolve(sd_bus_open_system); + resolve(sd_bus_get_property_string); + resolve(sd_bus_get_property_trivial); + resolve(sd_bus_unref); + + #undef resolve + } +#endif /* !BUILD_STATIC */ + + int r; + + /* Connect to the system bus */ + if (!bus) { + r = sym_sd_bus_open_system(&bus); + if (r < 0) + goto busfailure; + } + + static const char* const busServiceName = "org.freedesktop.systemd1"; + static const char* const busObjectPath = "/org/freedesktop/systemd1"; + static const char* const busInterfaceName = "org.freedesktop.systemd1.Manager"; + + r = sym_sd_bus_get_property_string(bus, + busServiceName, /* service to contact */ + busObjectPath, /* object path */ + busInterfaceName, /* interface name */ + "SystemState", /* property name */ + NULL, /* object to return error in */ + &systemState); + if (r < 0) + goto busfailure; + + r = sym_sd_bus_get_property_trivial(bus, + busServiceName, /* service to contact */ + busObjectPath, /* object path */ + busInterfaceName, /* interface name */ + "NFailedUnits", /* property name */ + NULL, /* object to return error in */ + 'u', /* property type */ + &nFailedUnits); + if (r < 0) + goto busfailure; + + r = sym_sd_bus_get_property_trivial(bus, + busServiceName, /* service to contact */ + busObjectPath, /* object path */ + busInterfaceName, /* interface name */ + "NInstalledJobs", /* property name */ + NULL, /* object to return error in */ + 'u', /* property type */ + &nInstalledJobs); + if (r < 0) + goto busfailure; + + r = sym_sd_bus_get_property_trivial(bus, + busServiceName, /* service to contact */ + busObjectPath, /* object path */ + busInterfaceName, /* interface name */ + "NNames", /* property name */ + NULL, /* object to return error in */ + 'u', /* property type */ + &nNames); + if (r < 0) + goto busfailure; + + r = sym_sd_bus_get_property_trivial(bus, + busServiceName, /* service to contact */ + busObjectPath, /* object path */ + busInterfaceName, /* interface name */ + "NJobs", /* property name */ + NULL, /* object to return error in */ + 'u', /* property type */ + &nJobs); + if (r < 0) + goto busfailure; + + /* success */ + return 0; + +busfailure: + sym_sd_bus_unref(bus); + bus = NULL; + return -2; + +#ifndef BUILD_STATIC +dlfailure: + if (dlopenHandle) { + dlclose(dlopenHandle); + dlopenHandle = NULL; + } + return -1; +#endif /* !BUILD_STATIC */ +} +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ + +static void updateViaExec(void) { + if (Settings_isReadonly()) + return; + + int fdpair[2]; + if (pipe(fdpair) < 0) + return; + + pid_t child = fork(); + if (child < 0) { + close(fdpair[1]); + close(fdpair[0]); + return; + } + + if (child == 0) { + close(fdpair[0]); + dup2(fdpair[1], STDOUT_FILENO); + close(fdpair[1]); + int fdnull = open("/dev/null", O_WRONLY); + if (fdnull < 0) + exit(1); + dup2(fdnull, STDERR_FILENO); + close(fdnull); + execlp("systemctl", + "systemctl", + "show", + "--property=SystemState", + "--property=NFailedUnits", + "--property=NNames", + "--property=NJobs", + "--property=NInstalledJobs", + NULL); + exit(127); + } + close(fdpair[1]); + + int wstatus; + if (waitpid(child, &wstatus, 0) < 0 || !WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { + close(fdpair[0]); + return; + } + + FILE* commandOutput = fdopen(fdpair[0], "r"); + if (!commandOutput) { + close(fdpair[0]); + return; + } + + char lineBuffer[128]; + while (fgets(lineBuffer, sizeof(lineBuffer), commandOutput)) { + if (String_startsWith(lineBuffer, "SystemState=")) { + char* newline = strchr(lineBuffer + strlen("SystemState="), '\n'); + if (newline) { + *newline = '\0'; + } + free_and_xStrdup(&systemState, lineBuffer + strlen("SystemState=")); + } else if (String_startsWith(lineBuffer, "NFailedUnits=")) { + nFailedUnits = strtoul(lineBuffer + strlen("NFailedUnits="), NULL, 10); + } else if (String_startsWith(lineBuffer, "NNames=")) { + nNames = strtoul(lineBuffer + strlen("NNames="), NULL, 10); + } else if (String_startsWith(lineBuffer, "NJobs=")) { + nJobs = strtoul(lineBuffer + strlen("NJobs="), NULL, 10); + } else if (String_startsWith(lineBuffer, "NInstalledJobs=")) { + nInstalledJobs = strtoul(lineBuffer + strlen("NInstalledJobs="), NULL, 10); + } + } + + fclose(commandOutput); +} + +static void SystemdMeter_updateValues(Meter* this) { + free(systemState); + systemState = NULL; + nFailedUnits = nInstalledJobs = nNames = nJobs = INVALID_VALUE; + +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) + if (updateViaLib() < 0) + updateViaExec(); +#else + updateViaExec(); +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s", systemState ? systemState : "???"); +} + +static int zeroDigitColor(unsigned int value) { + switch (value) { + case 0: + return CRT_colors[METER_VALUE]; + case INVALID_VALUE: + return CRT_colors[METER_VALUE_ERROR]; + default: + return CRT_colors[METER_VALUE_NOTICE]; + } +} + +static int valueDigitColor(unsigned int value) { + switch (value) { + case 0: + return CRT_colors[METER_VALUE_NOTICE]; + case INVALID_VALUE: + return CRT_colors[METER_VALUE_ERROR]; + default: + return CRT_colors[METER_VALUE]; + } +} + + +static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out) { + char buffer[16]; + int len; + + int color = (systemState && String_eq(systemState, "running")) ? METER_VALUE_OK : METER_VALUE_ERROR; + RichString_writeAscii(out, CRT_colors[color], systemState ? systemState : "N/A"); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " ("); + + if (nFailedUnits == INVALID_VALUE) { + buffer[0] = '?'; + buffer[1] = '\0'; + len = 1; + } else { + len = xSnprintf(buffer, sizeof(buffer), "%u", nFailedUnits); + } + RichString_appendnAscii(out, zeroDigitColor(nFailedUnits), buffer, len); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], "/"); + + if (nNames == INVALID_VALUE) { + buffer[0] = '?'; + buffer[1] = '\0'; + len = 1; + } else { + len = xSnprintf(buffer, sizeof(buffer), "%u", nNames); + } + RichString_appendnAscii(out, valueDigitColor(nNames), buffer, len); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " failed) ("); + + if (nJobs == INVALID_VALUE) { + buffer[0] = '?'; + buffer[1] = '\0'; + len = 1; + } else { + len = xSnprintf(buffer, sizeof(buffer), "%u", nJobs); + } + RichString_appendnAscii(out, zeroDigitColor(nJobs), buffer, len); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], "/"); + + if (nInstalledJobs == INVALID_VALUE) { + buffer[0] = '?'; + buffer[1] = '\0'; + len = 1; + } else { + len = xSnprintf(buffer, sizeof(buffer), "%u", nInstalledJobs); + } + RichString_appendnAscii(out, valueDigitColor(nInstalledJobs), buffer, len); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " jobs)"); +} + +static const int SystemdMeter_attributes[] = { + METER_VALUE +}; + +const MeterClass SystemdMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = SystemdMeter_display + }, + .updateValues = SystemdMeter_updateValues, + .done = SystemdMeter_done, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = SystemdMeter_attributes, + .name = "Systemd", + .uiName = "Systemd state", + .description = "Systemd system state and unit overview", + .caption = "Systemd: ", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SystemdMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SystemdMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/SystemdMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/SystemdMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,16 @@ +#ifndef HEADER_SystemdMeter +#define HEADER_SystemdMeter + +/* +htop - SystemdMeter.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass SystemdMeter_class; + +#endif /* HEADER_SystemdMeter */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ZramMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ZramMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ZramMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ZramMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,73 @@ +#include "linux/ZramMeter.h" + +#include + +#include "CRT.h" +#include "Meter.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" + + +static const int ZramMeter_attributes[] = { + ZRAM +}; + +static void ZramMeter_updateValues(Meter* this) { + char* buffer = this->txtBuffer; + size_t size = sizeof(this->txtBuffer); + int written; + + Platform_setZramValues(this); + + /* on print bar for compressed data size, not uncompressed */ + this->curItems = 1; + + written = Meter_humanUnit(buffer, this->values[0], size); + METER_BUFFER_CHECK(buffer, size, written); + + METER_BUFFER_APPEND_CHR(buffer, size, '('); + + written = Meter_humanUnit(buffer, this->values[1], size); + METER_BUFFER_CHECK(buffer, size, written); + + METER_BUFFER_APPEND_CHR(buffer, size, ')'); + + METER_BUFFER_APPEND_CHR(buffer, size, '/'); + + Meter_humanUnit(buffer, this->total, size); +} + +static void ZramMeter_display(const Object* cast, RichString* out) { + char buffer[50]; + const Meter* this = (const Meter*)cast; + + RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); + + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + + Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + + Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " uncompressed:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); +} + +const MeterClass ZramMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = ZramMeter_display, + }, + .updateValues = ZramMeter_updateValues, + .defaultMode = BAR_METERMODE, + .maxItems = 2, + .total = 100.0, + .attributes = ZramMeter_attributes, + .name = "Zram", + .uiName = "Zram", + .caption = "zrm" +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ZramMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ZramMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ZramMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ZramMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,9 @@ +#ifndef HEADER_ZramMeter +#define HEADER_ZramMeter + +#include "Meter.h" + + +extern const MeterClass ZramMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ZramStats.h pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ZramStats.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/linux/ZramStats.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/linux/ZramStats.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,10 @@ +#ifndef HEADER_ZramStats +#define HEADER_ZramStats + +typedef struct ZramStats_ { + memory_t totalZram; + memory_t usedZramComp; + memory_t usedZramOrig; +} ZramStats; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ListItem.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ListItem.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ListItem.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ListItem.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,68 @@ +/* +htop - ListItem.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "ListItem.h" + +#include +#include +#include + +#include "CRT.h" +#include "RichString.h" +#include "XUtils.h" + + +static void ListItem_delete(Object* cast) { + ListItem* this = (ListItem*)cast; + free(this->value); + free(this); +} + +static void ListItem_display(const Object* cast, RichString* out) { + const ListItem* const this = (const ListItem*)cast; + assert (this != NULL); + + if (this->moving) { + RichString_writeWide(out, CRT_colors[DEFAULT_COLOR], +#ifdef HAVE_LIBNCURSESW + CRT_utf8 ? "↕ " : +#endif + "+ "); + } + RichString_appendWide(out, CRT_colors[DEFAULT_COLOR], this->value); +} + +ListItem* ListItem_new(const char* value, int key) { + ListItem* this = AllocThis(ListItem); + this->value = xStrdup(value); + this->key = key; + this->moving = false; + return this; +} + +void ListItem_append(ListItem* this, const char* text) { + size_t oldLen = strlen(this->value); + size_t textLen = strlen(text); + size_t newLen = oldLen + textLen; + this->value = xRealloc(this->value, newLen + 1); + memcpy(this->value + oldLen, text, textLen); + this->value[newLen] = '\0'; +} + +static int ListItem_compare(const void* cast1, const void* cast2) { + const ListItem* obj1 = (const ListItem*) cast1; + const ListItem* obj2 = (const ListItem*) cast2; + return strcmp(obj1->value, obj2->value); +} + +const ObjectClass ListItem_class = { + .display = ListItem_display, + .delete = ListItem_delete, + .compare = ListItem_compare +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ListItem.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ListItem.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ListItem.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ListItem.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef HEADER_ListItem +#define HEADER_ListItem +/* +htop - ListItem.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Object.h" + + +typedef struct ListItem_ { + Object super; + char* value; + int key; + bool moving; +} ListItem; + +extern const ObjectClass ListItem_class; + +ListItem* ListItem_new(const char* value, int key); + +void ListItem_append(ListItem* this, const char* text); + +static inline const char* ListItem_getRef(const ListItem* this) { + return this->value; +} + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/LoadAverageMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/LoadAverageMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/LoadAverageMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/LoadAverageMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,134 @@ +/* +htop - LoadAverageMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "LoadAverageMeter.h" + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "XUtils.h" + + +static const int LoadAverageMeter_attributes[] = { + LOAD_AVERAGE_ONE, + LOAD_AVERAGE_FIVE, + LOAD_AVERAGE_FIFTEEN +}; + +static const int LoadMeter_attributes[] = { + LOAD +}; + +static const int OK_attributes[] = { + METER_VALUE_OK +}; + +static const int Medium_attributes[] = { + METER_VALUE_WARN +}; + +static const int High_attributes[] = { + METER_VALUE_ERROR +}; + +static void LoadAverageMeter_updateValues(Meter* this) { + Platform_getLoadAverage(&this->values[0], &this->values[1], &this->values[2]); + + // only show bar for 1min value + this->curItems = 1; + + // change bar color and total based on value + if (this->values[0] < 1.0) { + this->curAttributes = OK_attributes; + this->total = 1.0; + } else if (this->values[0] < this->pl->cpuCount) { + this->curAttributes = Medium_attributes; + this->total = this->pl->cpuCount; + } else { + this->curAttributes = High_attributes; + this->total = 2 * this->pl->cpuCount; + } + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.2f/%.2f/%.2f", this->values[0], this->values[1], this->values[2]); +} + +static void LoadAverageMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + char buffer[20]; + int len; + + len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[0]); + RichString_appendnAscii(out, CRT_colors[LOAD_AVERAGE_ONE], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[1]); + RichString_appendnAscii(out, CRT_colors[LOAD_AVERAGE_FIVE], buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[2]); + RichString_appendnAscii(out, CRT_colors[LOAD_AVERAGE_FIFTEEN], buffer, len); +} + +static void LoadMeter_updateValues(Meter* this) { + double five, fifteen; + Platform_getLoadAverage(&this->values[0], &five, &fifteen); + + // change bar color and total based on value + if (this->values[0] < 1.0) { + this->curAttributes = OK_attributes; + this->total = 1.0; + } else if (this->values[0] < this->pl->cpuCount) { + this->curAttributes = Medium_attributes; + this->total = this->pl->cpuCount; + } else { + this->curAttributes = High_attributes; + this->total = 2 * this->pl->cpuCount; + } + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.2f", this->values[0]); +} + +static void LoadMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + char buffer[20]; + int len; + + len = xSnprintf(buffer, sizeof(buffer), "%.2f ", this->values[0]); + RichString_appendnAscii(out, CRT_colors[LOAD], buffer, len); +} + +const MeterClass LoadAverageMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = LoadAverageMeter_display, + }, + .updateValues = LoadAverageMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 3, + .total = 100.0, + .attributes = LoadAverageMeter_attributes, + .name = "LoadAverage", + .uiName = "Load average", + .description = "Load averages: 1 minute, 5 minutes, 15 minutes", + .caption = "Load average: " +}; + +const MeterClass LoadMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = LoadMeter_display, + }, + .updateValues = LoadMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 100.0, + .attributes = LoadMeter_attributes, + .name = "Load", + .uiName = "Load", + .description = "Load: average of ready processes in the last minute", + .caption = "Load: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/LoadAverageMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/LoadAverageMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/LoadAverageMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/LoadAverageMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,17 @@ +#ifndef HEADER_LoadAverageMeter +#define HEADER_LoadAverageMeter +/* +htop - LoadAverageMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass LoadAverageMeter_class; + +extern const MeterClass LoadMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Macros.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Macros.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Macros.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Macros.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,85 @@ +#ifndef HEADER_Macros +#define HEADER_Macros + +#include // IWYU pragma: keep + +#ifndef MINIMUM +#define MINIMUM(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAXIMUM +#define MAXIMUM(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef CLAMP +#define CLAMP(x, low, high) (assert((low) <= (high)), ((x) > (high)) ? (high) : MAXIMUM(x, low)) +#endif + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#ifndef SPACESHIP_NUMBER +#define SPACESHIP_NUMBER(a, b) (((a) > (b)) - ((a) < (b))) +#endif + +#ifndef SPACESHIP_NULLSTR +#define SPACESHIP_NULLSTR(a, b) strcmp((a) ? (a) : "", (b) ? (b) : "") +#endif + +#ifndef SPACESHIP_DEFAULTSTR +#define SPACESHIP_DEFAULTSTR(a, b, s) strcmp((a) ? (a) : (s), (b) ? (b) : (s)) +#endif + +#ifdef __GNUC__ // defined by GCC and Clang + +#define ATTR_FORMAT(type, index, check) __attribute__((format (type, index, check))) +#define ATTR_NONNULL __attribute__((nonnull)) +#define ATTR_NORETURN __attribute__((noreturn)) +#define ATTR_UNUSED __attribute__((unused)) +#define ATTR_MALLOC __attribute__((malloc)) + +#else /* __GNUC__ */ + +#define ATTR_FORMAT(type, index, check) +#define ATTR_NONNULL +#define ATTR_NORETURN +#define ATTR_UNUSED +#define ATTR_MALLOC + +#endif /* __GNUC__ */ + +#ifdef HAVE_ATTR_ALLOC_SIZE + +#define ATTR_ALLOC_SIZE1(a) __attribute__((alloc_size (a))) +#define ATTR_ALLOC_SIZE2(a, b) __attribute__((alloc_size (a, b))) + +#else + +#define ATTR_ALLOC_SIZE1(a) +#define ATTR_ALLOC_SIZE2(a, b) + +#endif /* HAVE_ATTR_ALLOC_SIZE */ + +// ignore casts discarding const specifier, e.g. +// const char [] -> char * / void * +// const char *[2]' -> char *const * +#if defined(__clang__) +#define IGNORE_WCASTQUAL_BEGIN _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#define IGNORE_WCASTQUAL_END _Pragma("clang diagnostic pop") +#elif defined(__GNUC__) +#define IGNORE_WCASTQUAL_BEGIN _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#define IGNORE_WCASTQUAL_END _Pragma("GCC diagnostic pop") +#else +#define IGNORE_WCASTQUAL_BEGIN +#define IGNORE_WCASTQUAL_END +#endif + +/* This subtraction is used by Linux / NetBSD / OpenBSD for calculation of CPU usage items. */ +static inline unsigned long long saturatingSub(unsigned long long a, unsigned long long b) { + return a > b ? a - b : 0; +} + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/MainPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/MainPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/MainPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/MainPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,220 @@ +/* +htop - ColumnsPanel.c +(C) 2004-2015 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "MainPanel.h" + +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Platform.h" +#include "Process.h" +#include "ProcessList.h" +#include "ProvideCurses.h" +#include "Settings.h" +#include "XUtils.h" + + +static const char* const MainFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL}; +static const char* const MainFunctions_ro[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", " ", " ", " ", "Quit ", NULL}; + +void MainPanel_updateTreeFunctions(MainPanel* this, bool mode) { + FunctionBar* bar = MainPanel_getFunctionBar(this); + FunctionBar_setLabel(bar, KEY_F(5), mode ? "List " : "Tree "); +} + +static void MainPanel_pidSearch(MainPanel* this, int ch) { + Panel* super = (Panel*) this; + pid_t pid = ch - 48 + this->pidSearch; + for (int i = 0; i < Panel_size(super); i++) { + const Process* p = (const Process*) Panel_get(super, i); + if (p && p->pid == pid) { + Panel_setSelected(super, i); + break; + } + } + this->pidSearch = pid * 10; + if (this->pidSearch > 10000000) { + this->pidSearch = 0; + } +} + +static const char* MainPanel_getValue(Panel* this, int i) { + const Process* p = (const Process*) Panel_get(this, i); + return Process_getCommand(p); +} + +static HandlerResult MainPanel_eventHandler(Panel* super, int ch) { + MainPanel* this = (MainPanel*) super; + + HandlerResult result = IGNORED; + + Htop_Reaction reaction = HTOP_OK; + + /* Let supervising ScreenManager handle resize */ + if (ch == KEY_RESIZE) + return IGNORED; + + /* reset on every normal key */ + if (ch != ERR) + this->state->hideProcessSelection = false; + + if (EVENT_IS_HEADER_CLICK(ch)) { + int x = EVENT_HEADER_CLICK_GET_X(ch); + const ProcessList* pl = this->state->pl; + Settings* settings = this->state->settings; + int hx = super->scrollH + x + 1; + ProcessField field = ProcessList_keyAt(pl, hx); + if (settings->treeView && settings->treeViewAlwaysByPID) { + settings->treeView = false; + settings->direction = 1; + reaction |= Action_setSortKey(settings, field); + } else if (field == Settings_getActiveSortKey(settings)) { + Settings_invertSortOrder(settings); + } else { + reaction |= Action_setSortKey(settings, field); + } + reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS; + result = HANDLED; + } else if (ch != ERR && this->inc->active) { + bool filterChanged = IncSet_handleKey(this->inc, ch, super, MainPanel_getValue, NULL); + if (filterChanged) { + this->state->pl->incFilter = IncSet_filter(this->inc); + reaction = HTOP_REFRESH | HTOP_REDRAW_BAR; + } + if (this->inc->found) { + reaction |= Action_follow(this->state); + reaction |= HTOP_KEEP_FOLLOWING; + } + result = HANDLED; + } else if (ch == 27) { + this->state->hideProcessSelection = true; + return HANDLED; + } else if (ch != ERR && ch > 0 && ch < KEY_MAX && this->keys[ch]) { + reaction |= (this->keys[ch])(this->state); + result = HANDLED; + } else if (0 < ch && ch < 255 && isdigit((unsigned char)ch)) { + MainPanel_pidSearch(this, ch); + } else { + if (ch != ERR) { + this->pidSearch = 0; + } else { + reaction |= HTOP_KEEP_FOLLOWING; + } + } + + if (reaction & HTOP_REDRAW_BAR) { + MainPanel_updateTreeFunctions(this, this->state->settings->treeView); + } + if (reaction & HTOP_UPDATE_PANELHDR) { + result |= REDRAW; + } + if (reaction & HTOP_REFRESH) { + result |= REFRESH; + } + if (reaction & HTOP_RECALCULATE) { + result |= RESCAN; + } + if (reaction & HTOP_SAVE_SETTINGS) { + this->state->settings->changed = true; + } + if (reaction & HTOP_QUIT) { + return BREAK_LOOP; + } + if (!(reaction & HTOP_KEEP_FOLLOWING)) { + this->state->pl->following = -1; + Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS); + } + return result; +} + +int MainPanel_selectedPid(MainPanel* this) { + const Process* p = (const Process*) Panel_getSelected((Panel*)this); + if (p) { + return p->pid; + } + return -1; +} + +bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged) { + Panel* super = (Panel*) this; + bool ok = true; + bool anyTagged = false; + for (int i = 0; i < Panel_size(super); i++) { + Process* p = (Process*) Panel_get(super, i); + if (p->tag) { + ok = fn(p, arg) && ok; + anyTagged = true; + } + } + if (!anyTagged) { + Process* p = (Process*) Panel_getSelected(super); + if (p) { + ok &= fn(p, arg); + } + } + + if (wasAnyTagged) + *wasAnyTagged = anyTagged; + + return ok; +} + +static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) { + MainPanel* this = (MainPanel*) super; + + // Do not hide active search and filter bar. + if (hideFunctionBar && !this->inc->active) + return; + + IncSet_drawBar(this->inc); + if (this->state->pauseProcessUpdate) { + FunctionBar_append("PAUSED", CRT_colors[PAUSED]); + } +} + +static void MainPanel_printHeader(Panel* super) { + MainPanel* this = (MainPanel*) super; + ProcessList_printHeader(this->state->pl, &super->header); +} + +const PanelClass MainPanel_class = { + .super = { + .extends = Class(Panel), + .delete = MainPanel_delete + }, + .eventHandler = MainPanel_eventHandler, + .drawFunctionBar = MainPanel_drawFunctionBar, + .printHeader = MainPanel_printHeader +}; + +MainPanel* MainPanel_new() { + MainPanel* this = AllocThis(MainPanel); + Panel_init((Panel*) this, 1, 1, 1, 1, Class(Process), false, FunctionBar_new(Settings_isReadonly() ? MainFunctions_ro : MainFunctions, NULL, NULL)); + this->keys = xCalloc(KEY_MAX, sizeof(Htop_Action)); + this->inc = IncSet_new(MainPanel_getFunctionBar(this)); + + Action_setBindings(this->keys); + Platform_setBindings(this->keys); + + return this; +} + +void MainPanel_setState(MainPanel* this, State* state) { + this->state = state; +} + +void MainPanel_delete(Object* object) { + Panel* super = (Panel*) object; + MainPanel* this = (MainPanel*) object; + Panel_done(super); + IncSet_delete(this->inc); + free(this->keys); + free(this); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/MainPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/MainPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/MainPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/MainPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,49 @@ +#ifndef HEADER_MainPanel +#define HEADER_MainPanel +/* +htop - ColumnsPanel.h +(C) 2004-2015 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +#include "Action.h" +#include "IncSet.h" +#include "Object.h" +#include "Panel.h" +#include "Process.h" + + +typedef struct MainPanel_ { + Panel super; + State* state; + IncSet* inc; + Htop_Action* keys; + pid_t pidSearch; +} MainPanel; + +typedef bool(*MainPanel_ForeachProcessFn)(Process*, Arg); + +#define MainPanel_getFunctionBar(this_) (((Panel*)(this_))->defaultBar) + +void MainPanel_updateTreeFunctions(MainPanel* this, bool mode); + +int MainPanel_selectedPid(MainPanel* this); + +bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged); + +extern const PanelClass MainPanel_class; + +MainPanel* MainPanel_new(void); + +void MainPanel_setState(MainPanel* this, State* state); + +void MainPanel_delete(Object* object); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Makefile.am pcp-5.3.2/vendor/github.com/htop-dev/htop/Makefile.am --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Makefile.am 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,446 @@ +dist_man_MANS = htop.1 +EXTRA_DIST = \ + $(dist_man_MANS) \ + autogen.sh \ + htop.desktop \ + htop.png \ + htop.svg \ + build-aux/compile \ + build-aux/depcomp \ + build-aux/install-sh \ + build-aux/missing +applicationsdir = $(datadir)/applications +applications_DATA = htop.desktop +pixmapdir = $(datadir)/pixmaps +pixmap_DATA = htop.png +appicondir = $(datadir)/icons/hicolor/scalable/apps +appicon_DATA = htop.svg + +AM_CFLAGS += -pedantic -std=c99 -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR="\"$(sysconfdir)\"" -I"$(top_srcdir)/$(my_htop_platform)" +AM_LDFLAGS = + +myhtopsources = \ + Action.c \ + Affinity.c \ + AffinityPanel.c \ + AvailableColumnsPanel.c \ + AvailableMetersPanel.c \ + BatteryMeter.c \ + CategoriesPanel.c \ + ClockMeter.c \ + ColorsPanel.c \ + ColumnsPanel.c \ + CommandLine.c \ + CommandScreen.c \ + Compat.c \ + CPUMeter.c \ + CRT.c \ + DateMeter.c \ + DateTimeMeter.c \ + DiskIOMeter.c \ + DisplayOptionsPanel.c \ + DynamicMeter.c \ + EnvScreen.c \ + FunctionBar.c \ + Hashtable.c \ + Header.c \ + HostnameMeter.c \ + IncSet.c \ + InfoScreen.c \ + ListItem.c \ + LoadAverageMeter.c \ + MainPanel.c \ + MemoryMeter.c \ + Meter.c \ + MetersPanel.c \ + NetworkIOMeter.c \ + Object.c \ + OpenFilesScreen.c \ + OptionItem.c \ + Panel.c \ + Process.c \ + ProcessList.c \ + ProcessLocksScreen.c \ + RichString.c \ + ScreenManager.c \ + Settings.c \ + SignalsPanel.c \ + SwapMeter.c \ + SysArchMeter.c \ + TasksMeter.c \ + TraceScreen.c \ + UptimeMeter.c \ + UsersTable.c \ + Vector.c \ + XUtils.c + +myhtopheaders = \ + Action.h \ + Affinity.h \ + AffinityPanel.h \ + AvailableColumnsPanel.h \ + AvailableMetersPanel.h \ + BatteryMeter.h \ + CPUMeter.h \ + CRT.h \ + CategoriesPanel.h \ + ClockMeter.h \ + ColorsPanel.h \ + ColumnsPanel.h \ + CommandLine.h \ + CommandScreen.h \ + Compat.h \ + DateMeter.h \ + DateTimeMeter.h \ + DiskIOMeter.h \ + DisplayOptionsPanel.h \ + DynamicMeter.h \ + EnvScreen.h \ + FunctionBar.h \ + Hashtable.h \ + Header.h \ + HostnameMeter.h \ + IncSet.h \ + InfoScreen.h \ + ListItem.h \ + LoadAverageMeter.h \ + Macros.h \ + MainPanel.h \ + MemoryMeter.h \ + Meter.h \ + MetersPanel.h \ + NetworkIOMeter.h \ + Object.h \ + OpenFilesScreen.h \ + OptionItem.h \ + Panel.h \ + Process.h \ + ProcessList.h \ + ProcessLocksScreen.h \ + ProvideCurses.h \ + RichString.h \ + ScreenManager.h \ + Settings.h \ + SignalsPanel.h \ + SwapMeter.h \ + SysArchMeter.h \ + TasksMeter.h \ + TraceScreen.h \ + UptimeMeter.h \ + UsersTable.h \ + Vector.h \ + XUtils.h + +# Linux +# ----- + +linux_platform_headers = \ + generic/gettime.h \ + generic/hostname.h \ + generic/uname.h \ + linux/HugePageMeter.h \ + linux/IOPriority.h \ + linux/IOPriorityPanel.h \ + linux/LibSensors.h \ + linux/LinuxProcess.h \ + linux/LinuxProcessList.h \ + linux/Platform.h \ + linux/PressureStallMeter.h \ + linux/ProcessField.h \ + linux/SELinuxMeter.h \ + linux/SystemdMeter.h \ + linux/ZramMeter.h \ + linux/ZramStats.h \ + zfs/ZfsArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/ZfsCompressedArcMeter.h + +linux_platform_sources = \ + generic/gettime.c \ + generic/hostname.c \ + generic/uname.c \ + linux/HugePageMeter.c \ + linux/IOPriorityPanel.c \ + linux/LibSensors.c \ + linux/LinuxProcess.c \ + linux/LinuxProcessList.c \ + linux/Platform.c \ + linux/PressureStallMeter.c \ + linux/SELinuxMeter.c \ + linux/SystemdMeter.c \ + linux/ZramMeter.c \ + zfs/ZfsArcMeter.c \ + zfs/ZfsCompressedArcMeter.c + +if HTOP_LINUX +AM_LDFLAGS += -rdynamic +myhtopplatprogram = htop +myhtopplatheaders = $(linux_platform_headers) +myhtopplatsources = $(linux_platform_sources) +endif + +# FreeBSD +# ------- + +freebsd_platform_headers = \ + freebsd/FreeBSDProcessList.h \ + freebsd/FreeBSDProcess.h \ + freebsd/Platform.h \ + freebsd/ProcessField.h \ + generic/gettime.h \ + generic/hostname.h \ + generic/openzfs_sysctl.h \ + generic/uname.h \ + zfs/ZfsArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/ZfsCompressedArcMeter.h + +freebsd_platform_sources = \ + freebsd/Platform.c \ + freebsd/FreeBSDProcessList.c \ + freebsd/FreeBSDProcess.c \ + generic/gettime.c \ + generic/hostname.c \ + generic/openzfs_sysctl.c \ + generic/uname.c \ + zfs/ZfsArcMeter.c \ + zfs/ZfsCompressedArcMeter.c + +if HTOP_FREEBSD +myhtopplatprogram = htop +myhtopplatheaders = $(freebsd_platform_headers) +myhtopplatsources = $(freebsd_platform_sources) +endif + +# DragonFlyBSD +# ------------ + +dragonflybsd_platform_headers = \ + dragonflybsd/DragonFlyBSDProcessList.h \ + dragonflybsd/DragonFlyBSDProcess.h \ + dragonflybsd/Platform.h \ + dragonflybsd/ProcessField.h \ + generic/gettime.h \ + generic/hostname.h \ + generic/uname.h + +dragonflybsd_platform_sources = \ + dragonflybsd/DragonFlyBSDProcessList.c \ + dragonflybsd/DragonFlyBSDProcess.c \ + dragonflybsd/Platform.c \ + generic/gettime.c \ + generic/hostname.c \ + generic/uname.c + +if HTOP_DRAGONFLYBSD +myhtopplatprogram = htop +myhtopplatheaders = $(dragonflybsd_platform_headers) +myhtopplatsources = $(dragonflybsd_platform_sources) +endif + +# NetBSD +# ------- + +netbsd_platform_headers = \ + generic/gettime.h \ + generic/hostname.h \ + generic/uname.h \ + netbsd/Platform.h \ + netbsd/ProcessField.h \ + netbsd/NetBSDProcess.h \ + netbsd/NetBSDProcessList.h + +netbsd_platform_sources = \ + generic/gettime.c \ + generic/hostname.c \ + generic/uname.c \ + netbsd/Platform.c \ + netbsd/NetBSDProcess.c \ + netbsd/NetBSDProcessList.c + +if HTOP_NETBSD +myhtopplatprogram = htop +myhtopplatheaders = $(netbsd_platform_headers) +myhtopplatsources = $(netbsd_platform_sources) +endif + +# OpenBSD +# ------- + +openbsd_platform_headers = \ + generic/gettime.h \ + generic/hostname.h \ + generic/uname.h \ + openbsd/OpenBSDProcessList.h \ + openbsd/OpenBSDProcess.h \ + openbsd/Platform.h \ + openbsd/ProcessField.h + +openbsd_platform_sources = \ + generic/gettime.c \ + generic/hostname.c \ + generic/uname.c \ + openbsd/OpenBSDProcessList.c \ + openbsd/OpenBSDProcess.c \ + openbsd/Platform.c + +if HTOP_OPENBSD +myhtopplatprogram = htop +myhtopplatheaders = $(openbsd_platform_headers) +myhtopplatsources = $(openbsd_platform_sources) +endif + +# Darwin +# ------ + +darwin_platform_headers = \ + darwin/DarwinProcess.h \ + darwin/DarwinProcessList.h \ + darwin/Platform.h \ + darwin/ProcessField.h \ + generic/gettime.h \ + generic/hostname.h \ + generic/openzfs_sysctl.h \ + generic/uname.h \ + zfs/ZfsArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/ZfsCompressedArcMeter.h + +darwin_platform_sources = \ + darwin/Platform.c \ + darwin/DarwinProcess.c \ + darwin/DarwinProcessList.c \ + generic/gettime.c \ + generic/hostname.c \ + generic/openzfs_sysctl.c \ + generic/uname.c \ + zfs/ZfsArcMeter.c \ + zfs/ZfsCompressedArcMeter.c + +if HTOP_DARWIN +AM_LDFLAGS += -framework IOKit -framework CoreFoundation +myhtopplatprogram = htop +myhtopplatheaders = $(darwin_platform_headers) +myhtopplatsources = $(darwin_platform_sources) +endif + +# Solaris +# ------- + +solaris_platform_headers = \ + generic/gettime.h \ + generic/hostname.h \ + generic/uname.h \ + solaris/ProcessField.h \ + solaris/Platform.h \ + solaris/SolarisProcess.h \ + solaris/SolarisProcessList.h \ + zfs/ZfsArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/ZfsCompressedArcMeter.h + +solaris_platform_sources = \ + generic/gettime.c \ + generic/hostname.c \ + generic/uname.c \ + solaris/Platform.c \ + solaris/SolarisProcess.c \ + solaris/SolarisProcessList.c \ + zfs/ZfsArcMeter.c \ + zfs/ZfsCompressedArcMeter.c + +if HTOP_SOLARIS +myhtopplatprogram = htop +myhtopplatheaders = $(solaris_platform_headers) +myhtopplatsources = $(solaris_platform_sources) +endif + +# Performance Co-Pilot (PCP) +# -------------------------- + +pcp_platform_headers = \ + pcp/PCPDynamicMeter.h \ + pcp/PCPProcess.h \ + pcp/PCPProcessList.h \ + pcp/Platform.h \ + pcp/ProcessField.h \ + linux/PressureStallMeter.h \ + linux/ZramMeter.h \ + linux/ZramStats.h \ + zfs/ZfsArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/ZfsCompressedArcMeter.h + +pcp_platform_sources = \ + pcp/PCPDynamicMeter.c \ + pcp/PCPProcess.c \ + pcp/PCPProcessList.c \ + pcp/Platform.c \ + linux/PressureStallMeter.c \ + linux/ZramMeter.c \ + zfs/ZfsArcMeter.c \ + zfs/ZfsCompressedArcMeter.c + +if HTOP_PCP +myhtopplatprogram = pcp-htop +myhtopplatheaders = $(pcp_platform_headers) +myhtopplatsources = $(pcp_platform_sources) +pcp_htop_SOURCES = $(myhtopplatprogram).c $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources) +endif + +# Unsupported +# ----------- + +unsupported_platform_headers = \ + generic/gettime.h \ + unsupported/Platform.h \ + unsupported/ProcessField.h \ + unsupported/UnsupportedProcess.h \ + unsupported/UnsupportedProcessList.h + +unsupported_platform_sources = \ + generic/gettime.c \ + unsupported/Platform.c \ + unsupported/UnsupportedProcess.c \ + unsupported/UnsupportedProcessList.c + +if HTOP_UNSUPPORTED +myhtopplatprogram = htop +myhtopplatsources = $(unsupported_platform_sources) +myhtopplatheaders = $(unsupported_platform_headers) +endif + +# ---- + +bin_PROGRAMS = $(myhtopplatprogram) +htop_SOURCES = $(myhtopplatprogram).c $(myhtopheaders) $(myhtopplatheaders) $(myhtopsources) $(myhtopplatsources) +nodist_htop_SOURCES = config.h + +target: + echo $(htop_SOURCES) + +profile: + $(MAKE) all AM_CPPFLAGS="-pg -O2 -DNDEBUG" + +debug: + $(MAKE) all AM_CPPFLAGS="-ggdb3 -Og" CFLAGS="$(patsubst -O%,,$(CFLAGS))" + +coverage: + $(MAKE) all AM_CPPFLAGS="-fprofile-arcs -ftest-coverage" AM_LDFLAGS="-lgcov" + +cppcheck: + cppcheck -q -v . --enable=all -DHAVE_OPENVZ + +dist-hook: $(top_distdir)/configure + @if grep 'pkg_m4_absent' '$(top_distdir)/configure'; then \ + echo 'configure is generated without pkg.m4. Please supply pkg.m4 and run ./autogen.sh to rebuild the configure script.'>&2; \ + (exit 1); \ + else :; \ + fi + +.PHONY: lcov + +lcov: + mkdir -p lcov + lcov --capture --directory . --output-file coverage.info + genhtml coverage.info --output-directory lcov diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/MemoryMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/MemoryMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/MemoryMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/MemoryMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,96 @@ +/* +htop - MemoryMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "MemoryMeter.h" + +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" + + +static const int MemoryMeter_attributes[] = { + MEMORY_USED, + MEMORY_BUFFERS, + MEMORY_SHARED, + MEMORY_CACHE +}; + +static void MemoryMeter_updateValues(Meter* this) { + char* buffer = this->txtBuffer; + size_t size = sizeof(this->txtBuffer); + int written; + + /* shared and available memory are not supported on all platforms */ + this->values[2] = NAN; + this->values[4] = NAN; + Platform_setMemoryValues(this); + + /* Do not print available memory in bar mode */ + this->curItems = 4; + + written = Meter_humanUnit(buffer, isnan(this->values[4]) ? this->values[0] : this->total - this->values[4], size); + METER_BUFFER_CHECK(buffer, size, written); + + METER_BUFFER_APPEND_CHR(buffer, size, '/'); + + Meter_humanUnit(buffer, this->total, size); +} + +static void MemoryMeter_display(const Object* cast, RichString* out) { + char buffer[50]; + const Meter* this = (const Meter*)cast; + + RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + + Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); + RichString_appendAscii(out, CRT_colors[MEMORY_USED], buffer); + + Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " buffers:"); + RichString_appendAscii(out, CRT_colors[MEMORY_BUFFERS_TEXT], buffer); + + /* shared memory is not supported on all platforms */ + if (!isnan(this->values[2])) { + Meter_humanUnit(buffer, this->values[2], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " shared:"); + RichString_appendAscii(out, CRT_colors[MEMORY_SHARED], buffer); + } + + Meter_humanUnit(buffer, this->values[3], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:"); + RichString_appendAscii(out, CRT_colors[MEMORY_CACHE], buffer); + + /* available memory is not supported on all platforms */ + if (!isnan(this->values[4])) { + Meter_humanUnit(buffer, this->values[4], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " available:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + } +} + +const MeterClass MemoryMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = MemoryMeter_display, + }, + .updateValues = MemoryMeter_updateValues, + .defaultMode = BAR_METERMODE, + .maxItems = 5, + .total = 100.0, + .attributes = MemoryMeter_attributes, + .name = "Memory", + .uiName = "Memory", + .caption = "Mem" +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/MemoryMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/MemoryMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/MemoryMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/MemoryMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_MemoryMeter +#define HEADER_MemoryMeter +/* +htop - MemoryMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass MemoryMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Meter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Meter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Meter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Meter.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,482 @@ +/* +htop - Meter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "Meter.h" + +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "ProvideCurses.h" +#include "RichString.h" +#include "Settings.h" +#include "XUtils.h" + + +#define GRAPH_HEIGHT 4 /* Unit: rows (lines) */ + +const MeterClass Meter_class = { + .super = { + .extends = Class(Object) + } +}; + +Meter* Meter_new(const struct ProcessList_* pl, unsigned int param, const MeterClass* type) { + Meter* this = xCalloc(1, sizeof(Meter)); + Object_setClass(this, type); + this->h = 1; + this->param = param; + this->pl = pl; + this->curItems = type->maxItems; + this->curAttributes = NULL; + this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL; + this->total = type->total; + this->caption = xStrdup(type->caption); + if (Meter_initFn(this)) { + Meter_init(this); + } + Meter_setMode(this, type->defaultMode); + return this; +} + +int Meter_humanUnit(char* buffer, unsigned long int value, size_t size) { + const char* prefix = "KMGTPEZY"; + unsigned long int powi = 1; + unsigned int powj = 1, precision = 2; + + for (;;) { + if (value / 1024 < powi) + break; + + if (prefix[1] == '\0') + break; + + powi *= 1024; + ++prefix; + } + + if (*prefix == 'K') + precision = 0; + + for (; precision > 0; precision--) { + powj *= 10; + if (value / powi < powj) + break; + } + + return snprintf(buffer, size, "%.*f%c", precision, (double) value / powi, *prefix); +} + +void Meter_delete(Object* cast) { + if (!cast) + return; + + Meter* this = (Meter*) cast; + if (Meter_doneFn(this)) { + Meter_done(this); + } + free(this->drawData); + free(this->caption); + free(this->values); + free(this); +} + +void Meter_setCaption(Meter* this, const char* caption) { + free_and_xStrdup(&this->caption, caption); +} + +static inline void Meter_displayBuffer(const Meter* this, RichString* out) { + if (Object_displayFn(this)) { + Object_display(this, out); + } else { + RichString_writeWide(out, CRT_colors[Meter_attributes(this)[0]], this->txtBuffer); + } +} + +void Meter_setMode(Meter* this, int modeIndex) { + if (modeIndex > 0 && modeIndex == this->mode) { + return; + } + + if (!modeIndex) { + modeIndex = 1; + } + + assert(modeIndex < LAST_METERMODE); + if (Meter_defaultMode(this) == CUSTOM_METERMODE) { + this->draw = Meter_drawFn(this); + if (Meter_updateModeFn(this)) { + Meter_updateMode(this, modeIndex); + } + } else { + assert(modeIndex >= 1); + free(this->drawData); + this->drawData = NULL; + + const MeterMode* mode = Meter_modes[modeIndex]; + this->draw = mode->draw; + this->h = mode->h; + } + this->mode = modeIndex; +} + +ListItem* Meter_toListItem(const Meter* this, bool moving) { + char mode[20]; + if (this->mode) { + xSnprintf(mode, sizeof(mode), " [%s]", Meter_modes[this->mode]->uiName); + } else { + mode[0] = '\0'; + } + char name[32]; + if (Meter_getUiNameFn(this)) + Meter_getUiName(this, name, sizeof(name)); + else + xSnprintf(name, sizeof(name), "%s", Meter_uiName(this)); + char buffer[50]; + xSnprintf(buffer, sizeof(buffer), "%s%s", name, mode); + ListItem* li = ListItem_new(buffer, 0); + li->moving = moving; + return li; +} + +/* ---------- TextMeterMode ---------- */ + +static void TextMeterMode_draw(Meter* this, int x, int y, int w) { + const char* caption = Meter_getCaption(this); + attrset(CRT_colors[METER_TEXT]); + mvaddnstr(y, x, caption, w - 1); + attrset(CRT_colors[RESET_COLOR]); + + int captionLen = strlen(caption); + x += captionLen; + w -= captionLen; + if (w <= 0) + return; + + RichString_begin(out); + Meter_displayBuffer(this, &out); + RichString_printoffnVal(out, y, x, 0, w - 1); + RichString_delete(&out); +} + +/* ---------- BarMeterMode ---------- */ + +static const char BarMeterMode_characters[] = "|#*@$%&."; + +static void BarMeterMode_draw(Meter* this, int x, int y, int w) { + const char* caption = Meter_getCaption(this); + w -= 2; + attrset(CRT_colors[METER_TEXT]); + int captionLen = 3; + mvaddnstr(y, x, caption, captionLen); + x += captionLen; + w -= captionLen; + attrset(CRT_colors[BAR_BORDER]); + mvaddch(y, x, '['); + mvaddch(y, x + MAXIMUM(w, 0), ']'); + attrset(CRT_colors[RESET_COLOR]); + + w--; + x++; + + if (w < 1) + return; + + // The text in the bar is right aligned; + // Pad with maximal spaces and then calculate needed starting position offset + RichString_begin(bar); + RichString_appendChr(&bar, 0, ' ', w); + RichString_appendWide(&bar, 0, this->txtBuffer); + int startPos = RichString_sizeVal(bar) - w; + if (startPos > w) { + // Text is too large for bar + // Truncate meter text at a space character + for (int pos = 2 * w; pos > w; pos--) { + if (RichString_getCharVal(bar, pos) == ' ') { + while (pos > w && RichString_getCharVal(bar, pos - 1) == ' ') + pos--; + startPos = pos - w; + break; + } + } + + // If still too large, print the start not the end + startPos = MINIMUM(startPos, w); + } + assert(startPos >= 0); + assert(startPos <= w); + assert(startPos + w <= RichString_sizeVal(bar)); + + int blockSizes[10]; + + // First draw in the bar[] buffer... + int offset = 0; + for (uint8_t i = 0; i < this->curItems; i++) { + double value = this->values[i]; + value = CLAMP(value, 0.0, this->total); + if (value > 0) { + blockSizes[i] = ceil((value / this->total) * w); + } else { + blockSizes[i] = 0; + } + int nextOffset = offset + blockSizes[i]; + // (Control against invalid values) + nextOffset = CLAMP(nextOffset, 0, w); + for (int j = offset; j < nextOffset; j++) + if (RichString_getCharVal(bar, startPos + j) == ' ') { + if (CRT_colorScheme == COLORSCHEME_MONOCHROME) { + RichString_setChar(&bar, startPos + j, BarMeterMode_characters[i]); + } else { + RichString_setChar(&bar, startPos + j, '|'); + } + } + offset = nextOffset; + } + + // ...then print the buffer. + offset = 0; + for (uint8_t i = 0; i < this->curItems; i++) { + int attr = this->curAttributes ? this->curAttributes[i] : Meter_attributes(this)[i]; + RichString_setAttrn(&bar, CRT_colors[attr], startPos + offset, blockSizes[i]); + RichString_printoffnVal(bar, y, x + offset, startPos + offset, MINIMUM(blockSizes[i], w - offset)); + offset += blockSizes[i]; + offset = CLAMP(offset, 0, w); + } + if (offset < w) { + RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, w - offset); + RichString_printoffnVal(bar, y, x + offset, startPos + offset, w - offset); + } + + RichString_delete(&bar); + + move(y, x + w + 1); + attrset(CRT_colors[RESET_COLOR]); +} + +/* ---------- GraphMeterMode ---------- */ + +#ifdef HAVE_LIBNCURSESW + +#define PIXPERROW_UTF8 4 +static const char* const GraphMeterMode_dotsUtf8[] = { + /*00*/" ", /*01*/"⢀", /*02*/"⢠", /*03*/"⢰", /*04*/ "⢸", + /*10*/"⡀", /*11*/"⣀", /*12*/"⣠", /*13*/"⣰", /*14*/ "⣸", + /*20*/"⡄", /*21*/"⣄", /*22*/"⣤", /*23*/"⣴", /*24*/ "⣼", + /*30*/"⡆", /*31*/"⣆", /*32*/"⣦", /*33*/"⣶", /*34*/ "⣾", + /*40*/"⡇", /*41*/"⣇", /*42*/"⣧", /*43*/"⣷", /*44*/ "⣿" +}; + +#endif + +#define PIXPERROW_ASCII 2 +static const char* const GraphMeterMode_dotsAscii[] = { + /*00*/" ", /*01*/".", /*02*/":", + /*10*/".", /*11*/".", /*12*/":", + /*20*/":", /*21*/":", /*22*/":" +}; + +static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { + const ProcessList* pl = this->pl; + + if (!this->drawData) { + this->drawData = xCalloc(1, sizeof(GraphData)); + } + GraphData* data = this->drawData; + const int nValues = METER_GRAPHDATA_SIZE; + + const char* const* GraphMeterMode_dots; + int GraphMeterMode_pixPerRow; +#ifdef HAVE_LIBNCURSESW + if (CRT_utf8) { + GraphMeterMode_dots = GraphMeterMode_dotsUtf8; + GraphMeterMode_pixPerRow = PIXPERROW_UTF8; + } else +#endif + { + GraphMeterMode_dots = GraphMeterMode_dotsAscii; + GraphMeterMode_pixPerRow = PIXPERROW_ASCII; + } + + const char* caption = Meter_getCaption(this); + attrset(CRT_colors[METER_TEXT]); + int captionLen = 3; + mvaddnstr(y, x, caption, captionLen); + x += captionLen; + w -= captionLen; + + if (!timercmp(&pl->realtime, &(data->time), <)) { + int globalDelay = this->pl->settings->delay; + struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay - ((globalDelay / 10) * 10)) * 100000 }; + timeradd(&pl->realtime, &delay, &(data->time)); + + for (int i = 0; i < nValues - 1; i++) + data->values[i] = data->values[i + 1]; + + double value = 0.0; + for (uint8_t i = 0; i < this->curItems; i++) + value += this->values[i]; + data->values[nValues - 1] = value; + } + + int i = nValues - (w * 2) + 2, k = 0; + if (i < 0) { + k = -i / 2; + i = 0; + } + for (; i < nValues - 1; i += 2, k++) { + int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT; + if (this->total < 1) + this->total = 1; + int v1 = CLAMP((int) lround(data->values[i] / this->total * pix), 1, pix); + int v2 = CLAMP((int) lround(data->values[i + 1] / this->total * pix), 1, pix); + + int colorIdx = GRAPH_1; + for (int line = 0; line < GRAPH_HEIGHT; line++) { + int line1 = CLAMP(v1 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow); + int line2 = CLAMP(v2 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow); + + attrset(CRT_colors[colorIdx]); + mvaddstr(y + line, x + k, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]); + colorIdx = GRAPH_2; + } + } + attrset(CRT_colors[RESET_COLOR]); +} + +/* ---------- LEDMeterMode ---------- */ + +static const char* const LEDMeterMode_digitsAscii[] = { + " __ ", " ", " __ ", " __ ", " ", " __ ", " __ ", " __ ", " __ ", " __ ", + "| |", " |", " __|", " __|", "|__|", "|__ ", "|__ ", " |", "|__|", "|__|", + "|__|", " |", "|__ ", " __|", " |", " __|", "|__|", " |", "|__|", " __|" +}; + +#ifdef HAVE_LIBNCURSESW + +static const char* const LEDMeterMode_digitsUtf8[] = { + "┌──┐", " ┐ ", "╶──┐", "╶──┐", "╷ ╷", "┌──╴", "┌──╴", "╶──┐", "┌──┐", "┌──┐", + "│ │", " │ ", "┌──┘", " ──┤", "└──┤", "└──┐", "├──┐", " │", "├──┤", "└──┤", + "└──┘", " ╵ ", "└──╴", "╶──┘", " ╵", "╶──┘", "└──┘", " ╵", "└──┘", " ──┘" +}; + +#endif + +static const char* const* LEDMeterMode_digits; + +static void LEDMeterMode_drawDigit(int x, int y, int n) { + for (int i = 0; i < 3; i++) + mvaddstr(y + i, x, LEDMeterMode_digits[i * 10 + n]); +} + +static void LEDMeterMode_draw(Meter* this, int x, int y, ATTR_UNUSED int w) { +#ifdef HAVE_LIBNCURSESW + if (CRT_utf8) + LEDMeterMode_digits = LEDMeterMode_digitsUtf8; + else +#endif + LEDMeterMode_digits = LEDMeterMode_digitsAscii; + + RichString_begin(out); + Meter_displayBuffer(this, &out); + + int yText = +#ifdef HAVE_LIBNCURSESW + CRT_utf8 ? y + 1 : +#endif + y + 2; + attrset(CRT_colors[LED_COLOR]); + const char* caption = Meter_getCaption(this); + mvaddstr(yText, x, caption); + int xx = x + strlen(caption); + int len = RichString_sizeVal(out); + for (int i = 0; i < len; i++) { + int c = RichString_getCharVal(out, i); + if (c >= '0' && c <= '9') { + LEDMeterMode_drawDigit(xx, y, c - '0'); + xx += 4; + } else { +#ifdef HAVE_LIBNCURSESW + const cchar_t wc = { .chars = { c, '\0' }, .attr = 0 }; /* use LED_COLOR from attrset() */ + mvadd_wch(yText, xx, &wc); +#else + mvaddch(yText, xx, c); +#endif + xx += 1; + } + } + attrset(CRT_colors[RESET_COLOR]); + RichString_delete(&out); +} + +static MeterMode BarMeterMode = { + .uiName = "Bar", + .h = 1, + .draw = BarMeterMode_draw, +}; + +static MeterMode TextMeterMode = { + .uiName = "Text", + .h = 1, + .draw = TextMeterMode_draw, +}; + +static MeterMode GraphMeterMode = { + .uiName = "Graph", + .h = GRAPH_HEIGHT, + .draw = GraphMeterMode_draw, +}; + +static MeterMode LEDMeterMode = { + .uiName = "LED", + .h = 3, + .draw = LEDMeterMode_draw, +}; + +const MeterMode* const Meter_modes[] = { + NULL, + &BarMeterMode, + &TextMeterMode, + &GraphMeterMode, + &LEDMeterMode, + NULL +}; + +/* Blank meter */ + +static void BlankMeter_updateValues(Meter* this) { + this->txtBuffer[0] = '\0'; +} + +static void BlankMeter_display(ATTR_UNUSED const Object* cast, ATTR_UNUSED RichString* out) { +} + +static const int BlankMeter_attributes[] = { + DEFAULT_COLOR +}; + +const MeterClass BlankMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = BlankMeter_display, + }, + .updateValues = BlankMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = BlankMeter_attributes, + .name = "Blank", + .uiName = "Blank", + .caption = "" +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Meter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Meter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Meter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Meter.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,153 @@ +#ifndef HEADER_Meter +#define HEADER_Meter +/* +htop - Meter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include +#include +#include + +#include "ListItem.h" +#include "Object.h" +#include "ProcessList.h" + + +#define METER_TXTBUFFER_LEN 256 +#define METER_GRAPHDATA_SIZE 256 + +#define METER_BUFFER_CHECK(buffer, size, written) \ + do { \ + if ((written) < 0 || (size_t)(written) >= (size)) { \ + return; \ + } \ + (buffer) += (written); \ + (size) -= (size_t)(written); \ + } while (0) + +#define METER_BUFFER_APPEND_CHR(buffer, size, c) \ + do { \ + if ((size) < 2) { \ + return; \ + } \ + *(buffer)++ = c; \ + *(buffer) = '\0'; \ + (size)--; \ + if ((size) == 0) { \ + return; \ + } \ + } while (0) + + +struct Meter_; +typedef struct Meter_ Meter; + +typedef void(*Meter_Init)(Meter*); +typedef void(*Meter_Done)(Meter*); +typedef void(*Meter_UpdateMode)(Meter*, int); +typedef void(*Meter_UpdateValues)(Meter*); +typedef void(*Meter_Draw)(Meter*, int, int, int); +typedef const char* (*Meter_GetCaption)(const Meter*); +typedef void(*Meter_GetUiName)(const Meter*, char*, size_t); + +typedef struct MeterClass_ { + const ObjectClass super; + const Meter_Init init; + const Meter_Done done; + const Meter_UpdateMode updateMode; + const Meter_UpdateValues updateValues; + const Meter_Draw draw; + const Meter_GetCaption getCaption; + const Meter_GetUiName getUiName; + const int defaultMode; + const double total; + const int* const attributes; + const char* const name; /* internal name of the meter, must not contain any space */ + const char* const uiName; /* display name in header setup menu */ + const char* const caption; /* prefix in the actual header */ + const char* const description; /* optional meter description in header setup menu */ + const uint8_t maxItems; +} MeterClass; + +#define As_Meter(this_) ((const MeterClass*)((this_)->super.klass)) +#define Meter_initFn(this_) As_Meter(this_)->init +#define Meter_init(this_) As_Meter(this_)->init((Meter*)(this_)) +#define Meter_done(this_) As_Meter(this_)->done((Meter*)(this_)) +#define Meter_updateModeFn(this_) As_Meter(this_)->updateMode +#define Meter_updateMode(this_, m_) As_Meter(this_)->updateMode((Meter*)(this_), m_) +#define Meter_drawFn(this_) As_Meter(this_)->draw +#define Meter_doneFn(this_) As_Meter(this_)->done +#define Meter_updateValues(this_) As_Meter(this_)->updateValues((Meter*)(this_)) +#define Meter_getUiNameFn(this_) As_Meter(this_)->getUiName +#define Meter_getUiName(this_,n_,l_) As_Meter(this_)->getUiName((const Meter*)(this_),n_,l_) +#define Meter_getCaptionFn(this_) As_Meter(this_)->getCaption +#define Meter_getCaption(this_) (Meter_getCaptionFn(this_) ? As_Meter(this_)->getCaption((const Meter*)(this_)) : (this_)->caption) +#define Meter_defaultMode(this_) As_Meter(this_)->defaultMode +#define Meter_attributes(this_) As_Meter(this_)->attributes +#define Meter_name(this_) As_Meter(this_)->name +#define Meter_uiName(this_) As_Meter(this_)->uiName + +typedef struct GraphData_ { + struct timeval time; + double values[METER_GRAPHDATA_SIZE]; +} GraphData; + +struct Meter_ { + Object super; + Meter_Draw draw; + + char* caption; + int mode; + unsigned int param; + GraphData* drawData; + int h; + int columnWidthCount; /*<< only used internally by the Header */ + const ProcessList* pl; + uint8_t curItems; + const int* curAttributes; + char txtBuffer[METER_TXTBUFFER_LEN]; + double* values; + double total; + void* meterData; +}; + +typedef struct MeterMode_ { + Meter_Draw draw; + const char* uiName; + int h; +} MeterMode; + +typedef enum { + CUSTOM_METERMODE = 0, + BAR_METERMODE, + TEXT_METERMODE, + GRAPH_METERMODE, + LED_METERMODE, + LAST_METERMODE +} MeterModeId; + +extern const MeterClass Meter_class; + +Meter* Meter_new(const ProcessList* pl, unsigned int param, const MeterClass* type); + +int Meter_humanUnit(char* buffer, unsigned long int value, size_t size); + +void Meter_delete(Object* cast); + +void Meter_setCaption(Meter* this, const char* caption); + +void Meter_setMode(Meter* this, int modeIndex); + +ListItem* Meter_toListItem(const Meter* this, bool moving); + +extern const MeterMode* const Meter_modes[]; + +extern const MeterClass BlankMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/MetersPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/MetersPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/MetersPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/MetersPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,223 @@ +/* +htop - MetersPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "MetersPanel.h" + +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Header.h" +#include "ListItem.h" +#include "Meter.h" +#include "Object.h" +#include "ProvideCurses.h" + + +// Note: In code the meters are known to have bar/text/graph "Modes", but in UI +// we call them "Styles". +static const char* const MetersFunctions[] = {"Style ", "Move ", " ", "Delete", "Done ", NULL}; +static const char* const MetersKeys[] = {"Space", "Enter", "", "Del", "F10"}; +static const int MetersEvents[] = {' ', 13, ERR, KEY_DC, KEY_F(10)}; + +// We avoid UTF-8 arrows ← → here as they might display full-width on Chinese +// terminals, breaking our aligning. +// In , arrows (U+2019..U+2199) are +// considered "Ambiguous characters". +static const char* const MetersMovingFunctions[] = {"Style ", "Lock ", "Up ", "Down ", "Left ", "Right ", " ", "Delete", "Done ", NULL}; +static const char* const MetersMovingKeys[] = {"Space", "Enter", "Up", "Dn", "<-", "->", " ", "Del", "F10"}; +static const int MetersMovingEvents[] = {' ', 13, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, ERR, KEY_DC, KEY_F(10)}; +static FunctionBar* Meters_movingBar = NULL; + +void MetersPanel_cleanup() { + if (Meters_movingBar) { + FunctionBar_delete(Meters_movingBar); + Meters_movingBar = NULL; + } +} + +static void MetersPanel_delete(Object* object) { + Panel* super = (Panel*) object; + MetersPanel* this = (MetersPanel*) object; + Panel_done(super); + free(this); +} + +void MetersPanel_setMoving(MetersPanel* this, bool moving) { + Panel* super = (Panel*) this; + this->moving = moving; + ListItem* selected = (ListItem*)Panel_getSelected(super); + if (selected) { + selected->moving = moving; + } + if (!moving) { + Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS); + Panel_setDefaultBar(super); + } else { + Panel_setSelectionColor(super, PANEL_SELECTION_FOLLOW); + super->currentBar = Meters_movingBar; + } +} + +static inline bool moveToNeighbor(MetersPanel* this, MetersPanel* neighbor, int selected) { + Panel* super = (Panel*) this; + if (this->moving) { + if (neighbor) { + if (selected < Vector_size(this->meters)) { + MetersPanel_setMoving(this, false); + + Meter* meter = (Meter*) Vector_take(this->meters, selected); + Panel_remove(super, selected); + Vector_insert(neighbor->meters, selected, meter); + Panel_insert(&(neighbor->super), selected, (Object*) Meter_toListItem(meter, false)); + Panel_setSelected(&(neighbor->super), selected); + + MetersPanel_setMoving(neighbor, true); + return true; + } + } + } + return false; +} + +static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) { + MetersPanel* this = (MetersPanel*) super; + + int selected = Panel_getSelectedIndex(super); + HandlerResult result = IGNORED; + bool sideMove = false; + + switch(ch) { + case 0x0a: + case 0x0d: + case KEY_ENTER: + { + if (!Vector_size(this->meters)) + break; + MetersPanel_setMoving(this, !(this->moving)); + result = HANDLED; + break; + } + case ' ': + case KEY_F(4): + case 't': + { + if (!Vector_size(this->meters)) + break; + Meter* meter = (Meter*) Vector_get(this->meters, selected); + int mode = meter->mode + 1; + if (mode == LAST_METERMODE) mode = 1; + Meter_setMode(meter, mode); + Panel_set(super, selected, (Object*) Meter_toListItem(meter, this->moving)); + result = HANDLED; + break; + } + case KEY_UP: + { + if (!this->moving) { + break; + } + } + /* else fallthrough */ + case KEY_F(7): + case '[': + case '-': + { + Vector_moveUp(this->meters, selected); + Panel_moveSelectedUp(super); + result = HANDLED; + break; + } + case KEY_DOWN: + { + if (!this->moving) { + break; + } + } + /* else fallthrough */ + case KEY_F(8): + case ']': + case '+': + { + Vector_moveDown(this->meters, selected); + Panel_moveSelectedDown(super); + result = HANDLED; + break; + } + case KEY_RIGHT: + { + sideMove = moveToNeighbor(this, this->rightNeighbor, selected); + if (this->moving && !sideMove) { + // lock user here until it exits positioning-mode + result = HANDLED; + } + // if user is free, don't set HANDLED; + // let ScreenManager handle focus. + break; + } + case KEY_LEFT: + { + sideMove = moveToNeighbor(this, this->leftNeighbor, selected); + if (this->moving && !sideMove) { + result = HANDLED; + } + break; + } + case KEY_F(9): + case KEY_DC: + { + if (!Vector_size(this->meters)) + break; + if (selected < Vector_size(this->meters)) { + Vector_remove(this->meters, selected); + Panel_remove(super, selected); + } + MetersPanel_setMoving(this, false); + result = HANDLED; + break; + } + } + if (result == HANDLED || sideMove) { + Header* header = this->scr->header; + this->settings->changed = true; + Header_calculateHeight(header); + Header_draw(header); + ScreenManager_resize(this->scr, this->scr->x1, header->height, this->scr->x2, this->scr->y2); + } + return result; +} + +const PanelClass MetersPanel_class = { + .super = { + .extends = Class(Panel), + .delete = MetersPanel_delete + }, + .eventHandler = MetersPanel_eventHandler +}; + +MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr) { + MetersPanel* this = AllocThis(MetersPanel); + Panel* super = (Panel*) this; + FunctionBar* fuBar = FunctionBar_new(MetersFunctions, MetersKeys, MetersEvents); + if (!Meters_movingBar) { + Meters_movingBar = FunctionBar_new(MetersMovingFunctions, MetersMovingKeys, MetersMovingEvents); + } + Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar); + + this->settings = settings; + this->meters = meters; + this->scr = scr; + this->moving = false; + this->rightNeighbor = NULL; + this->leftNeighbor = NULL; + Panel_setHeader(super, header); + for (int i = 0; i < Vector_size(meters); i++) { + const Meter* meter = (const Meter*) Vector_get(meters, i); + Panel_add(super, (Object*) Meter_toListItem(meter, false)); + } + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/MetersPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/MetersPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/MetersPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/MetersPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,40 @@ +#ifndef HEADER_MetersPanel +#define HEADER_MetersPanel +/* +htop - MetersPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Panel.h" +#include "ScreenManager.h" +#include "Settings.h" +#include "Vector.h" + + +struct MetersPanel_; +typedef struct MetersPanel_ MetersPanel; + +struct MetersPanel_ { + Panel super; + + Settings* settings; + Vector* meters; + ScreenManager* scr; + MetersPanel* leftNeighbor; + MetersPanel* rightNeighbor; + bool moving; +}; + +void MetersPanel_cleanup(void); + +void MetersPanel_setMoving(MetersPanel* this, bool moving); + +extern const PanelClass MetersPanel_class; + +MetersPanel* MetersPanel_new(Settings* settings, const char* header, Vector* meters, ScreenManager* scr); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,262 @@ +/* +htop - NetBSDProcess.c +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +(C) 2021 Santhosh Raju +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "netbsd/NetBSDProcess.h" + +#include + +#include "CRT.h" +#include "Process.h" +#include "RichString.h" +#include "XUtils.h" + + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { + .name = "", + .title = NULL, + .description = NULL, + .flags = 0, + }, + [PID] = { + .name = "PID", + .title = "PID", + .description = "Process/thread ID", + .flags = 0, + .pidColumn = true, + }, + [COMM] = { + .name = "Command", + .title = "Command ", + .description = "Command line", + .flags = 0, + }, + [STATE] = { + .name = "STATE", + .title = "S ", + .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging)", + .flags = 0, + }, + [PPID] = { + .name = "PPID", + .title = "PPID", + .description = "Parent process ID", + .flags = 0, + .pidColumn = true, + }, + [PGRP] = { + .name = "PGRP", + .title = "PGRP", + .description = "Process group ID", + .flags = 0, + .pidColumn = true, + }, + [SESSION] = { + .name = "SESSION", + .title = "SESN", + .description = "Process's session ID", + .flags = 0, + .pidColumn = true, + }, + [TTY] = { + .name = "TTY", + .title = "TTY ", + .description = "Controlling terminal", + .flags = 0, + }, + [TPGID] = { + .name = "TPGID", + .title = "TPGID", + .description = "Process ID of the fg process group of the controlling terminal", + .flags = 0, + .pidColumn = true, + }, + [MINFLT] = { + .name = "MINFLT", + .title = " MINFLT ", + .description = "Number of minor faults which have not required loading a memory page from disk", + .flags = 0, + .defaultSortDesc = true, + }, + [MAJFLT] = { + .name = "MAJFLT", + .title = " MAJFLT ", + .description = "Number of major faults which have required loading a memory page from disk", + .flags = 0, + .defaultSortDesc = true, + }, + [PRIORITY] = { + .name = "PRIORITY", + .title = "PRI ", + .description = "Kernel's internal priority for the process", + .flags = 0, + }, + [NICE] = { + .name = "NICE", + .title = " NI ", + .description = "Nice value (the higher the value, the more it lets other processes take priority)", + .flags = 0, + }, + [STARTTIME] = { + .name = "STARTTIME", + .title = "START ", + .description = "Time the process was started", + .flags = 0, + }, + [ELAPSED] = { + .name = "ELAPSED", + .title = "ELAPSED ", + .description = "Time since the process was started", + .flags = 0, + }, + [PROCESSOR] = { + .name = "PROCESSOR", + .title = "CPU ", + .description = "Id of the CPU the process last executed on", + .flags = 0, + }, + [M_VIRT] = { + .name = "M_VIRT", + .title = " VIRT ", + .description = "Total program size in virtual memory", + .flags = 0, + .defaultSortDesc = true, + }, + [M_RESIDENT] = { + .name = "M_RESIDENT", + .title = " RES ", + .description = "Resident set size, size of the text and data sections, plus stack usage", + .flags = 0, + .defaultSortDesc = true, + }, + [ST_UID] = { + .name = "ST_UID", + .title = " UID ", + .description = "User ID of the process owner", + .flags = 0, + }, + [PERCENT_CPU] = { + .name = "PERCENT_CPU", + .title = "CPU% ", + .description = "Percentage of the CPU time the process used in the last sampling", + .flags = 0, + .defaultSortDesc = true, + }, + [PERCENT_NORM_CPU] = { + .name = "PERCENT_NORM_CPU", + .title = "NCPU%", + .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", + .flags = 0, + .defaultSortDesc = true, + }, + [PERCENT_MEM] = { + .name = "PERCENT_MEM", + .title = "MEM% ", + .description = "Percentage of the memory the process is using, based on resident memory size", + .flags = 0, + .defaultSortDesc = true, + }, + [USER] = { + .name = "USER", + .title = "USER ", + .description = "Username of the process owner (or user ID if name cannot be determined)", + .flags = 0, + }, + [TIME] = { + .name = "TIME", + .title = " TIME+ ", + .description = "Total time the process has spent in user and system time", + .flags = 0, + .defaultSortDesc = true, + }, + [NLWP] = { + .name = "NLWP", + .title = "NLWP ", + .description = "Number of threads in the process", + .flags = 0, + }, + [TGID] = { + .name = "TGID", + .title = "TGID", + .description = "Thread group ID (i.e. process ID)", + .flags = 0, + .pidColumn = true, + }, + [PROC_COMM] = { + .name = "COMM", + .title = "COMM ", + .description = "comm string of the process", + .flags = 0, + }, + [PROC_EXE] = { + .name = "EXE", + .title = "EXE ", + .description = "Basename of exe of the process", + .flags = 0, + }, + [CWD] = { + .name = "CWD", + .title = "CWD ", + .description = "The current working directory of the process", + .flags = PROCESS_FLAG_CWD, + }, + +}; + +Process* NetBSDProcess_new(const Settings* settings) { + NetBSDProcess* this = xCalloc(sizeof(NetBSDProcess), 1); + Object_setClass(this, Class(NetBSDProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + NetBSDProcess* this = (NetBSDProcess*) cast; + Process_done((Process*)cast); + free(this); +} + +static void NetBSDProcess_writeField(const Process* this, RichString* str, ProcessField field) { + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + + switch (field) { + // add NetBSD-specific fields here + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int NetBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const NetBSDProcess* p1 = (const NetBSDProcess*)v1; + const NetBSDProcess* p2 = (const NetBSDProcess*)v2; + + // remove if actually used + (void)p1; (void)p2; + + switch (key) { + // add NetBSD-specific fields here + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass NetBSDProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = NetBSDProcess_writeField, + .compareByKey = NetBSDProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcess.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef HEADER_NetBSDProcess +#define HEADER_NetBSDProcess +/* +htop - NetBSDProcess.h +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +(C) 2021 Santhosh Raju +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Object.h" +#include "Process.h" +#include "Settings.h" + + +typedef struct NetBSDProcess_ { + Process super; +} NetBSDProcess; + +extern const ProcessClass NetBSDProcess_class; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* NetBSDProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,435 @@ +/* +htop - NetBSDProcessList.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +(C) 2021 Santhosh Raju +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "netbsd/NetBSDProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "Process.h" +#include "ProcessList.h" +#include "Settings.h" +#include "XUtils.h" +#include "netbsd/NetBSDProcess.h" + + +static long fscale; +static int pageSize; +static int pageSizeKB; + +static char const *freqSysctls[] = { + "machdep.est.frequency.current", + "machdep.powernow.frequency.current", + "machdep.intrepid.frequency.current", + "machdep.loongson.frequency.current", + "machdep.cpu.frequency.current", + "machdep.frequency.current", + NULL +}; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + const int mib[] = { CTL_HW, HW_NCPU }; + const int fmib[] = { CTL_KERN, KERN_FSCALE }; + int r; + size_t size; + char errbuf[_POSIX2_LINE_MAX]; + + NetBSDProcessList* npl = xCalloc(1, sizeof(NetBSDProcessList)); + ProcessList* pl = (ProcessList*) npl; + ProcessList_init(pl, Class(NetBSDProcess), usersTable, dynamicMeters, pidMatchList, userId); + + size = sizeof(pl->cpuCount); + r = sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); + if (r < 0 || pl->cpuCount < 1) { + pl->cpuCount = 1; + } + npl->cpus = xCalloc(pl->cpuCount + 1, sizeof(CPUData)); + + size = sizeof(fscale); + if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) { + CRT_fatalError("fscale sysctl call failed"); + } + + if ((pageSize = sysconf(_SC_PAGESIZE)) == -1) + CRT_fatalError("pagesize sysconf call failed"); + pageSizeKB = pageSize / ONE_K; + + for (unsigned int i = 0; i <= pl->cpuCount; i++) { + CPUData* d = npl->cpus + i; + d->totalTime = 1; + d->totalPeriod = 1; + } + + npl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); + if (npl->kd == NULL) { + CRT_fatalError("kvm_openfiles() failed"); + } + + return pl; +} + +void ProcessList_delete(ProcessList* this) { + NetBSDProcessList* npl = (NetBSDProcessList*) this; + + if (npl->kd) { + kvm_close(npl->kd); + } + + free(npl->cpus); + + ProcessList_done(this); + free(this); +} + +static void NetBSDProcessList_scanMemoryInfo(ProcessList* pl) { + static int uvmexp_mib[] = {CTL_VM, VM_UVMEXP2}; + struct uvmexp_sysctl uvmexp; + size_t size_uvmexp = sizeof(uvmexp); + + if (sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0) < 0) { + CRT_fatalError("uvmexp sysctl call failed"); + } + + pl->totalMem = uvmexp.npages * pageSizeKB; + pl->buffersMem = 0; + pl->cachedMem = (uvmexp.filepages + uvmexp.execpages) * pageSizeKB; + pl->usedMem = (uvmexp.active + uvmexp.wired) * pageSizeKB; + pl->totalSwap = uvmexp.swpages * pageSizeKB; + pl->usedSwap = uvmexp.swpginuse * pageSizeKB; +} + +static void NetBSDProcessList_updateExe(const struct kinfo_proc2* kproc, Process* proc) { + const int mib[] = { CTL_KERN, KERN_PROC_ARGS, kproc->p_pid, KERN_PROC_PATHNAME }; + char buffer[2048]; + size_t size = sizeof(buffer); + if (sysctl(mib, 4, buffer, &size, NULL, 0) != 0) { + Process_updateExe(proc, NULL); + return; + } + + /* Kernel threads return an empty buffer */ + if (buffer[0] == '\0') { + Process_updateExe(proc, NULL); + return; + } + + Process_updateExe(proc, buffer); +} + +static void NetBSDProcessList_updateCwd(const struct kinfo_proc2* kproc, Process* proc) { + const int mib[] = { CTL_KERN, KERN_PROC_ARGS, kproc->p_pid, KERN_PROC_CWD }; + char buffer[2048]; + size_t size = sizeof(buffer); + if (sysctl(mib, 4, buffer, &size, NULL, 0) != 0) { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + /* Kernel threads return an empty buffer */ + if (buffer[0] == '\0') { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + free_and_xStrdup(&proc->procCwd, buffer); +} + +static void NetBSDProcessList_updateProcessName(kvm_t* kd, const struct kinfo_proc2* kproc, Process* proc) { + Process_updateComm(proc, kproc->p_comm); + + /* + * Like NetBSD's top(1), we try to fall back to the command name + * (argv[0]) if we fail to construct the full command. + */ + char** arg = kvm_getargv2(kd, kproc, 500); + if (arg == NULL || *arg == NULL) { + Process_updateCmdline(proc, kproc->p_comm, 0, strlen(kproc->p_comm)); + return; + } + + size_t len = 0; + for (int i = 0; arg[i] != NULL; i++) { + len += strlen(arg[i]) + 1; /* room for arg and trailing space or NUL */ + } + + /* don't use xMalloc here - we want to handle huge argv's gracefully */ + char* s; + if ((s = malloc(len)) == NULL) { + Process_updateCmdline(proc, kproc->p_comm, 0, strlen(kproc->p_comm)); + return; + } + + *s = '\0'; + + int start = 0; + int end = 0; + for (int i = 0; arg[i] != NULL; i++) { + size_t n = strlcat(s, arg[i], len); + if (i == 0) { + end = MINIMUM(n, len - 1); + /* check if cmdline ended earlier, e.g 'kdeinit5: Running...' */ + for (int j = end; j > 0; j--) { + if (arg[0][j] == ' ' && arg[0][j - 1] != '\\') { + end = (arg[0][j - 1] == ':') ? (j - 1) : j; + } + } + } + /* the trailing space should get truncated anyway */ + strlcat(s, " ", len); + } + + Process_updateCmdline(proc, s, start, end); +} + +/* + * Borrowed with modifications from NetBSD's top(1). + */ +static double getpcpu(const struct kinfo_proc2* kp) { + if (fscale == 0) + return 0.0; + + return 100.0 * (double)kp->p_pctcpu / fscale; +} + +static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) { + const Settings* settings = this->super.settings; + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + int count = 0; + int nlwps = 0; + + const struct kinfo_proc2* kprocs = kvm_getproc2(this->kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &count); + + for (int i = 0; i < count; i++) { + const struct kinfo_proc2* kproc = &kprocs[i]; + + bool preExisting = false; + Process* proc = ProcessList_getProcess(&this->super, kproc->p_pid, &preExisting, NetBSDProcess_new); + + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc))); + + if (!preExisting) { + proc->pid = kproc->p_pid; + proc->ppid = kproc->p_ppid; + proc->tpgid = kproc->p_tpgid; + proc->tgid = kproc->p_pid; + proc->session = kproc->p_sid; + proc->tty_nr = kproc->p_tdev; + proc->pgrp = kproc->p__pgid; + proc->isKernelThread = proc->pgrp == 0; + proc->isUserlandThread = proc->pid != proc->tgid; + proc->starttime_ctime = kproc->p_ustart_sec; + Process_fillStarttimeBuffer(proc); + ProcessList_add(&this->super, proc); + + NetBSDProcessList_updateExe(kproc, proc); + NetBSDProcessList_updateProcessName(this->kd, kproc, proc); + } else { + if (settings->updateProcessNames) { + NetBSDProcessList_updateProcessName(this->kd, kproc, proc); + } + } + + if (settings->flags & PROCESS_FLAG_CWD) { + NetBSDProcessList_updateCwd(kproc, proc); + } + + if (proc->st_uid != kproc->p_uid) { + proc->st_uid = kproc->p_uid; + proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid); + } + + proc->m_virt = kproc->p_vm_vsize; + proc->m_resident = kproc->p_vm_rssize; + proc->percent_mem = (proc->m_resident * pageSizeKB) / (double)(this->super.totalMem) * 100.0; + proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0, this->super.cpuCount * 100.0); + proc->nlwp = kproc->p_nlwps; + proc->nice = kproc->p_nice - 20; + proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000)); + proc->priority = kproc->p_priority - PZERO; + + struct kinfo_lwp* klwps = kvm_getlwps(this->kd, kproc->p_pid, kproc->p_paddr, sizeof(struct kinfo_lwp), &nlwps); + + switch (kproc->p_realstat) { + case SIDL: proc->state = 'I'; break; + case SACTIVE: + // We only consider the first LWP with a one of the below states. + for (int j = 0; j < nlwps; j++) { + if (klwps) { + switch (klwps[j].l_stat) { + case LSONPROC: proc->state = 'P'; break; + case LSRUN: proc->state = 'R'; break; + case LSSLEEP: proc->state = 'S'; break; + case LSSTOP: proc->state = 'T'; break; + default: proc->state = '?'; + } + if (proc->state != '?') + break; + } else { + proc->state = '?'; + break; + } + } + break; + case SSTOP: proc->state = 'T'; break; + case SZOMB: proc->state = 'Z'; break; + case SDEAD: proc->state = 'D'; break; + default: proc->state = '?'; + } + + if (Process_isKernelThread(proc)) { + this->super.kernelThreads++; + } else if (Process_isUserlandThread(proc)) { + this->super.userlandThreads++; + } + + this->super.totalTasks++; + // SRUN ('R') means runnable, not running + if (proc->state == 'P') { + this->super.runningTasks++; + } + proc->updated = true; + } +} + +static void getKernelCPUTimes(int cpuId, u_int64_t* times) { + const int mib[] = { CTL_KERN, KERN_CP_TIME, cpuId }; + size_t length = sizeof(*times) * CPUSTATES; + if (sysctl(mib, 3, times, &length, NULL, 0) == -1 || length != sizeof(*times) * CPUSTATES) { + CRT_fatalError("sysctl kern.cp_time2 failed"); + } +} + +static void kernelCPUTimesToHtop(const u_int64_t* times, CPUData* cpu) { + unsigned long long totalTime = 0; + for (int i = 0; i < CPUSTATES; i++) { + totalTime += times[i]; + } + + unsigned long long sysAllTime = times[CP_INTR] + times[CP_SYS]; + + cpu->totalPeriod = saturatingSub(totalTime, cpu->totalTime); + cpu->userPeriod = saturatingSub(times[CP_USER], cpu->userTime); + cpu->nicePeriod = saturatingSub(times[CP_NICE], cpu->niceTime); + cpu->sysPeriod = saturatingSub(times[CP_SYS], cpu->sysTime); + cpu->sysAllPeriod = saturatingSub(sysAllTime, cpu->sysAllTime); + cpu->intrPeriod = saturatingSub(times[CP_INTR], cpu->intrTime); + cpu->idlePeriod = saturatingSub(times[CP_IDLE], cpu->idleTime); + + cpu->totalTime = totalTime; + cpu->userTime = times[CP_USER]; + cpu->niceTime = times[CP_NICE]; + cpu->sysTime = times[CP_SYS]; + cpu->sysAllTime = sysAllTime; + cpu->intrTime = times[CP_INTR]; + cpu->idleTime = times[CP_IDLE]; +} + +static void NetBSDProcessList_scanCPUTime(NetBSDProcessList* this) { + u_int64_t kernelTimes[CPUSTATES] = {0}; + u_int64_t avg[CPUSTATES] = {0}; + + for (unsigned int i = 0; i < this->super.cpuCount; i++) { + getKernelCPUTimes(i, kernelTimes); + CPUData* cpu = this->cpus + i + 1; + kernelCPUTimesToHtop(kernelTimes, cpu); + + avg[CP_USER] += cpu->userTime; + avg[CP_NICE] += cpu->niceTime; + avg[CP_SYS] += cpu->sysTime; + avg[CP_INTR] += cpu->intrTime; + avg[CP_IDLE] += cpu->idleTime; + } + + for (int i = 0; i < CPUSTATES; i++) { + avg[i] /= this->super.cpuCount; + } + + kernelCPUTimesToHtop(avg, this->cpus); +} + +static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) { + unsigned int cpus = this->super.cpuCount; + bool match = false; + char name[64]; + int freq = 0; + size_t freqSize; + + for (unsigned int i = 0; i <= cpus; i++) { + this->cpus[i].frequency = NAN; + } + + /* newer hardware supports per-core frequency, for e.g. ARM big.LITTLE */ + for (unsigned int i = 0; i <= cpus; i++) { + xSnprintf(name, sizeof(name), "machdep.cpufreq.cpu%u.current", i); + freqSize = sizeof(freq); + if (sysctlbyname(name, &freq, &freqSize, NULL, 0) != -1) { + this->cpus[i].frequency = freq; + match = true; + } + } + + if (match) { + return; + } + + /* + * Iterate through legacy sysctl nodes for single-core frequency until + * we find a match... + */ + for (const char** s = freqSysctls; *s != NULL; ++s) { + freqSize = sizeof(freq); + if (sysctlbyname(*s, &freq, &freqSize, NULL, 0) != -1) { + match = true; + break; + } + } + + if (match) { + for (unsigned int i = 0; i <= cpus; i++) { + this->cpus[i].frequency = freq; + } + } +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + NetBSDProcessList* npl = (NetBSDProcessList*) super; + + NetBSDProcessList_scanMemoryInfo(super); + NetBSDProcessList_scanCPUTime(npl); + + if (super->settings->showCPUFrequency) { + NetBSDProcessList_scanCPUFrequency(npl); + } + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + NetBSDProcessList_scanProcs(npl); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/NetBSDProcessList.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,58 @@ +#ifndef HEADER_NetBSDProcessList +#define HEADER_NetBSDProcessList +/* +htop - NetBSDProcessList.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +(C) 2021 Santhosh Raju +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" + + +typedef struct CPUData_ { + unsigned long long int totalTime; + unsigned long long int userTime; + unsigned long long int niceTime; + unsigned long long int sysTime; + unsigned long long int sysAllTime; + unsigned long long int spinTime; + unsigned long long int intrTime; + unsigned long long int idleTime; + + unsigned long long int totalPeriod; + unsigned long long int userPeriod; + unsigned long long int nicePeriod; + unsigned long long int sysPeriod; + unsigned long long int sysAllPeriod; + unsigned long long int spinPeriod; + unsigned long long int intrPeriod; + unsigned long long int idlePeriod; + + double frequency; +} CPUData; + +typedef struct NetBSDProcessList_ { + ProcessList super; + kvm_t* kd; + + CPUData* cpus; +} NetBSDProcessList; + + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/Platform.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,329 @@ +/* +htop - netbsd/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +(C) 2021 Santhosh Raju +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "netbsd/Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CPUMeter.h" +#include "ClockMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MemoryMeter.h" +#include "Meter.h" +#include "ProcessList.h" +#include "Settings.h" +#include "SignalsPanel.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "XUtils.h" +#include "netbsd/NetBSDProcess.h" +#include "netbsd/NetBSDProcessList.h" + + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +/* + * See /usr/include/sys/signal.h + */ +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 6 SIGIOT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGURG", .number = 16 }, + { .name = "17 SIGSTOP", .number = 17 }, + { .name = "18 SIGTSTP", .number = 18 }, + { .name = "19 SIGCONT", .number = 19 }, + { .name = "20 SIGCHLD", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGIO", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGINFO", .number = 29 }, + { .name = "30 SIGUSR1", .number = 30 }, + { .name = "31 SIGUSR2", .number = 31 }, + { .name = "32 SIGPWR", .number = 32 }, + { .name = "33 SIGRTMIN", .number = 33 }, + { .name = "34 SIGRTMIN+1", .number = 34 }, + { .name = "35 SIGRTMIN+2", .number = 35 }, + { .name = "36 SIGRTMIN+3", .number = 36 }, + { .name = "37 SIGRTMIN+4", .number = 37 }, + { .name = "38 SIGRTMIN+5", .number = 38 }, + { .name = "39 SIGRTMIN+6", .number = 39 }, + { .name = "40 SIGRTMIN+7", .number = 40 }, + { .name = "41 SIGRTMIN+8", .number = 41 }, + { .name = "42 SIGRTMIN+9", .number = 42 }, + { .name = "43 SIGRTMIN+10", .number = 43 }, + { .name = "44 SIGRTMIN+11", .number = 44 }, + { .name = "45 SIGRTMIN+12", .number = 45 }, + { .name = "46 SIGRTMIN+13", .number = 46 }, + { .name = "47 SIGRTMIN+14", .number = 47 }, + { .name = "48 SIGRTMIN+15", .number = 48 }, + { .name = "49 SIGRTMIN+16", .number = 49 }, + { .name = "50 SIGRTMIN+17", .number = 50 }, + { .name = "51 SIGRTMIN+18", .number = 51 }, + { .name = "52 SIGRTMIN+19", .number = 52 }, + { .name = "53 SIGRTMIN+20", .number = 53 }, + { .name = "54 SIGRTMIN+21", .number = 54 }, + { .name = "55 SIGRTMIN+22", .number = 55 }, + { .name = "56 SIGRTMIN+23", .number = 56 }, + { .name = "57 SIGRTMIN+24", .number = 57 }, + { .name = "58 SIGRTMIN+25", .number = 58 }, + { .name = "59 SIGRTMIN+26", .number = 59 }, + { .name = "60 SIGRTMIN+27", .number = 60 }, + { .name = "61 SIGRTMIN+28", .number = 61 }, + { .name = "62 SIGRTMIN+29", .number = 62 }, + { .name = "63 SIGRTMAX", .number = 63 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + NULL +}; + +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + struct timeval bootTime, currTime; + const int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t size = sizeof(bootTime); + + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); + if (err) { + return -1; + } + gettimeofday(&currTime, NULL); + + return (int) difftime(currTime.tv_sec, bootTime.tv_sec); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + struct loadavg loadAverage; + const int mib[2] = { CTL_VM, VM_LOADAVG }; + size_t size = sizeof(loadAverage); + + int err = sysctl(mib, 2, &loadAverage, &size, NULL, 0); + if (err) { + *one = 0; + *five = 0; + *fifteen = 0; + return; + } + *one = (double) loadAverage.ldavg[0] / loadAverage.fscale; + *five = (double) loadAverage.ldavg[1] / loadAverage.fscale; + *fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale; +} + +int Platform_getMaxPid() { + // https://nxr.netbsd.org/xref/src/sys/sys/ansi.h#__pid_t + // pid is assigned as a 32bit Integer. + return INT32_MAX; +} + +double Platform_setCPUValues(Meter* this, int cpu) { + const NetBSDProcessList* npl = (const NetBSDProcessList*) this->pl; + const CPUData* cpuData = &npl->cpus[cpu]; + double total = cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod; + double totalPercent; + double* v = this->values; + + v[CPU_METER_NICE] = cpuData->nicePeriod / total * 100.0; + v[CPU_METER_NORMAL] = cpuData->userPeriod / total * 100.0; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->sysPeriod / total * 100.0; + v[CPU_METER_IRQ] = cpuData->intrPeriod / total * 100.0; + v[CPU_METER_SOFTIRQ] = 0.0; + v[CPU_METER_STEAL] = 0.0; + v[CPU_METER_GUEST] = 0.0; + v[CPU_METER_IOWAIT] = 0.0; + v[CPU_METER_FREQUENCY] = NAN; + this->curItems = 8; + totalPercent = v[0] + v[1] + v[2] + v[3]; + } else { + v[2] = cpuData->sysAllPeriod / total * 100.0; + v[3] = 0.0; // No steal nor guest on NetBSD + totalPercent = v[0] + v[1] + v[2]; + this->curItems = 4; + } + + totalPercent = CLAMP(totalPercent, 0.0, 100.0); + + v[CPU_METER_FREQUENCY] = cpuData->frequency; + v[CPU_METER_TEMPERATURE] = NAN; + + return totalPercent; +} + +void Platform_setMemoryValues(Meter* this) { + const ProcessList* pl = this->pl; + long int usedMem = pl->usedMem; + long int buffersMem = pl->buffersMem; + long int cachedMem = pl->cachedMem; + this->total = pl->totalMem; + this->values[0] = usedMem; + this->values[1] = buffersMem; + // this->values[2] = "shared memory, like tmpfs and shm" + this->values[3] = cachedMem; + // this->values[4] = "available memory" +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = NAN; +} + +char* Platform_getProcessEnv(pid_t pid) { + char errbuf[_POSIX2_LINE_MAX]; + char* env; + char** ptr; + int count; + kvm_t* kt; + struct kinfo_proc* kproc; + size_t capacity = 4096, size = 0; + + if ((kt = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) { + return NULL; + } + + if ((kproc = kvm_getprocs(kt, KERN_PROC_PID, pid, &count)) == NULL) { + (void) kvm_close(kt); + return NULL; + } + + if ((ptr = kvm_getenvv(kt, kproc, 0)) == NULL) { + (void) kvm_close(kt); + return NULL; + } + + env = xMalloc(capacity); + for (char** p = ptr; *p; p++) { + size_t len = strlen(*p) + 1; + + if (size + len > capacity) { + capacity *= 2; + env = xRealloc(env, capacity); + } + + String_safeStrncpy(env + size, *p, len); + size += len; + } + + if (size < 2 || env[size - 1] || env[size - 2]) { + if (size + 2 < capacity) + env = xRealloc(env, capacity + 2); + env[size] = 0; + env[size + 1] = 0; + } + + (void) kvm_close(kt); + return env; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + // TODO + (void)data; + return false; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + // TODO + (void)data; + return false; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + // TODO + (void)percent; + (void)isOnAC; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/Platform.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,107 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - netbsd/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +(C) 2021 Santhosh Raju +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + + +/* There are no Long Options for NetBSD as of now. */ +#define PLATFORM_LONG_OPTIONS \ + // End of list + +extern const ProcessField Platform_defaultFields[]; + +/* see /usr/include/sys/signal.h */ +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/ProcessField.h 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_NetBSDProcessField +#define HEADER_NetBSDProcessField +/* +htop - netbsd/ProcessField.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + // End of list + + +#endif /* HEADER_NetBSDProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/README.md pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/README.md --- pcp-5.3.1/vendor/github.com/htop-dev/htop/netbsd/README.md 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/netbsd/README.md 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,33 @@ +NetBSD support in htop(1) +=== + +This implementation utilizes kvm_getprocs(3), sysctl(3), etc, eliminating the +need for mount_procfs(8) with Linux compatibility enabled. + +The implementation was initially based on the OpenBSD support in htop(1). + +Notes on NetBSD curses +--- + +NetBSD is one of the last operating systems to use and maintain its own +implementation of Curses. + +htop(1) can be compiled against either ncurses or NetBSD's curses(3). +In order for NetBSD's libcurses to be used, htop(1) must be configured with +`--disable-unicode`. This is necessary because htop(1) with Unicode enabled +directly accesses ncurses's cchar_t struct, which has different contents +in NetBSD's curses. + +Versions of libcurses in NetBSD 9 and prior have no mouse support +(this is an ncurses extension). Newer versions contain no-op mouse functions +for compatibility with ncurses. + +What needs improvement +--- + +* Kernel and userspace threads are not displayed or counted - + maybe look at NetBSD top(1). +* Battery display - use envsys(4). +* Support for compiling using libcurses's Unicode support. +* Support for fstat(1) (view open files, like lsof(8) on Linux). +* Support for ktrace(1) (like strace(1) on Linux). diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/NetworkIOMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/NetworkIOMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/NetworkIOMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/NetworkIOMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,137 @@ +#include "NetworkIOMeter.h" + +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "Platform.h" +#include "Process.h" +#include "ProcessList.h" +#include "RichString.h" +#include "XUtils.h" + + +static const int NetworkIOMeter_attributes[] = { + METER_VALUE_IOREAD, + METER_VALUE_IOWRITE, +}; + +static bool hasData = false; + +static uint32_t cached_rxb_diff; +static uint32_t cached_rxp_diff; +static uint32_t cached_txb_diff; +static uint32_t cached_txp_diff; + +static void NetworkIOMeter_updateValues(Meter* this) { + const ProcessList* pl = this->pl; + static uint64_t cached_last_update = 0; + + uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update; + + /* update only every 500ms */ + if (passedTimeInMs > 500) { + static uint64_t cached_rxb_total; + static uint64_t cached_rxp_total; + static uint64_t cached_txb_total; + static uint64_t cached_txp_total; + uint64_t diff; + + cached_last_update = pl->realtimeMs; + + NetworkIOData data; + hasData = Platform_getNetworkIO(&data); + if (!hasData) { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "no data"); + return; + } + + if (data.bytesReceived > cached_rxb_total) { + diff = data.bytesReceived - cached_rxb_total; + diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */ + diff = (1000 * diff) / passedTimeInMs; /* convert to per second */ + cached_rxb_diff = (uint32_t)diff; + } else { + cached_rxb_diff = 0; + } + cached_rxb_total = data.bytesReceived; + + if (data.packetsReceived > cached_rxp_total) { + diff = data.packetsReceived - cached_rxp_total; + cached_rxp_diff = (uint32_t)diff; + } else { + cached_rxp_diff = 0; + } + cached_rxp_total = data.packetsReceived; + + if (data.bytesTransmitted > cached_txb_total) { + diff = data.bytesTransmitted - cached_txb_total; + diff /= ONE_K; /* Meter_humanUnit() expects unit in kilo */ + diff = (1000 * diff) / passedTimeInMs; /* convert to per second */ + cached_txb_diff = (uint32_t)diff; + } else { + cached_txb_diff = 0; + } + cached_txb_total = data.bytesTransmitted; + + if (data.packetsTransmitted > cached_txp_total) { + diff = data.packetsTransmitted - cached_txp_total; + cached_txp_diff = (uint32_t)diff; + } else { + cached_txp_diff = 0; + } + cached_txp_total = data.packetsTransmitted; + } + + this->values[0] = cached_rxb_diff; + this->values[1] = cached_txb_diff; + if (cached_rxb_diff + cached_txb_diff > this->total) { + this->total = cached_rxb_diff + cached_txb_diff; + } + + char bufferBytesReceived[12], bufferBytesTransmitted[12]; + Meter_humanUnit(bufferBytesReceived, cached_rxb_diff, sizeof(bufferBytesReceived)); + Meter_humanUnit(bufferBytesTransmitted, cached_txb_diff, sizeof(bufferBytesTransmitted)); + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "rx:%siB/s tx:%siB/s", bufferBytesReceived, bufferBytesTransmitted); +} + +static void NetworkIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out) { + if (!hasData) { + RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data"); + return; + } + + char buffer[64]; + int len; + + RichString_writeAscii(out, CRT_colors[METER_TEXT], "rx: "); + Meter_humanUnit(buffer, cached_rxb_diff, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], buffer); + RichString_appendAscii(out, CRT_colors[METER_VALUE_IOREAD], "iB/s"); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " tx: "); + Meter_humanUnit(buffer, cached_txb_diff, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], buffer); + RichString_appendAscii(out, CRT_colors[METER_VALUE_IOWRITE], "iB/s"); + + len = xSnprintf(buffer, sizeof(buffer), " (%u/%u packets) ", cached_rxp_diff, cached_txp_diff); + RichString_appendnAscii(out, CRT_colors[METER_TEXT], buffer, len); +} + +const MeterClass NetworkIOMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = NetworkIOMeter_display + }, + .updateValues = NetworkIOMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 2, + .total = 100.0, + .attributes = NetworkIOMeter_attributes, + .name = "NetworkIO", + .uiName = "Network IO", + .caption = "Network: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/NetworkIOMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/NetworkIOMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/NetworkIOMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/NetworkIOMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,16 @@ +#ifndef HEADER_NetworkIOMeter +#define HEADER_NetworkIOMeter + +#include "Meter.h" + + +typedef struct NetworkIOData_ { + uint64_t bytesReceived; + uint64_t packetsReceived; + uint64_t bytesTransmitted; + uint64_t packetsTransmitted; +} NetworkIOData; + +extern const MeterClass NetworkIOMeter_class; + +#endif /* HEADER_NetworkIOMeter */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/NEWS pcp-5.3.2/vendor/github.com/htop-dev/htop/NEWS --- pcp-5.3.1/vendor/github.com/htop-dev/htop/NEWS 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/NEWS 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,4 @@ + +See the commit history for news of the past. +See the bug tracker for news of the future. +Run the program for news of the present. diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Object.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Object.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Object.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Object.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,29 @@ +/* +htop - Object.c +(C) 2004-2012 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Object.h" + +#include + + +const ObjectClass Object_class = { + .extends = NULL +}; + +bool Object_isA(const Object* o, const ObjectClass* klass) { + if (!o) + return false; + + for (const ObjectClass* type = o->klass; type; type = type->extends) { + if (type == klass) { + return true; + } + } + + return false; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Object.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Object.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Object.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Object.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,59 @@ +#ifndef HEADER_Object +#define HEADER_Object +/* +htop - Object.h +(C) 2004-2012 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +#include "RichString.h" +#include "XUtils.h" // IWYU pragma: keep + + +struct Object_; +typedef struct Object_ Object; + +typedef void(*Object_Display)(const Object*, RichString*); +typedef int(*Object_Compare)(const void*, const void*); +typedef void(*Object_Delete)(Object*); + +#define Object_getClass(obj_) ((const Object*)(obj_))->klass +#define Object_setClass(obj_, class_) (((Object*)(obj_))->klass = (const ObjectClass*) (class_)) + +#define Object_delete(obj_) (assert(Object_getClass(obj_)->delete), Object_getClass(obj_)->delete((Object*)(obj_))) +#define Object_displayFn(obj_) Object_getClass(obj_)->display +#define Object_display(obj_, str_) (assert(Object_getClass(obj_)->display), Object_getClass(obj_)->display((const Object*)(obj_), str_)) +#define Object_compare(obj_, other_) (assert(Object_getClass(obj_)->compare), Object_getClass(obj_)->compare((const void*)(obj_), other_)) + +#define Class(class_) ((const ObjectClass*)(&(class_ ## _class))) + +#define AllocThis(class_) (class_*) xMalloc(sizeof(class_)); Object_setClass(this, Class(class_)) + +typedef struct ObjectClass_ { + const void* const extends; + const Object_Display display; + const Object_Delete delete; + const Object_Compare compare; +} ObjectClass; + +struct Object_ { + const ObjectClass* klass; +}; + +typedef union { + int i; + void* v; +} Arg; + +extern const ObjectClass Object_class; + +bool Object_isA(const Object* o, const ObjectClass* klass); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,255 @@ +/* +htop - OpenBSDProcess.c +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "openbsd/OpenBSDProcess.h" + +#include + +#include "CRT.h" +#include "Process.h" +#include "RichString.h" +#include "XUtils.h" + + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { + .name = "", + .title = NULL, + .description = NULL, + .flags = 0, + }, + [PID] = { + .name = "PID", + .title = "PID", + .description = "Process/thread ID", + .flags = 0, + .pidColumn = true, + }, + [COMM] = { + .name = "Command", + .title = "Command ", + .description = "Command line", + .flags = 0, + }, + [STATE] = { + .name = "STATE", + .title = "S ", + .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging)", + .flags = 0, + }, + [PPID] = { + .name = "PPID", + .title = "PPID", + .description = "Parent process ID", + .flags = 0, + .pidColumn = true, + }, + [PGRP] = { + .name = "PGRP", + .title = "PGRP", + .description = "Process group ID", + .flags = 0, + .pidColumn = true, + }, + [SESSION] = { + .name = "SESSION", + .title = "SESN", + .description = "Process's session ID", + .flags = 0, + .pidColumn = true, + }, + [TTY] = { + .name = "TTY", + .title = "TTY ", + .description = "Controlling terminal", + .flags = 0, + }, + [TPGID] = { + .name = "TPGID", + .title = "TPGID", + .description = "Process ID of the fg process group of the controlling terminal", + .flags = 0, + .pidColumn = true, + }, + [MINFLT] = { + .name = "MINFLT", + .title = " MINFLT ", + .description = "Number of minor faults which have not required loading a memory page from disk", + .flags = 0, + .defaultSortDesc = true, + }, + [MAJFLT] = { + .name = "MAJFLT", + .title = " MAJFLT ", + .description = "Number of major faults which have required loading a memory page from disk", + .flags = 0, + .defaultSortDesc = true, + }, + [PRIORITY] = { + .name = "PRIORITY", + .title = "PRI ", + .description = "Kernel's internal priority for the process", + .flags = 0, + }, + [NICE] = { + .name = "NICE", + .title = " NI ", + .description = "Nice value (the higher the value, the more it lets other processes take priority)", + .flags = 0, + }, + [STARTTIME] = { + .name = "STARTTIME", + .title = "START ", + .description = "Time the process was started", + .flags = 0, + }, + [ELAPSED] = { + .name = "ELAPSED", + .title = "ELAPSED ", + .description = "Time since the process was started", + .flags = 0, + }, + [PROCESSOR] = { + .name = "PROCESSOR", + .title = "CPU ", + .description = "Id of the CPU the process last executed on", + .flags = 0, + }, + [M_VIRT] = { + .name = "M_VIRT", + .title = " VIRT ", + .description = "Total program size in virtual memory", + .flags = 0, + .defaultSortDesc = true, + }, + [M_RESIDENT] = { + .name = "M_RESIDENT", + .title = " RES ", + .description = "Resident set size, size of the text and data sections, plus stack usage", + .flags = 0, + .defaultSortDesc = true, + }, + [ST_UID] = { + .name = "ST_UID", + .title = " UID ", + .description = "User ID of the process owner", + .flags = 0, + }, + [PERCENT_CPU] = { + .name = "PERCENT_CPU", + .title = "CPU% ", + .description = "Percentage of the CPU time the process used in the last sampling", + .flags = 0, + .defaultSortDesc = true, + }, + [PERCENT_NORM_CPU] = { + .name = "PERCENT_NORM_CPU", + .title = "NCPU%", + .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", + .flags = 0, + .defaultSortDesc = true, + }, + [PERCENT_MEM] = { + .name = "PERCENT_MEM", + .title = "MEM% ", + .description = "Percentage of the memory the process is using, based on resident memory size", + .flags = 0, + .defaultSortDesc = true, + }, + [USER] = { + .name = "USER", + .title = "USER ", + .description = "Username of the process owner (or user ID if name cannot be determined)", + .flags = 0, + }, + [TIME] = { + .name = "TIME", + .title = " TIME+ ", + .description = "Total time the process has spent in user and system time", + .flags = 0, + .defaultSortDesc = true, + }, + [NLWP] = { + .name = "NLWP", + .title = "NLWP ", + .description = "Number of threads in the process", + .flags = 0, + }, + [TGID] = { + .name = "TGID", + .title = "TGID", + .description = "Thread group ID (i.e. process ID)", + .flags = 0, + .pidColumn = true, + }, + [PROC_COMM] = { + .name = "COMM", + .title = "COMM ", + .description = "comm string of the process", + .flags = 0, + }, + [CWD] = { + .name = "CWD", + .title = "CWD ", + .description = "The current working directory of the process", + .flags = PROCESS_FLAG_CWD, + }, + +}; + +Process* OpenBSDProcess_new(const Settings* settings) { + OpenBSDProcess* this = xCalloc(sizeof(OpenBSDProcess), 1); + Object_setClass(this, Class(OpenBSDProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + OpenBSDProcess* this = (OpenBSDProcess*) cast; + Process_done((Process*)cast); + free(this); +} + +static void OpenBSDProcess_writeField(const Process* this, RichString* str, ProcessField field) { + //const OpenBSDProcess* op = (const OpenBSDProcess*) this; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + //int n = sizeof(buffer) - 1; + switch (field) { + // add OpenBSD-specific fields here + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int OpenBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const OpenBSDProcess* p1 = (const OpenBSDProcess*)v1; + const OpenBSDProcess* p2 = (const OpenBSDProcess*)v2; + + // remove if actually used + (void)p1; (void)p2; + + switch (key) { + // add OpenBSD-specific fields here + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass OpenBSDProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = OpenBSDProcess_writeField, + .compareByKey = OpenBSDProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,33 @@ +#ifndef HEADER_OpenBSDProcess +#define HEADER_OpenBSDProcess +/* +htop - OpenBSDProcess.h +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Object.h" +#include "Process.h" +#include "Settings.h" + + +typedef struct OpenBSDProcess_ { + Process super; + + /* 'Kernel virtual addr of u-area' to detect main threads */ + uint64_t addr; +} OpenBSDProcess; + +extern const ProcessClass OpenBSDProcess_class; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* OpenBSDProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.c 2021-07-30 04:05:08.000000000 +0000 @@ -0,0 +1,448 @@ +/* +htop - OpenBSDProcessList.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "openbsd/OpenBSDProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "Process.h" +#include "ProcessList.h" +#include "Settings.h" +#include "XUtils.h" +#include "openbsd/OpenBSDProcess.h" + + +static long fscale; +static int pageSize; +static int pageSizeKB; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + const int nmib[] = { CTL_HW, HW_NCPU }; + const int mib[] = { CTL_HW, HW_NCPUONLINE }; + const int fmib[] = { CTL_KERN, KERN_FSCALE }; + int r; + unsigned int cpu_index_c = 0; + unsigned int ncpu; + size_t size; + char errbuf[_POSIX2_LINE_MAX]; + + OpenBSDProcessList* opl = xCalloc(1, sizeof(OpenBSDProcessList)); + ProcessList* pl = (ProcessList*) opl; + ProcessList_init(pl, Class(OpenBSDProcess), usersTable, dynamicMeters, pidMatchList, userId); + + size = sizeof(pl->cpuCount); + r = sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); + if (r < 0 || pl->cpuCount < 1) { + pl->cpuCount = 1; + } + opl->cpus = xCalloc(pl->cpuCount + 1, sizeof(CPUData)); + + size = sizeof(int); + r = sysctl(nmib, 2, &ncpu, &size, NULL, 0); + if (r < 0) { + ncpu = pl->cpuCount; + } + + size = sizeof(fscale); + if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) { + CRT_fatalError("fscale sysctl call failed"); + } + + if ((pageSize = sysconf(_SC_PAGESIZE)) == -1) + CRT_fatalError("pagesize sysconf call failed"); + pageSizeKB = pageSize / ONE_K; + + for (unsigned int i = 0; i <= pl->cpuCount; i++) { + CPUData* d = opl->cpus + i; + d->totalTime = 1; + d->totalPeriod = 1; + } + + opl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); + if (opl->kd == NULL) { + CRT_fatalError("kvm_openfiles() failed"); + } + + opl->cpuSpeed = -1; + + for (unsigned int i = 0; i < ncpu; i++) { + const int ncmib[] = { CTL_KERN, KERN_CPUSTATS, i }; + struct cpustats cpu_stats; + + size = sizeof(cpu_stats); + if (sysctl(ncmib, 3, &cpu_stats, &size, NULL, 0) < 0) { + CRT_fatalError("ncmib sysctl call failed"); + } + if (cpu_stats.cs_flags & CPUSTATS_ONLINE) { + opl->cpus[cpu_index_c].cpuIndex = i; + cpu_index_c++; + } + + if (cpu_index_c == pl->cpuCount) + break; + } + + return pl; +} + +void ProcessList_delete(ProcessList* this) { + OpenBSDProcessList* opl = (OpenBSDProcessList*) this; + + if (opl->kd) { + kvm_close(opl->kd); + } + + free(opl->cpus); + + ProcessList_done(this); + free(this); +} + +static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { + const int uvmexp_mib[] = { CTL_VM, VM_UVMEXP }; + struct uvmexp uvmexp; + size_t size_uvmexp = sizeof(uvmexp); + + if (sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0) < 0) { + CRT_fatalError("uvmexp sysctl call failed"); + } + + pl->totalMem = uvmexp.npages * pageSizeKB; + pl->usedMem = (uvmexp.npages - uvmexp.free - uvmexp.paging) * pageSizeKB; + + // Taken from OpenBSD systat/iostat.c, top/machine.c and uvm_sysctl(9) + const int bcache_mib[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT }; + struct bcachestats bcstats; + size_t size_bcstats = sizeof(bcstats); + + if (sysctl(bcache_mib, 3, &bcstats, &size_bcstats, NULL, 0) < 0) { + CRT_fatalError("cannot get vfs.bcachestat"); + } + + pl->cachedMem = bcstats.numbufpages * pageSizeKB; + + /* + * Copyright (c) 1994 Thorsten Lockert + * All rights reserved. + * + * Taken almost directly from OpenBSD's top(1) + * + * Originally released under a BSD-3 license + * Modified through htop developers applying GPL-2 + */ + int nswap = swapctl(SWAP_NSWAP, 0, 0); + if (nswap > 0) { + struct swapent swdev[nswap]; + int rnswap = swapctl(SWAP_STATS, swdev, nswap); + + /* Total things up */ + unsigned long long int total = 0, used = 0; + for (int i = 0; i < rnswap; i++) { + if (swdev[i].se_flags & SWF_ENABLE) { + used += (swdev[i].se_inuse / (1024 / DEV_BSIZE)); + total += (swdev[i].se_nblks / (1024 / DEV_BSIZE)); + } + } + + pl->totalSwap = total; + pl->usedSwap = used; + } else { + pl->totalSwap = pl->usedSwap = 0; + } +} + +static void OpenBSDProcessList_updateCwd(const struct kinfo_proc* kproc, Process* proc) { + const int mib[] = { CTL_KERN, KERN_PROC_CWD, kproc->ki_pid }; + char buffer[2048]; + size_t size = sizeof(buffer); + if (sysctl(mib, 3, buffer, &size, NULL, 0) != 0) { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + /* Kernel threads return an empty buffer */ + if (buffer[0] == '\0') { + free(proc->procCwd); + proc->procCwd = NULL; + return; + } + + free_and_xStrdup(&proc->procCwd, buffer); +} + +static void OpenBSDProcessList_updateProcessName(kvm_t* kd, const struct kinfo_proc* kproc, Process* proc) { + Process_updateComm(proc, kproc->p_comm); + + /* + * Like OpenBSD's top(1), we try to fall back to the command name + * (argv[0]) if we fail to construct the full command. + */ + char** arg = kvm_getargv(kd, kproc, 500); + if (arg == NULL || *arg == NULL) { + Process_updateCmdline(proc, kproc->p_comm, 0, strlen(kproc->p_comm)); + return; + } + + size_t len = 0; + for (int i = 0; arg[i] != NULL; i++) { + len += strlen(arg[i]) + 1; /* room for arg and trailing space or NUL */ + } + + /* don't use xMalloc here - we want to handle huge argv's gracefully */ + char* s; + if ((s = malloc(len)) == NULL) { + Process_updateCmdline(proc, kproc->p_comm, 0, strlen(kproc->p_comm)); + return; + } + + *s = '\0'; + + int start = 0; + int end = 0; + for (int i = 0; arg[i] != NULL; i++) { + size_t n = strlcat(s, arg[i], len); + if (i == 0) { + end = MINIMUM(n, len - 1); + /* check if cmdline ended earlier, e.g 'kdeinit5: Running...' */ + for (int j = end; j > 0; j--) { + if (arg[0][j] == ' ' && arg[0][j - 1] != '\\') { + end = (arg[0][j - 1] == ':') ? (j - 1) : j; + } + } + } + /* the trailing space should get truncated anyway */ + strlcat(s, " ", len); + } + + Process_updateCmdline(proc, s, start, end); +} + +/* + * Taken from OpenBSD's ps(1). + */ +static double getpcpu(const struct kinfo_proc* kp) { + if (fscale == 0) + return 0.0; + + return 100.0 * (double)kp->p_pctcpu / fscale; +} + +static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) { + const Settings* settings = this->super.settings; + const bool hideKernelThreads = settings->hideKernelThreads; + const bool hideUserlandThreads = settings->hideUserlandThreads; + int count = 0; + + const struct kinfo_proc* kprocs = kvm_getprocs(this->kd, KERN_PROC_KTHREAD | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &count); + + for (int i = 0; i < count; i++) { + const struct kinfo_proc* kproc = &kprocs[i]; + + /* Ignore main threads */ + if (kproc->p_tid != -1) { + Process* containingProcess = ProcessList_findProcess(&this->super, kproc->p_pid); + if (containingProcess) { + if (((OpenBSDProcess*)containingProcess)->addr == kproc->p_addr) + continue; + + containingProcess->nlwp++; + } + } + + bool preExisting = false; + Process* proc = ProcessList_getProcess(&this->super, (kproc->p_tid == -1) ? kproc->p_pid : kproc->p_tid, &preExisting, OpenBSDProcess_new); + OpenBSDProcess* fp = (OpenBSDProcess*) proc; + + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc))); + + if (!preExisting) { + proc->ppid = kproc->p_ppid; + proc->tpgid = kproc->p_tpgid; + proc->tgid = kproc->p_pid; + proc->session = kproc->p_sid; + proc->pgrp = kproc->p__pgid; + proc->isKernelThread = proc->pgrp == 0; + proc->isUserlandThread = kproc->p_tid != -1; + proc->starttime_ctime = kproc->p_ustart_sec; + Process_fillStarttimeBuffer(proc); + ProcessList_add(&this->super, proc); + + OpenBSDProcessList_updateProcessName(this->kd, kproc, proc); + + if (settings->flags & PROCESS_FLAG_CWD) { + OpenBSDProcessList_updateCwd(kproc, proc); + } + + proc->tty_nr = kproc->p_tdev; + const char* name = ((dev_t)kproc->p_tdev != NODEV) ? devname(kproc->p_tdev, S_IFCHR) : NULL; + if (!name || String_eq(name, "??")) { + free(proc->tty_name); + proc->tty_name = NULL; + } else { + free_and_xStrdup(&proc->tty_name, name); + } + } else { + if (settings->updateProcessNames) { + OpenBSDProcessList_updateProcessName(this->kd, kproc, proc); + } + } + + fp->addr = kproc->p_addr; + proc->m_virt = kproc->p_vm_dsize * pageSizeKB; + proc->m_resident = kproc->p_vm_rssize * pageSizeKB; + proc->percent_mem = proc->m_resident / (float)this->super.totalMem * 100.0F; + proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0F, this->super.cpuCount * 100.0F); + proc->nice = kproc->p_nice - 20; + proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000)); + proc->priority = kproc->p_priority - PZERO; + proc->processor = kproc->p_cpuid; + proc->minflt = kproc->p_uru_minflt; + proc->majflt = kproc->p_uru_majflt; + proc->nlwp = 1; + + if (proc->st_uid != kproc->p_uid) { + proc->st_uid = kproc->p_uid; + proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid); + } + + switch (kproc->p_stat) { + case SIDL: proc->state = 'I'; break; + case SRUN: proc->state = 'P'; break; + case SSLEEP: proc->state = 'S'; break; + case SSTOP: proc->state = 'T'; break; + case SZOMB: proc->state = 'Z'; break; + case SDEAD: proc->state = 'D'; break; + case SONPROC: proc->state = 'R'; break; + default: proc->state = '?'; + } + + if (Process_isKernelThread(proc)) { + this->super.kernelThreads++; + } else if (Process_isUserlandThread(proc)) { + this->super.userlandThreads++; + } + + this->super.totalTasks++; + if (proc->state == 'R') { + this->super.runningTasks++; + } + proc->updated = true; + } +} + +static void getKernelCPUTimes(int cpuId, u_int64_t* times) { + const int mib[] = { CTL_KERN, KERN_CPTIME2, cpuId }; + size_t length = sizeof(*times) * CPUSTATES; + if (sysctl(mib, 3, times, &length, NULL, 0) == -1 || length != sizeof(*times) * CPUSTATES) { + CRT_fatalError("sysctl kern.cp_time2 failed"); + } +} + +static void kernelCPUTimesToHtop(const u_int64_t* times, CPUData* cpu) { + unsigned long long totalTime = 0; + for (int i = 0; i < CPUSTATES; i++) { + totalTime += times[i]; + } + + unsigned long long sysAllTime = times[CP_INTR] + times[CP_SYS]; + + // XXX Not sure if CP_SPIN should be added to sysAllTime. + // See https://github.com/openbsd/src/commit/531d8034253fb82282f0f353c086e9ad827e031c + #ifdef CP_SPIN + sysAllTime += times[CP_SPIN]; + #endif + + cpu->totalPeriod = saturatingSub(totalTime, cpu->totalTime); + cpu->userPeriod = saturatingSub(times[CP_USER], cpu->userTime); + cpu->nicePeriod = saturatingSub(times[CP_NICE], cpu->niceTime); + cpu->sysPeriod = saturatingSub(times[CP_SYS], cpu->sysTime); + cpu->sysAllPeriod = saturatingSub(sysAllTime, cpu->sysAllTime); + #ifdef CP_SPIN + cpu->spinPeriod = saturatingSub(times[CP_SPIN], cpu->spinTime); + #endif + cpu->intrPeriod = saturatingSub(times[CP_INTR], cpu->intrTime); + cpu->idlePeriod = saturatingSub(times[CP_IDLE], cpu->idleTime); + + cpu->totalTime = totalTime; + cpu->userTime = times[CP_USER]; + cpu->niceTime = times[CP_NICE]; + cpu->sysTime = times[CP_SYS]; + cpu->sysAllTime = sysAllTime; + #ifdef CP_SPIN + cpu->spinTime = times[CP_SPIN]; + #endif + cpu->intrTime = times[CP_INTR]; + cpu->idleTime = times[CP_IDLE]; +} + +static void OpenBSDProcessList_scanCPUTime(OpenBSDProcessList* this) { + u_int64_t kernelTimes[CPUSTATES] = {0}; + u_int64_t avg[CPUSTATES] = {0}; + + for (unsigned int i = 0; i < this->super.cpuCount; i++) { + getKernelCPUTimes(this->cpus[i].cpuIndex, kernelTimes); + CPUData* cpu = this->cpus + i + 1; + kernelCPUTimesToHtop(kernelTimes, cpu); + + avg[CP_USER] += cpu->userTime; + avg[CP_NICE] += cpu->niceTime; + avg[CP_SYS] += cpu->sysTime; + #ifdef CP_SPIN + avg[CP_SPIN] += cpu->spinTime; + #endif + avg[CP_INTR] += cpu->intrTime; + avg[CP_IDLE] += cpu->idleTime; + } + + for (int i = 0; i < CPUSTATES; i++) { + avg[i] /= this->super.cpuCount; + } + + kernelCPUTimesToHtop(avg, this->cpus); + + { + const int mib[] = { CTL_HW, HW_CPUSPEED }; + int cpuSpeed; + size_t size = sizeof(cpuSpeed); + if (sysctl(mib, 2, &cpuSpeed, &size, NULL, 0) == -1) { + this->cpuSpeed = -1; + } else { + this->cpuSpeed = cpuSpeed; + } + } +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + OpenBSDProcessList* opl = (OpenBSDProcessList*) super; + + OpenBSDProcessList_scanMemoryInfo(super); + OpenBSDProcessList_scanCPUTime(opl); + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + OpenBSDProcessList_scanProcs(opl); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/OpenBSDProcessList.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,58 @@ +#ifndef HEADER_OpenBSDProcessList +#define HEADER_OpenBSDProcessList +/* +htop - OpenBSDProcessList.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" + + +typedef struct CPUData_ { + unsigned long long int totalTime; + unsigned long long int userTime; + unsigned long long int niceTime; + unsigned long long int sysTime; + unsigned long long int sysAllTime; + unsigned long long int spinTime; + unsigned long long int intrTime; + unsigned long long int idleTime; + + unsigned long long int totalPeriod; + unsigned long long int userPeriod; + unsigned long long int nicePeriod; + unsigned long long int sysPeriod; + unsigned long long int sysAllPeriod; + unsigned long long int spinPeriod; + unsigned long long int intrPeriod; + unsigned long long int idlePeriod; + + int cpuIndex; +} CPUData; + +typedef struct OpenBSDProcessList_ { + ProcessList super; + kvm_t* kd; + + CPUData* cpus; + int cpuSpeed; + +} OpenBSDProcessList; + + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/Platform.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,352 @@ +/* +htop - openbsd/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "openbsd/Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include // needs to be included before for 'struct sigaltstack' +#include +#include +#include +#include +#include +#include +#include + +#include "CPUMeter.h" +#include "ClockMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MemoryMeter.h" +#include "Meter.h" +#include "ProcessList.h" +#include "Settings.h" +#include "SignalsPanel.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "XUtils.h" +#include "openbsd/OpenBSDProcess.h" +#include "openbsd/OpenBSDProcessList.h" + + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +/* + * See /usr/include/sys/signal.h + */ +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 6 SIGIOT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGURG", .number = 16 }, + { .name = "17 SIGSTOP", .number = 17 }, + { .name = "18 SIGTSTP", .number = 18 }, + { .name = "19 SIGCONT", .number = 19 }, + { .name = "20 SIGCHLD", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGIO", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGINFO", .number = 29 }, + { .name = "30 SIGUSR1", .number = 30 }, + { .name = "31 SIGUSR2", .number = 31 }, + { .name = "32 SIGTHR", .number = 32 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + NULL +}; + +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + struct timeval bootTime, currTime; + const int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t size = sizeof(bootTime); + + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); + if (err) { + return -1; + } + gettimeofday(&currTime, NULL); + + return (int) difftime(currTime.tv_sec, bootTime.tv_sec); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + struct loadavg loadAverage; + const int mib[2] = { CTL_VM, VM_LOADAVG }; + size_t size = sizeof(loadAverage); + + int err = sysctl(mib, 2, &loadAverage, &size, NULL, 0); + if (err) { + *one = 0; + *five = 0; + *fifteen = 0; + return; + } + *one = (double) loadAverage.ldavg[0] / loadAverage.fscale; + *five = (double) loadAverage.ldavg[1] / loadAverage.fscale; + *fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale; +} + +int Platform_getMaxPid() { + return 2 * THREAD_PID_OFFSET; +} + +double Platform_setCPUValues(Meter* this, unsigned int cpu) { + const OpenBSDProcessList* pl = (const OpenBSDProcessList*) this->pl; + const CPUData* cpuData = &(pl->cpus[cpu]); + double total = cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod; + double totalPercent; + double* v = this->values; + + v[CPU_METER_NICE] = cpuData->nicePeriod / total * 100.0; + v[CPU_METER_NORMAL] = cpuData->userPeriod / total * 100.0; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->sysPeriod / total * 100.0; + v[CPU_METER_IRQ] = cpuData->intrPeriod / total * 100.0; + v[CPU_METER_SOFTIRQ] = 0.0; + v[CPU_METER_STEAL] = 0.0; + v[CPU_METER_GUEST] = 0.0; + v[CPU_METER_IOWAIT] = 0.0; + v[CPU_METER_FREQUENCY] = NAN; + this->curItems = 8; + totalPercent = v[0] + v[1] + v[2] + v[3]; + } else { + v[2] = cpuData->sysAllPeriod / total * 100.0; + v[3] = 0.0; // No steal nor guest on OpenBSD + totalPercent = v[0] + v[1] + v[2]; + this->curItems = 4; + } + + totalPercent = CLAMP(totalPercent, 0.0, 100.0); + + v[CPU_METER_TEMPERATURE] = NAN; + + v[CPU_METER_FREQUENCY] = (pl->cpuSpeed != -1) ? pl->cpuSpeed : NAN; + + return totalPercent; +} + +void Platform_setMemoryValues(Meter* this) { + const ProcessList* pl = this->pl; + long int usedMem = pl->usedMem; + long int buffersMem = pl->buffersMem; + long int cachedMem = pl->cachedMem; + usedMem -= buffersMem + cachedMem; + this->total = pl->totalMem; + this->values[0] = usedMem; + this->values[1] = buffersMem; + // this->values[2] = "shared memory, like tmpfs and shm" + this->values[3] = cachedMem; + // this->values[4] = "available memory" +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = NAN; +} + +char* Platform_getProcessEnv(pid_t pid) { + char errbuf[_POSIX2_LINE_MAX]; + char* env; + char** ptr; + int count; + kvm_t* kt; + struct kinfo_proc* kproc; + size_t capacity = 4096, size = 0; + + if ((kt = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) { + return NULL; + } + + if ((kproc = kvm_getprocs(kt, KERN_PROC_PID, pid, + sizeof(struct kinfo_proc), &count)) == NULL) { + (void) kvm_close(kt); + return NULL; + } + + if ((ptr = kvm_getenvv(kt, kproc, 0)) == NULL) { + (void) kvm_close(kt); + return NULL; + } + + env = xMalloc(capacity); + for (char** p = ptr; *p; p++) { + size_t len = strlen(*p) + 1; + + if (size + len > capacity) { + capacity *= 2; + env = xRealloc(env, capacity); + } + + strlcpy(env + size, *p, len); + size += len; + } + + if (size < 2 || env[size - 1] || env[size - 2]) { + if (size + 2 < capacity) + env = xRealloc(env, capacity + 2); + env[size] = 0; + env[size + 1] = 0; + } + + (void) kvm_close(kt); + return env; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + // TODO + (void)data; + return false; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + // TODO + (void)data; + return false; +} + +static bool findDevice(const char* name, int* mib, struct sensordev* snsrdev, size_t* sdlen) { + for (int devn = 0;; devn++) { + mib[2] = devn; + if (sysctl(mib, 3, snsrdev, sdlen, NULL, 0) == -1) { + if (errno == ENXIO) + continue; + if (errno == ENOENT) + return false; + } + if (String_eq(name, snsrdev->xname)) { + return true; + } + } +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + int mib[] = {CTL_HW, HW_SENSORS, 0, 0, 0}; + struct sensor s; + size_t slen = sizeof(struct sensor); + struct sensordev snsrdev; + size_t sdlen = sizeof(struct sensordev); + + bool found = findDevice("acpibat0", mib, &snsrdev, &sdlen); + + *percent = NAN; + if (found) { + /* last full capacity */ + mib[3] = 7; + mib[4] = 0; + double last_full_capacity = 0; + if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) + last_full_capacity = s.value; + if (last_full_capacity > 0) { + /* remaining capacity */ + mib[3] = 7; + mib[4] = 3; + if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) { + double charge = s.value; + *percent = 100 * (charge / last_full_capacity); + if (charge >= last_full_capacity) { + *percent = 100; + } + } + } + } + + found = findDevice("acpiac0", mib, &snsrdev, &sdlen); + + *isOnAC = AC_ERROR; + if (found) { + mib[3] = 9; + mib[4] = 0; + if (sysctl(mib, 5, &s, &slen, NULL, 0) != -1) + *isOnAC = s.value; + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/Platform.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,100 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - openbsd/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + + +extern const ProcessField Platform_defaultFields[]; + +/* see /usr/include/sys/signal.h */ +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, unsigned int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +#define PLATFORM_LONG_OPTIONS + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/openbsd/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/openbsd/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_OpenBSDProcessField +#define HEADER_OpenBSDProcessField +/* +htop - openbsd/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + // End of list + + +#endif /* HEADER_OpenBSDProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/OpenFilesScreen.c pcp-5.3.2/vendor/github.com/htop-dev/htop/OpenFilesScreen.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/OpenFilesScreen.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/OpenFilesScreen.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,247 @@ +/* +htop - OpenFilesScreen.c +(C) 2005-2006 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "OpenFilesScreen.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "Macros.h" +#include "Panel.h" +#include "ProvideCurses.h" +#include "Vector.h" +#include "XUtils.h" + + +typedef struct OpenFiles_Data_ { + char* data[7]; +} OpenFiles_Data; + +typedef struct OpenFiles_ProcessData_ { + OpenFiles_Data data; + int error; + struct OpenFiles_FileData_* files; +} OpenFiles_ProcessData; + +typedef struct OpenFiles_FileData_ { + OpenFiles_Data data; + struct OpenFiles_FileData_* next; +} OpenFiles_FileData; + +static size_t getIndexForType(char type) { + switch (type) { + case 'f': + return 0; + case 'a': + return 1; + case 'D': + return 2; + case 'i': + return 3; + case 'n': + return 4; + case 's': + return 5; + case 't': + return 6; + } + + /* should never reach here */ + abort(); +} + +static const char* getDataForType(const OpenFiles_Data* data, char type) { + size_t index = getIndexForType(type); + return data->data[index] ? data->data[index] : ""; +} + +OpenFilesScreen* OpenFilesScreen_new(const Process* process) { + OpenFilesScreen* this = xMalloc(sizeof(OpenFilesScreen)); + Object_setClass(this, Class(OpenFilesScreen)); + if (Process_isThread(process)) { + this->pid = process->tgid; + } else { + this->pid = process->pid; + } + return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE MODE DEVICE SIZE NODE NAME"); +} + +void OpenFilesScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); +} + +static void OpenFilesScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, Process_getCommand(this->process)); +} + +static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { + OpenFiles_ProcessData* pdata = xCalloc(1, sizeof(OpenFiles_ProcessData)); + + int fdpair[2] = {0, 0}; + if (pipe(fdpair) == -1) { + pdata->error = 1; + return pdata; + } + + pid_t child = fork(); + if (child == -1) { + close(fdpair[1]); + close(fdpair[0]); + pdata->error = 1; + return pdata; + } + + if (child == 0) { + close(fdpair[0]); + dup2(fdpair[1], STDOUT_FILENO); + close(fdpair[1]); + int fdnull = open("/dev/null", O_WRONLY); + if (fdnull < 0) { + exit(1); + } + + dup2(fdnull, STDERR_FILENO); + close(fdnull); + char buffer[32] = {0}; + xSnprintf(buffer, sizeof(buffer), "%d", pid); + execlp("lsof", "lsof", "-P", "-p", buffer, "-F", NULL); + exit(127); + } + close(fdpair[1]); + + OpenFiles_Data* item = &(pdata->data); + OpenFiles_FileData* fdata = NULL; + + FILE* fd = fdopen(fdpair[0], "r"); + if (!fd) { + pdata->error = 1; + return pdata; + } + for (;;) { + char* line = String_readLine(fd); + if (!line) { + break; + } + + unsigned char cmd = line[0]; + switch (cmd) { + case 'f': /* file descriptor */ + { + OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData)); + if (fdata == NULL) { + pdata->files = nextFile; + } else { + fdata->next = nextFile; + } + fdata = nextFile; + item = &(fdata->data); + } /* FALLTHRU */ + case 'a': /* file access mode */ + case 'D': /* file's major/minor device number */ + case 'i': /* file's inode number */ + case 'n': /* file name, comment, Internet address */ + case 's': /* file's size */ + case 't': /* file's type */ + { + size_t index = getIndexForType(cmd); + free(item->data[index]); + item->data[index] = xStrdup(line + 1); + break; + } + case 'c': /* process command name */ + case 'd': /* file's device character code */ + case 'g': /* process group ID */ + case 'G': /* file flags */ + case 'k': /* link count */ + case 'l': /* file's lock status */ + case 'L': /* process login name */ + case 'o': /* file's offset */ + case 'p': /* process ID */ + case 'P': /* protocol name */ + case 'R': /* parent process ID */ + case 'T': /* TCP/TPI information, identified by prefixes */ + case 'u': /* process user ID */ + /* ignore */ + break; + } + free(line); + } + fclose(fd); + + int wstatus; + if (waitpid(child, &wstatus, 0) == -1) { + pdata->error = 1; + return pdata; + } + + if (!WIFEXITED(wstatus)) { + pdata->error = 1; + } else { + pdata->error = WEXITSTATUS(wstatus); + } + + return pdata; +} + +static void OpenFiles_Data_clear(OpenFiles_Data* data) { + for (size_t i = 0; i < ARRAYSIZE(data->data); i++) + free(data->data[i]); +} + +static void OpenFilesScreen_scan(InfoScreen* this) { + Panel* panel = this->display; + int idx = Panel_getSelectedIndex(panel); + Panel_prune(panel); + OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(((OpenFilesScreen*)this)->pid); + if (pdata->error == 127) { + InfoScreen_addLine(this, "Could not execute 'lsof'. Please make sure it is available in your $PATH."); + } else if (pdata->error == 1) { + InfoScreen_addLine(this, "Failed listing open files."); + } else { + OpenFiles_FileData* fdata = pdata->files; + while (fdata) { + OpenFiles_Data* data = &fdata->data; + size_t lenN = strlen(getDataForType(data, 'n')); + size_t sizeEntry = 5 + 7 + 4 + 10 + 10 + 10 + lenN + 7 /*spaces*/ + 1 /*null*/; + char entry[sizeEntry]; + xSnprintf(entry, sizeof(entry), "%5.5s %-7.7s %-4.4s %-10.10s %10.10s %10.10s %s", + getDataForType(data, 'f'), + getDataForType(data, 't'), + getDataForType(data, 'a'), + getDataForType(data, 'D'), + getDataForType(data, 's'), + getDataForType(data, 'i'), + getDataForType(data, 'n')); + InfoScreen_addLine(this, entry); + OpenFiles_Data_clear(data); + OpenFiles_FileData* old = fdata; + fdata = fdata->next; + free(old); + } + OpenFiles_Data_clear(&pdata->data); + } + free(pdata); + Vector_insertionSort(this->lines); + Vector_insertionSort(panel->items); + Panel_setSelected(panel, idx); +} + +const InfoScreenClass OpenFilesScreen_class = { + .super = { + .extends = Class(Object), + .delete = OpenFilesScreen_delete + }, + .scan = OpenFilesScreen_scan, + .draw = OpenFilesScreen_draw +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/OpenFilesScreen.h pcp-5.3.2/vendor/github.com/htop-dev/htop/OpenFilesScreen.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/OpenFilesScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/OpenFilesScreen.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,28 @@ +#ifndef HEADER_OpenFilesScreen +#define HEADER_OpenFilesScreen +/* +htop - OpenFilesScreen.h +(C) 2005-2006 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "InfoScreen.h" +#include "Object.h" +#include "Process.h" + + +typedef struct OpenFilesScreen_ { + InfoScreen super; + pid_t pid; +} OpenFilesScreen; + +extern const InfoScreenClass OpenFilesScreen_class; + +OpenFilesScreen* OpenFilesScreen_new(const Process* process); + +void OpenFilesScreen_delete(Object* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/OptionItem.c pcp-5.3.2/vendor/github.com/htop-dev/htop/OptionItem.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/OptionItem.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/OptionItem.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,191 @@ +/* +htop - OptionItem.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "OptionItem.h" + +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "RichString.h" +#include "XUtils.h" + + +static void OptionItem_delete(Object* cast) { + OptionItem* this = (OptionItem*)cast; + assert (this != NULL); + + free(this->text); + free(this); +} + +static void CheckItem_display(const Object* cast, RichString* out) { + const CheckItem* this = (const CheckItem*)cast; + assert (this != NULL); + + RichString_writeAscii(out, CRT_colors[CHECK_BOX], "["); + if (CheckItem_get(this)) { + RichString_appendAscii(out, CRT_colors[CHECK_MARK], "x"); + } else { + RichString_appendAscii(out, CRT_colors[CHECK_MARK], " "); + } + RichString_appendAscii(out, CRT_colors[CHECK_BOX], "] "); + RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text); +} + +static void NumberItem_display(const Object* cast, RichString* out) { + const NumberItem* this = (const NumberItem*)cast; + assert (this != NULL); + + char buffer[12]; + RichString_writeAscii(out, CRT_colors[CHECK_BOX], "["); + int written; + if (this->scale < 0) { + written = xSnprintf(buffer, sizeof(buffer), "%.*f", -this->scale, pow(10, this->scale) * NumberItem_get(this)); + } else if (this->scale > 0) { + written = xSnprintf(buffer, sizeof(buffer), "%d", (int) (pow(10, this->scale) * NumberItem_get(this))); + } else { + written = xSnprintf(buffer, sizeof(buffer), "%d", NumberItem_get(this)); + } + RichString_appendnAscii(out, CRT_colors[CHECK_MARK], buffer, written); + RichString_appendAscii(out, CRT_colors[CHECK_BOX], "]"); + for (int i = written; i < 5; i++) { + RichString_appendAscii(out, CRT_colors[CHECK_BOX], " "); + } + RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text); +} + +const OptionItemClass OptionItem_class = { + .super = { + .extends = Class(Object), + .delete = OptionItem_delete + } +}; + +const OptionItemClass CheckItem_class = { + .super = { + .extends = Class(OptionItem), + .delete = OptionItem_delete, + .display = CheckItem_display + }, + .kind = OPTION_ITEM_CHECK +}; + +const OptionItemClass NumberItem_class = { + .super = { + .extends = Class(OptionItem), + .delete = OptionItem_delete, + .display = NumberItem_display + }, + .kind = OPTION_ITEM_NUMBER +}; + +CheckItem* CheckItem_newByRef(const char* text, bool* ref) { + CheckItem* this = AllocThis(CheckItem); + this->super.text = xStrdup(text); + this->value = false; + this->ref = ref; + return this; +} + +CheckItem* CheckItem_newByVal(const char* text, bool value) { + CheckItem* this = AllocThis(CheckItem); + this->super.text = xStrdup(text); + this->value = value; + this->ref = NULL; + return this; +} + +bool CheckItem_get(const CheckItem* this) { + if (this->ref) { + return *(this->ref); + } else { + return this->value; + } +} + +void CheckItem_set(CheckItem* this, bool value) { + if (this->ref) { + *(this->ref) = value; + } else { + this->value = value; + } +} + +void CheckItem_toggle(CheckItem* this) { + if (this->ref) { + *(this->ref) = !*(this->ref); + } else { + this->value = !this->value; + } +} + +NumberItem* NumberItem_newByRef(const char* text, int* ref, int scale, int min, int max) { + assert(min <= max); + + NumberItem* this = AllocThis(NumberItem); + this->super.text = xStrdup(text); + this->value = 0; + this->ref = ref; + this->scale = scale; + this->min = min; + this->max = max; + return this; +} + +NumberItem* NumberItem_newByVal(const char* text, int value, int scale, int min, int max) { + assert(min <= max); + + NumberItem* this = AllocThis(NumberItem); + this->super.text = xStrdup(text); + this->value = CLAMP(value, min, max); + this->ref = NULL; + this->scale = scale; + this->min = min; + this->max = max; + return this; +} + +int NumberItem_get(const NumberItem* this) { + if (this->ref) { + return *(this->ref); + } else { + return this->value; + } +} + +void NumberItem_decrease(NumberItem* this) { + if (this->ref) { + *(this->ref) = CLAMP(*(this->ref) - 1, this->min, this->max); + } else { + this->value = CLAMP(this->value - 1, this->min, this->max); + } +} + +void NumberItem_increase(NumberItem* this) { + if (this->ref) { + *(this->ref) = CLAMP(*(this->ref) + 1, this->min, this->max); + } else { + this->value = CLAMP(this->value + 1, this->min, this->max); + } +} + +void NumberItem_toggle(NumberItem* this) { + if (this->ref) { + if (*(this->ref) >= this->max) + *(this->ref) = this->min; + else + *(this->ref) += 1; + } else { + if (this->value >= this->max) + this->value = this->min; + else + this->value += 1; + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/OptionItem.h pcp-5.3.2/vendor/github.com/htop-dev/htop/OptionItem.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/OptionItem.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/OptionItem.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,70 @@ +#ifndef HEADER_OptionItem +#define HEADER_OptionItem +/* +htop - OptionItem.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Object.h" + + +enum OptionItemType { + OPTION_ITEM_CHECK, + OPTION_ITEM_NUMBER, +}; + +typedef struct OptionItemClass_ { + const ObjectClass super; + + enum OptionItemType kind; +} OptionItemClass; + +#define As_OptionItem(this_) ((const OptionItemClass*)((this_)->super.klass)) +#define OptionItem_kind(this_) As_OptionItem(this_)->kind + +typedef struct OptionItem_ { + Object super; + + char* text; +} OptionItem; + +typedef struct CheckItem_ { + OptionItem super; + + bool* ref; + bool value; +} CheckItem; + +typedef struct NumberItem_ { + OptionItem super; + + char* text; + int* ref; + int value; + int scale; + int min; + int max; +} NumberItem; + +extern const OptionItemClass OptionItem_class; +extern const OptionItemClass CheckItem_class; +extern const OptionItemClass NumberItem_class; + +CheckItem* CheckItem_newByRef(const char* text, bool* ref); +CheckItem* CheckItem_newByVal(const char* text, bool value); +bool CheckItem_get(const CheckItem* this); +void CheckItem_set(CheckItem* this, bool value); +void CheckItem_toggle(CheckItem* this); + +NumberItem* NumberItem_newByRef(const char* text, int* ref, int scale, int min, int max); +NumberItem* NumberItem_newByVal(const char* text, int value, int scale, int min, int max); +int NumberItem_get(const NumberItem* this); +void NumberItem_decrease(NumberItem* this); +void NumberItem_increase(NumberItem* this); +void NumberItem_toggle(NumberItem* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Panel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Panel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Panel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Panel.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,487 @@ +/* +htop - Panel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" + +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "ListItem.h" +#include "Macros.h" +#include "ProvideCurses.h" +#include "RichString.h" +#include "XUtils.h" + + +const PanelClass Panel_class = { + .super = { + .extends = Class(Object), + .delete = Panel_delete + }, + .eventHandler = Panel_selectByTyping, +}; + +Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) { + Panel* this; + this = xMalloc(sizeof(Panel)); + Object_setClass(this, Class(Panel)); + Panel_init(this, x, y, w, h, type, owner, fuBar); + return this; +} + +void Panel_delete(Object* cast) { + Panel* this = (Panel*)cast; + Panel_done(this); + free(this); +} + +void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) { + this->x = x; + this->y = y; + this->w = w; + this->h = h; + this->eventHandlerState = NULL; + this->items = Vector_new(type, owner, DEFAULT_SIZE); + this->scrollV = 0; + this->scrollH = 0; + this->selected = 0; + this->oldSelected = 0; + this->selectedLen = 0; + this->needsRedraw = true; + this->wasFocus = false; + RichString_beginAllocated(this->header); + this->defaultBar = fuBar; + this->currentBar = fuBar; + this->selectionColorId = PANEL_SELECTION_FOCUS; +} + +void Panel_done(Panel* this) { + assert (this != NULL); + free(this->eventHandlerState); + Vector_delete(this->items); + FunctionBar_delete(this->defaultBar); + RichString_delete(&this->header); +} + +void Panel_setSelectionColor(Panel* this, ColorElements colorId) { + this->selectionColorId = colorId; +} + +inline void Panel_setHeader(Panel* this, const char* header) { + RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header); + this->needsRedraw = true; +} + +void Panel_move(Panel* this, int x, int y) { + assert (this != NULL); + + this->x = x; + this->y = y; + this->needsRedraw = true; +} + +void Panel_resize(Panel* this, int w, int h) { + assert (this != NULL); + + this->w = w; + this->h = h; + this->needsRedraw = true; +} + +void Panel_prune(Panel* this) { + assert (this != NULL); + + Vector_prune(this->items); + this->scrollV = 0; + this->selected = 0; + this->oldSelected = 0; + this->needsRedraw = true; +} + +void Panel_add(Panel* this, Object* o) { + assert (this != NULL); + + Vector_add(this->items, o); + this->needsRedraw = true; +} + +void Panel_insert(Panel* this, int i, Object* o) { + assert (this != NULL); + + Vector_insert(this->items, i, o); + this->needsRedraw = true; +} + +void Panel_set(Panel* this, int i, Object* o) { + assert (this != NULL); + + Vector_set(this->items, i, o); +} + +Object* Panel_get(Panel* this, int i) { + assert (this != NULL); + + return Vector_get(this->items, i); +} + +Object* Panel_remove(Panel* this, int i) { + assert (this != NULL); + + this->needsRedraw = true; + Object* removed = Vector_remove(this->items, i); + if (this->selected > 0 && this->selected >= Vector_size(this->items)) { + this->selected--; + } + + return removed; +} + +Object* Panel_getSelected(Panel* this) { + assert (this != NULL); + if (Vector_size(this->items) > 0) { + return Vector_get(this->items, this->selected); + } else { + return NULL; + } +} + +void Panel_moveSelectedUp(Panel* this) { + assert (this != NULL); + + Vector_moveUp(this->items, this->selected); + if (this->selected > 0) { + this->selected--; + } +} + +void Panel_moveSelectedDown(Panel* this) { + assert (this != NULL); + + Vector_moveDown(this->items, this->selected); + if (this->selected + 1 < Vector_size(this->items)) { + this->selected++; + } +} + +int Panel_getSelectedIndex(const Panel* this) { + assert (this != NULL); + + return this->selected; +} + +int Panel_size(const Panel* this) { + assert (this != NULL); + + return Vector_size(this->items); +} + +void Panel_setSelected(Panel* this, int selected) { + assert (this != NULL); + + int size = Vector_size(this->items); + if (selected >= size) { + selected = size - 1; + } + if (selected < 0) { + selected = 0; + } + this->selected = selected; + if (Panel_eventHandlerFn(this)) { + Panel_eventHandler(this, EVENT_SET_SELECTED); + } +} + +void Panel_splice(Panel* this, Vector* from) { + assert (this != NULL); + assert (from != NULL); + + Vector_splice(this->items, from); + this->needsRedraw = true; +} + +void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar) { + assert (this != NULL); + + int size = Vector_size(this->items); + int scrollH = this->scrollH; + int y = this->y; + int x = this->x; + int h = this->h; + + if (hideFunctionBar) + h++; + + const int header_attr = focus + ? CRT_colors[PANEL_HEADER_FOCUS] + : CRT_colors[PANEL_HEADER_UNFOCUS]; + if (force_redraw) { + if (Panel_printHeaderFn(this)) + Panel_printHeader(this); + else + RichString_setAttr(&this->header, header_attr); + } + int headerLen = RichString_sizeVal(this->header); + if (headerLen > 0) { + attrset(header_attr); + mvhline(y, x, ' ', this->w); + if (scrollH < headerLen) { + RichString_printoffnVal(this->header, y, x, scrollH, + MINIMUM(headerLen - scrollH, this->w)); + } + attrset(CRT_colors[RESET_COLOR]); + y++; + h--; + } + + // ensure scroll area is on screen + if (this->scrollV < 0) { + this->scrollV = 0; + this->needsRedraw = true; + } else if (this->scrollV > size - h) { + this->scrollV = MAXIMUM(size - h, 0); + this->needsRedraw = true; + } + // ensure selection is on screen + if (this->selected < this->scrollV) { + this->scrollV = this->selected; + this->needsRedraw = true; + } else if (this->selected >= this->scrollV + h) { + this->scrollV = this->selected - h + 1; + this->needsRedraw = true; + } + + int first = this->scrollV; + int upTo = MINIMUM(first + h, size); + + int selectionColor = focus + ? CRT_colors[this->selectionColorId] + : CRT_colors[PANEL_SELECTION_UNFOCUS]; + + if (this->needsRedraw || force_redraw) { + int line = 0; + for (int i = first; line < h && i < upTo; i++) { + const Object* itemObj = Vector_get(this->items, i); + RichString_begin(item); + Object_display(itemObj, &item); + int itemLen = RichString_sizeVal(item); + int amt = MINIMUM(itemLen - scrollH, this->w); + if (highlightSelected && i == this->selected) { + item.highlightAttr = selectionColor; + } + if (item.highlightAttr) { + attrset(item.highlightAttr); + RichString_setAttr(&item, item.highlightAttr); + this->selectedLen = itemLen; + } + mvhline(y + line, x, ' ', this->w); + if (amt > 0) + RichString_printoffnVal(item, y + line, x, scrollH, amt); + if (item.highlightAttr) + attrset(CRT_colors[RESET_COLOR]); + RichString_delete(&item); + line++; + } + while (line < h) { + mvhline(y + line, x, ' ', this->w); + line++; + } + + } else { + const Object* oldObj = Vector_get(this->items, this->oldSelected); + RichString_begin(old); + Object_display(oldObj, &old); + int oldLen = RichString_sizeVal(old); + const Object* newObj = Vector_get(this->items, this->selected); + RichString_begin(new); + Object_display(newObj, &new); + int newLen = RichString_sizeVal(new); + this->selectedLen = newLen; + mvhline(y + this->oldSelected - first, x + 0, ' ', this->w); + if (scrollH < oldLen) + RichString_printoffnVal(old, y + this->oldSelected - first, x, + scrollH, MINIMUM(oldLen - scrollH, this->w)); + attrset(selectionColor); + mvhline(y + this->selected - first, x + 0, ' ', this->w); + RichString_setAttr(&new, selectionColor); + if (scrollH < newLen) + RichString_printoffnVal(new, y + this->selected - first, x, + scrollH, MINIMUM(newLen - scrollH, this->w)); + attrset(CRT_colors[RESET_COLOR]); + RichString_delete(&new); + RichString_delete(&old); + } + + if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) { + if (Panel_drawFunctionBarFn(this)) + Panel_drawFunctionBar(this, hideFunctionBar); + else if (!hideFunctionBar) + FunctionBar_draw(this->currentBar); + } + + this->oldSelected = this->selected; + this->wasFocus = focus; + this->needsRedraw = false; + move(0, 0); +} + +static int Panel_headerHeight(const Panel* this) { + return RichString_sizeVal(this->header) > 0 ? 1 : 0; +} + +bool Panel_onKey(Panel* this, int key) { + assert (this != NULL); + + const int size = Vector_size(this->items); + + #define PANEL_SCROLL(amount) \ + do { \ + this->selected += (amount); \ + this->scrollV = CLAMP(this->scrollV + (amount), 0, MAXIMUM(0, (size - this->h - Panel_headerHeight(this)))); \ + this->needsRedraw = true; \ + } while (0) + + switch (key) { + case KEY_DOWN: + case KEY_CTRL('N'): + #ifdef KEY_C_DOWN + case KEY_C_DOWN: + #endif + this->selected++; + break; + + case KEY_UP: + case KEY_CTRL('P'): + #ifdef KEY_C_UP + case KEY_C_UP: + #endif + this->selected--; + break; + + case KEY_LEFT: + case KEY_CTRL('B'): + if (this->scrollH > 0) { + this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0); + this->needsRedraw = true; + } + break; + + case KEY_RIGHT: + case KEY_CTRL('F'): + this->scrollH += CRT_scrollHAmount; + this->needsRedraw = true; + break; + + case KEY_PPAGE: + PANEL_SCROLL(-(this->h - Panel_headerHeight(this))); + break; + + case KEY_NPAGE: + PANEL_SCROLL(+(this->h - Panel_headerHeight(this))); + break; + + case KEY_WHEELUP: + PANEL_SCROLL(-CRT_scrollWheelVAmount); + break; + + case KEY_WHEELDOWN: + PANEL_SCROLL(+CRT_scrollWheelVAmount); + break; + + case KEY_HOME: + this->selected = 0; + break; + + case KEY_END: + this->selected = size - 1; + break; + + case KEY_CTRL('A'): + case '^': + this->scrollH = 0; + this->needsRedraw = true; + break; + case KEY_CTRL('E'): + case '$': + this->scrollH = MAXIMUM(this->selectedLen - this->w, 0); + this->needsRedraw = true; + break; + default: + return false; + } + + #undef PANEL_SCROLL + + // ensure selection within bounds + if (this->selected < 0 || size == 0) { + this->selected = 0; + this->needsRedraw = true; + } else if (this->selected >= size) { + this->selected = size - 1; + this->needsRedraw = true; + } + + return true; +} + + +HandlerResult Panel_selectByTyping(Panel* this, int ch) { + int size = Panel_size(this); + + if (!this->eventHandlerState) + this->eventHandlerState = xCalloc(100, sizeof(char)); + char* buffer = this->eventHandlerState; + + if (0 < ch && ch < 255 && isgraph((unsigned char)ch)) { + int len = strlen(buffer); + if (!len) { + if ('/' == ch) { + ch = '\001'; + } else if ('q' == ch) { + return BREAK_LOOP; + } + } else if (1 == len && '\001' == buffer[0]) { + len--; + } + + if (len < 99) { + buffer[len] = ch; + buffer[len + 1] = '\0'; + } + + for (int try = 0; try < 2; try++) { + len = strlen(buffer); + for (int i = 0; i < size; i++) { + const char* cur = ((ListItem*) Panel_get(this, i))->value; + while (*cur == ' ') cur++; + if (strncasecmp(cur, buffer, len) == 0) { + Panel_setSelected(this, i); + return HANDLED; + } + } + + // if current word did not match, + // retry considering the character the start of a new word. + buffer[0] = ch; + buffer[1] = '\0'; + } + + return HANDLED; + } else if (ch != ERR) { + buffer[0] = '\0'; + } + + if (ch == 13) { + return BREAK_LOOP; + } + + return IGNORED; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Panel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Panel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Panel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Panel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,129 @@ +#ifndef HEADER_Panel +#define HEADER_Panel +/* +htop - Panel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Object.h" +#include "RichString.h" +#include "Vector.h" + + +struct Panel_; +typedef struct Panel_ Panel; + +typedef enum HandlerResult_ { + HANDLED = 0x01, + IGNORED = 0x02, + BREAK_LOOP = 0x04, + REFRESH = 0x08, + REDRAW = 0x10, + RESCAN = 0x20, + SYNTH_KEY = 0x40, +} HandlerResult; + +#define EVENT_SET_SELECTED (-1) + +#define EVENT_HEADER_CLICK(x_) (-10000 + (x_)) +#define EVENT_IS_HEADER_CLICK(ev_) ((ev_) >= -10000 && (ev_) <= -9000) +#define EVENT_HEADER_CLICK_GET_X(ev_) ((ev_) + 10000) + +typedef HandlerResult (*Panel_EventHandler)(Panel*, int); +typedef void (*Panel_DrawFunctionBar)(Panel*, bool); +typedef void (*Panel_PrintHeader)(Panel*); + +typedef struct PanelClass_ { + const ObjectClass super; + const Panel_EventHandler eventHandler; + const Panel_DrawFunctionBar drawFunctionBar; + const Panel_PrintHeader printHeader; +} PanelClass; + +#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass)) +#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler +#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_)) +#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar +#define Panel_drawFunctionBar(this_, hideFB_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_), hideFB_)) +#define Panel_printHeaderFn(this_) As_Panel(this_)->printHeader +#define Panel_printHeader(this_) (assert(As_Panel(this_)->printHeader), As_Panel(this_)->printHeader((Panel*)(this_))) + +struct Panel_ { + Object super; + int x, y, w, h; + Vector* items; + int selected; + int oldSelected; + int selectedLen; + void* eventHandlerState; + int scrollV; + short scrollH; + bool needsRedraw; + bool wasFocus; + FunctionBar* currentBar; + FunctionBar* defaultBar; + RichString header; + ColorElements selectionColorId; +}; + +#define Panel_setDefaultBar(this_) do { (this_)->currentBar = (this_)->defaultBar; } while (0) + +#define KEY_CTRL(l) ((l)-'A'+1) + +extern const PanelClass Panel_class; + +Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar); + +void Panel_delete(Object* cast); + +void Panel_init(Panel* this, int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar); + +void Panel_done(Panel* this); + +void Panel_setSelectionColor(Panel* this, ColorElements colorId); + +void Panel_setHeader(Panel* this, const char* header); + +void Panel_move(Panel* this, int x, int y); + +void Panel_resize(Panel* this, int w, int h); + +void Panel_prune(Panel* this); + +void Panel_add(Panel* this, Object* o); + +void Panel_insert(Panel* this, int i, Object* o); + +void Panel_set(Panel* this, int i, Object* o); + +Object* Panel_get(Panel* this, int i); + +Object* Panel_remove(Panel* this, int i); + +Object* Panel_getSelected(Panel* this); + +void Panel_moveSelectedUp(Panel* this); + +void Panel_moveSelectedDown(Panel* this); + +int Panel_getSelectedIndex(const Panel* this); + +int Panel_size(const Panel* this); + +void Panel_setSelected(Panel* this, int selected); + +void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar); + +void Panel_splice(Panel* this, Vector* from); + +bool Panel_onKey(Panel* this, int key); + +HandlerResult Panel_selectByTyping(Panel* this, int ch); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/entropy pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/entropy --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/entropy 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/entropy 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,9 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[entropy] +caption = Entropy +avail.metric = kernel.all.entropy.avail / kernel.all.entropy.poolsize * 100 +avail.label = avail +avail.suffix = % diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/freespace pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/freespace --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/freespace 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/freespace 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,11 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[freespace] +caption = Freespace +description = Filesystem space +used.metric = sum(filesys.used) +used.color = blue +free.metric = sum(filesys.free) +free.color = green diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/ipc pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/ipc --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/ipc 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/ipc 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,13 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[ipc] +caption = SysV IPC +description = SysV IPC counts +msg.metric = ipc.msg.used_queues +msg.color = blue +sem.metric = ipc.sem.used_sem +sem.color = green +shm.metric = ipc.shm.used_ids +shm.color = cyan diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/locks pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/locks --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/locks 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/locks 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,15 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[locks] +caption = File locks +description = VFS file locks +posix.metric = vfs.locks.posix.count +posix.color = blue +flock.metric = vfs.locks.flock.count +flock.color = green +readlock.metric = vfs.locks.posix.read + vfs.locks.flock.read +readlock.color = red +writelock.metric = vfs.locks.posix.write + vfs.locks.flock.write +writelock.color = yellow diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/memcache pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/memcache --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/memcache 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/memcache 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,11 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[memcache] +caption = Memcache +description = Memcache Hits +hit.metric = sum(memcache.hits) +hit.color = green +miss.metric = sum(memcache.misses) +miss.color = blue diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/mysql pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/mysql --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/mysql 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/mysql 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,71 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[mysql_io] +caption = MySQL I/O +recv.metric = mysql.status.bytes_received +recv.color = green +sent.metric = mysql.status.bytes_sent +sent.color = blue + +[mysql_keys] +caption = MySQL keys +description = MySQL key status +key_blocks_used.metric = mysql.status.key_blocks_used +key_blocks_used.label = color +key_blocks_used.label = used +key_reads.metric = mysql.status.key_reads +key_reads.label = read +key_reads.color = green +key_writes.metric = mysql.status.key_writes +key_writes.label = writ +key_writes.color = blue +key_read_requests.metric = mysql.status.key_read_requests +key_read_requests.label = rreq +key_read_requests.color = green +key_write_requests.metric = mysql.status.key_write_requests +key_write_requests.label = wreq +key_write_requests.color = blue + +[innodb_buffer] +caption = InnoDB pool +description = InnoDB buffer pool +created.metric = mysql.status.innodb_pages_created +created.label = cr +created.color = yellow +read.metric = mysql.status.innodb_pages_read +read.label = rd +read.color = greed +written.metric = mysql.status.innodb_pages_written +written.label = wr +written.color = red + +[innodb_io] +caption = InnoDB I/O +description = InnoDB I/O operations +read.metric = mysql.status.innodb_data_read +read.label = rd +read.color = green +written.metric = mysql.status.innodb_data.writes +written.label = wr +written.color = blue +sync.metric = mysql.status.innodb_data_fsyncs +sync.label = sync +sync.color = cyan + +[innodb_ops] +caption = InnoDB ops +description = InnoDB operations +inserted.metric = mysql.status.innodb_rows_inserted +inserted.label = ins +inserted.color = blue +updated.metric = mysql.status.innodb_rows_updated +updated.label = upd +updated.color = cyan +deleted.metric = mysql.status.innodb_rows_deleted +deleted.label = del +deleted.color = red +read.metric = mysql.status.innodb_rows_read +read.label = rd +read.color = green diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/postfix pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/postfix --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/postfix 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/postfix 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,20 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[postfix] +caption = Postfix +incoming.metric = sum(postfix.queues.incoming) +incoming.color = green +incoming.label = in +active.metric = sum(postfix.queues.active) +active.color = blue +active.label = act +deferred.metric = sum(postfix.queues.deferred) +deferred.color = cyan +deferred.label = dfr +bounce.metric = sum(postfix.queues.maildrop) +bounce.color = red +bounce.label = bnc +hold.metric = sum(postfix.queues.hold) +hold.color = yellow diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/redis pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/redis --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/redis 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/redis 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,39 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[redisxact] +caption = Redis xact +description = Redis transactions +tps.metric = redis.instantaneous_ops_per_sec +tps.color = green + +[redismem] +caption = Redis mem +description = Redis memory +lua.metric = redis.used_memory_lua +lua.color = magenta +used.metric = redis.used_memory +used.color = blue + +[redisclient] +caption = Redis clients +description = Redis clients +type = bar +blocked.metric = redis.blocked_clients +blocked.color = blue +blocked.label = blk +clients.metric = redis.connected_clients +clients.color = green +clients.label = conn + +[redisconn] +caption = Redis conn +description = Redis connections +type = bar +reject.metric = redis.rejected_connections +reject.color = magenta +reject.label = fail/s +total.metric = redis.total_connections_received +total.color = blue +total.label = conn/s diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/tcp pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/tcp --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/meters/tcp 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/meters/tcp 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,21 @@ +# +# pcp-htop(1) configuration file - see pcp-htop(5) +# + +[tcp] +caption = TCP +description = TCP sockets +listen.metric = network.tcpconn.listen +listen.color = green +listen.label = lis +active.metric = network.tcpconn.established +active.color = blue +active.label = act +syn.metric = network.tcpconn.syn_sent + network.tcpconn.syn_recv + network.tcpconn.last_ack +syn.color = cyan +wait.metric = network.tcpconn.time_wait +wait.color = red +wait.label = tim +close.metric = network.tcpconn.fin_wait1 + network.tcpconn.fin_wait2 + network.tcpconn.close + network.tcpconn.close_wait + network.tcpconn.closing +close.color = yellow +close.label = clo diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,434 @@ +/* +htop - PCPDynamicMeter.c +(C) 2021 htop dev team +(C) 2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +#include "config.h" // IWYU pragma: keep + +#include "pcp/PCPDynamicMeter.h" + +#include + +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "Settings.h" +#include "XUtils.h" + +static PCPDynamicMetric* PCPDynamicMeter_lookupMetric(PCPDynamicMeters* meters, PCPDynamicMeter* meter, const char* name) { + size_t bytes = 8 + strlen(meter->super.name) + strlen(name); + char* metricName = xMalloc(bytes); + xSnprintf(metricName, bytes, "htop.%s.%s", meter->super.name, name); + + PCPDynamicMetric* metric; + for (unsigned int i = 0; i < meter->totalMetrics; i++) { + metric = &meter->metrics[i]; + if (String_eq(metric->name, metricName)) { + free(metricName); + return metric; + } + } + + /* not an existing metric in this meter - add it */ + unsigned int n = meter->totalMetrics + 1; + meter->metrics = xReallocArray(meter->metrics, n, sizeof(PCPDynamicMetric)); + meter->totalMetrics = n; + metric = &meter->metrics[n - 1]; + memset(metric, 0, sizeof(PCPDynamicMetric)); + metric->name = metricName; + metric->label = String_cat(name, ": "); + metric->id = meters->offset + meters->cursor; + meters->cursor++; + + Platform_addMetric(metric->id, metricName); + + return metric; +} + +static void PCPDynamicMeter_parseMetric(PCPDynamicMeters* meters, PCPDynamicMeter* meter, const char* path, unsigned int line, char* key, char* value) { + PCPDynamicMetric* metric; + char* p; + + if ((p = strchr(key, '.')) == NULL) + return; + *p++ = '\0'; /* end the name, p is now the attribute, e.g. 'label' */ + + if (String_eq(p, "metric")) { + /* lookup a dynamic metric with this name, else create */ + metric = PCPDynamicMeter_lookupMetric(meters, meter, key); + + /* use derived metrics in dynamic meters for simplicity */ + char* error; + if (pmRegisterDerivedMetric(metric->name, value, &error) < 0) { + char* note; + xAsprintf(¬e, + "%s: failed to parse expression in %s at line %u\n%s\n%s", + pmGetProgname(), path, line, error, pmGetProgname()); + free(error); + errno = EINVAL; + CRT_fatalError(note); + free(note); + } + } else { + /* this is a property of a dynamic metric - the metric expression */ + /* may not have been observed yet - i.e. we allow for any ordering */ + metric = PCPDynamicMeter_lookupMetric(meters, meter, key); + if (String_eq(p, "color")) { + if (String_eq(value, "gray")) + metric->color = DYNAMIC_GRAY; + else if (String_eq(value, "darkgray")) + metric->color = DYNAMIC_DARKGRAY; + else if (String_eq(value, "red")) + metric->color = DYNAMIC_RED; + else if (String_eq(value, "green")) + metric->color = DYNAMIC_GREEN; + else if (String_eq(value, "blue")) + metric->color = DYNAMIC_BLUE; + else if (String_eq(value, "cyan")) + metric->color = DYNAMIC_CYAN; + else if (String_eq(value, "magenta")) + metric->color = DYNAMIC_MAGENTA; + else if (String_eq(value, "yellow")) + metric->color = DYNAMIC_YELLOW; + else if (String_eq(value, "white")) + metric->color = DYNAMIC_WHITE; + } else if (String_eq(p, "label")) { + char* label = String_cat(value, ": "); + free_and_xStrdup(&metric->label, label); + free(label); + } else if (String_eq(p, "suffix")) { + free_and_xStrdup(&metric->suffix, value); + } + } +} + +// Ensure a valid name for use in a PCP metric name and in htoprc +static bool PCPDynamicMeter_validateMeterName(char* key, const char* path, unsigned int line) { + char* p = key; + char* end = strrchr(key, ']'); + + if (end) { + *end = '\0'; + } else { + fprintf(stderr, + "%s: no closing brace on meter name at %s line %u\n\"%s\"\n", + pmGetProgname(), path, line, key); + return false; + } + + while (*p) { + if (p == key) { + if (!isalpha(*p) && *p != '_') + break; + } else { + if (!isalnum(*p) && *p != '_') + break; + } + p++; + } + if (*p != '\0') { /* badness */ + fprintf(stderr, + "%s: invalid meter name at %s line %u\n\"%s\"\n", + pmGetProgname(), path, line, key); + return false; + } + return true; +} + +// Ensure a meter name has not been defined previously +static bool PCPDynamicMeter_uniqueName(char* key, const char* path, unsigned int line, PCPDynamicMeters* meters) { + if (DynamicMeter_search(meters->table, key, NULL) == false) + return true; + + fprintf(stderr, "%s: duplicate name at %s line %u: \"%s\", ignored\n", + pmGetProgname(), path, line, key); + return false; +} + +static PCPDynamicMeter* PCPDynamicMeter_new(PCPDynamicMeters* meters, const char* name) { + PCPDynamicMeter* meter = xCalloc(1, sizeof(*meter)); + String_safeStrncpy(meter->super.name, name, sizeof(meter->super.name)); + Hashtable_put(meters->table, ++meters->count, meter); + return meter; +} + +static void PCPDynamicMeter_parseFile(PCPDynamicMeters* meters, const char* path) { + FILE* file = fopen(path, "r"); + if (!file) + return; + + PCPDynamicMeter* meter = NULL; + unsigned int lineno = 0; + bool ok = true; + for (;;) { + char* line = String_readLine(file); + if (!line) + break; + lineno++; + + /* cleanup whitespace, skip comment lines */ + char* trimmed = String_trim(line); + free(line); + if (trimmed[0] == '#' || trimmed[0] == '\0') { + free(trimmed); + continue; + } + + size_t n; + char** config = String_split(trimmed, '=', &n); + free(trimmed); + if (config == NULL) + continue; + + char* key = String_trim(config[0]); + char* value = n > 1 ? String_trim(config[1]) : NULL; + if (key[0] == '[') { /* new section heading - i.e. new meter */ + ok = PCPDynamicMeter_validateMeterName(key + 1, path, lineno); + if (ok) + ok = PCPDynamicMeter_uniqueName(key + 1, path, lineno, meters); + if (ok) + meter = PCPDynamicMeter_new(meters, key + 1); + } else if (!ok) { + ; /* skip this one, we're looking for a new header */ + } else if (value && meter && String_eq(key, "caption")) { + char* caption = String_cat(value, ": "); + if (caption) { + free_and_xStrdup(&meter->super.caption, caption); + free(caption); + caption = NULL; + } + } else if (value && meter && String_eq(key, "description")) { + free_and_xStrdup(&meter->super.description, value); + } else if (value && meter && String_eq(key, "type")) { + if (String_eq(config[1], "bar")) + meter->super.type = BAR_METERMODE; + else if (String_eq(config[1], "text")) + meter->super.type = TEXT_METERMODE; + else if (String_eq(config[1], "graph")) + meter->super.type = GRAPH_METERMODE; + else if (String_eq(config[1], "led")) + meter->super.type = LED_METERMODE; + } else if (value && meter && String_eq(key, "maximum")) { + meter->super.maximum = strtod(value, NULL); + } else if (value && meter) { + PCPDynamicMeter_parseMetric(meters, meter, path, lineno, key, value); + } + String_freeArray(config); + free(value); + free(key); + } + fclose(file); +} + +static void PCPDynamicMeter_scanDir(PCPDynamicMeters* meters, char* path) { + DIR* dir = opendir(path); + if (!dir) + return; + + struct dirent* dirent; + while ((dirent = readdir(dir)) != NULL) { + if (dirent->d_name[0] == '.') + continue; + + char* file = String_cat(path, dirent->d_name); + PCPDynamicMeter_parseFile(meters, file); + free(file); + } + closedir(dir); +} + +void PCPDynamicMeters_init(PCPDynamicMeters* meters) { + const char* sysconf = pmGetConfig("PCP_SYSCONF_DIR"); + const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); + const char* home = getenv("HOME"); + char* path; + + meters->table = Hashtable_new(0, true); + + /* search in the users home directory first of all */ + if (xdgConfigHome) { + path = String_cat(xdgConfigHome, "/htop/meters/"); + } else { + if (!home) + home = ""; + path = String_cat(home, "/.config/htop/meters/"); + } + PCPDynamicMeter_scanDir(meters, path); + free(path); + + /* secondly search in the system meters directory */ + path = String_cat(sysconf, "/htop/meters/"); + PCPDynamicMeter_scanDir(meters, path); + free(path); + + /* check the working directory, as a final option */ + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + path = String_cat(cwd, "/pcp/meters/"); + PCPDynamicMeter_scanDir(meters, path); + free(path); + } +} + +void PCPDynamicMeter_enable(PCPDynamicMeter* this) { + for (unsigned int i = 0; i < this->totalMetrics; i++) + Metric_enable(this->metrics[i].id, true); +} + +void PCPDynamicMeter_updateValues(PCPDynamicMeter* this, Meter* meter) { + char* buffer = meter->txtBuffer; + size_t size = sizeof(meter->txtBuffer); + size_t bytes = 0; + + for (unsigned int i = 0; i < this->totalMetrics; i++) { + if (i > 0 && bytes < size - 1) + buffer[bytes++] = '/'; /* separator */ + + PCPDynamicMetric* metric = &this->metrics[i]; + const pmDesc* desc = Metric_desc(metric->id); + pmAtomValue atom, raw; + + if (!Metric_values(metric->id, &raw, 1, desc->type)) { + bytes--; /* clear the separator */ + continue; + } + + pmUnits conv = desc->units; /* convert to canonical units */ + if (conv.dimSpace) + conv.scaleSpace = PM_SPACE_KBYTE; + if (conv.dimTime) + conv.scaleTime = PM_TIME_SEC; + if (desc->type == PM_TYPE_STRING) + atom = raw; + else if (pmConvScale(desc->type, &raw, &desc->units, &atom, &conv) < 0) { + bytes--; /* clear the separator */ + continue; + } + + size_t saved = bytes; + switch (desc->type) { + case PM_TYPE_STRING: + bytes += xSnprintf(buffer + bytes, size - bytes, "%s", atom.cp); + free(atom.cp); + break; + case PM_TYPE_32: + bytes += conv.dimSpace ? + Meter_humanUnit(buffer + bytes, atom.l, size - bytes) : + xSnprintf(buffer + bytes, size - bytes, "%d", atom.l); + break; + case PM_TYPE_U32: + bytes += conv.dimSpace ? + Meter_humanUnit(buffer + bytes, atom.ul, size - bytes) : + xSnprintf(buffer + bytes, size - bytes, "%u", atom.ul); + break; + case PM_TYPE_64: + bytes += conv.dimSpace ? + Meter_humanUnit(buffer + bytes, atom.ll, size - bytes) : + xSnprintf(buffer + bytes, size - bytes, "%lld", (long long) atom.ll); + break; + case PM_TYPE_U64: + bytes += conv.dimSpace ? + Meter_humanUnit(buffer + bytes, atom.ull, size - bytes) : + xSnprintf(buffer + bytes, size - bytes, "%llu", (unsigned long long) atom.ull); + break; + case PM_TYPE_FLOAT: + bytes += conv.dimSpace ? + Meter_humanUnit(buffer + bytes, atom.f, size - bytes) : + xSnprintf(buffer + bytes, size - bytes, "%.2f", (double) atom.f); + break; + case PM_TYPE_DOUBLE: + bytes += conv.dimSpace ? + Meter_humanUnit(buffer + bytes, atom.d, size - bytes) : + xSnprintf(buffer + bytes, size - bytes, "%.2f", atom.d); + break; + default: + break; + } + if (saved != bytes && metric->suffix) + bytes += xSnprintf(buffer + bytes, size - bytes, "%s", metric->suffix); + } + if (!bytes) + xSnprintf(buffer, size, "no data"); +} + +void PCPDynamicMeter_display(PCPDynamicMeter* this, ATTR_UNUSED const Meter* meter, RichString* out) { + int nodata = 1; + + for (unsigned int i = 0; i < this->totalMetrics; i++) { + PCPDynamicMetric* metric = &this->metrics[i]; + const pmDesc* desc = Metric_desc(metric->id); + pmAtomValue atom, raw; + char buffer[64]; + + if (!Metric_values(metric->id, &raw, 1, desc->type)) + continue; + + pmUnits conv = desc->units; /* convert to canonical units */ + if (conv.dimSpace) + conv.scaleSpace = PM_SPACE_KBYTE; + if (conv.dimTime) + conv.scaleTime = PM_TIME_SEC; + if (desc->type == PM_TYPE_STRING) + atom = raw; + else if (pmConvScale(desc->type, &raw, &desc->units, &atom, &conv) < 0) + continue; + + nodata = 0; /* we will use this metric so *some* data will be added */ + + if (i > 0) + RichString_appendnAscii(out, CRT_colors[metric->color], " ", 1); + + if (metric->label) + RichString_appendAscii(out, CRT_colors[METER_TEXT], metric->label); + + int len = 0; + switch (desc->type) { + case PM_TYPE_STRING: + len = xSnprintf(buffer, sizeof(buffer), "%s", atom.cp); + free(atom.cp); + break; + case PM_TYPE_32: + len = conv.dimSpace ? + Meter_humanUnit(buffer, atom.l, sizeof(buffer)) : + xSnprintf(buffer, sizeof(buffer), "%d", atom.l); + break; + case PM_TYPE_U32: + len = conv.dimSpace ? + Meter_humanUnit(buffer, atom.ul, sizeof(buffer)) : + xSnprintf(buffer, sizeof(buffer), "%u", atom.ul); + break; + case PM_TYPE_64: + len = conv.dimSpace ? + Meter_humanUnit(buffer, atom.ll, sizeof(buffer)) : + xSnprintf(buffer, sizeof(buffer), "%lld", (long long) atom.ll); + break; + case PM_TYPE_U64: + len = conv.dimSpace ? + Meter_humanUnit(buffer, atom.ull, sizeof(buffer)) : + xSnprintf(buffer, sizeof(buffer), "%llu", (unsigned long long) atom.ull); + break; + case PM_TYPE_FLOAT: + len = conv.dimSpace ? + Meter_humanUnit(buffer, atom.f, sizeof(buffer)) : + xSnprintf(buffer, sizeof(buffer), "%.2f", (double) atom.f); + break; + case PM_TYPE_DOUBLE: + len = conv.dimSpace ? + Meter_humanUnit(buffer, atom.d, sizeof(buffer)) : + xSnprintf(buffer, sizeof(buffer), "%.2f", atom.d); + break; + default: + break; + } + if (len) { + RichString_appendnAscii(out, CRT_colors[metric->color], buffer, len); + if (metric->suffix) + RichString_appendAscii(out, CRT_colors[METER_TEXT], metric->suffix); + } + } + if (nodata) + RichString_writeAscii(out, CRT_colors[METER_VALUE_ERROR], "no data"); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPDynamicMeter.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,36 @@ +#ifndef HEADER_PCPDynamicMeter +#define HEADER_PCPDynamicMeter + +#include "CRT.h" +#include "DynamicMeter.h" + +typedef struct { + unsigned int id; /* index into metric array */ + ColorElements color; + char* name; /* derived metric name */ + char* label; + char* suffix; +} PCPDynamicMetric; + +typedef struct { + DynamicMeter super; + PCPDynamicMetric* metrics; + unsigned int totalMetrics; +} PCPDynamicMeter; + +typedef struct { + Hashtable* table; + unsigned int count; /* count of dynamic meters discovered by scan */ + unsigned int offset; /* start offset into the Platform metric array */ + unsigned int cursor; /* identifier allocator for each new metric used */ +} PCPDynamicMeters; + +void PCPDynamicMeters_init(PCPDynamicMeters* meters); + +void PCPDynamicMeter_enable(PCPDynamicMeter* this); + +void PCPDynamicMeter_updateValues(PCPDynamicMeter* this, Meter* meter); + +void PCPDynamicMeter_display(PCPDynamicMeter* this, const Meter* meter, RichString* out); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcess.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,262 @@ +/* +htop - PCPProcess.c +(C) 2014 Hisham H. Muhammad +(C) 2020 htop dev team +(C) 2020-2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "pcp/PCPProcess.h" + +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Process.h" +#include "ProvideCurses.h" +#include "XUtils.h" + +const ProcessFieldData Process_fields[] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging, I idle)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, }, + [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [CMINFLT] = { .name = "CMINFLT", .title = " CMINFLT ", .description = "Children processes' minor faults", .flags = 0, .defaultSortDesc = true, }, + [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [CMAJFLT] = { .name = "CMAJFLT", .title = " CMAJFLT ", .description = "Children processes' major faults", .flags = 0, .defaultSortDesc = true, }, + [UTIME] = { .name = "UTIME", .title = " UTIME+ ", .description = "User CPU time - time the process spent executing in user mode", .flags = 0, .defaultSortDesc = true, }, + [STIME] = { .name = "STIME", .title = " STIME+ ", .description = "System CPU time - time the kernel spent running system calls for this process", .flags = 0, .defaultSortDesc = true, }, + [CUTIME] = { .name = "CUTIME", .title = " CUTIME+ ", .description = "Children processes' user CPU time", .flags = 0, .defaultSortDesc = true, }, + [CSTIME] = { .name = "CSTIME", .title = " CSTIME+ ", .description = "Children processes' system CPU time", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "If of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [M_SHARE] = { .name = "M_SHARE", .title = " SHR ", .description = "Size of the process's shared pages", .flags = 0, .defaultSortDesc = true, }, + [M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the text segment of the process", .flags = 0, .defaultSortDesc = true, }, + [M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, }, + [M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, }, + [M_DT] = { .name = "M_DT", .title = " DIRTY ", .description = "Size of the dirty pages of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, }, + [RCHAR] = { .name = "RCHAR", .title = "RCHAR ", .description = "Number of bytes the process has read", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [WCHAR] = { .name = "WCHAR", .title = "WCHAR ", .description = "Number of bytes the process has written", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [SYSCR] = { .name = "SYSCR", .title = " READ_SYSC ", .description = "Number of read(2) syscalls for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [SYSCW] = { .name = "SYSCW", .title = " WRITE_SYSC ", .description = "Number of write(2) syscalls for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [RBYTES] = { .name = "RBYTES", .title = " IO_R ", .description = "Bytes of read(2) I/O for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [WBYTES] = { .name = "WBYTES", .title = " IO_W ", .description = "Bytes of write(2) I/O for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [CNCLWB] = { .name = "CNCLWB", .title = " IO_C ", .description = "Bytes of cancelled write(2) I/O", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [IO_READ_RATE] = { .name = "IO_READ_RATE", .title = " DISK READ ", .description = "The I/O rate of read(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [IO_WRITE_RATE] = { .name = "IO_WRITE_RATE", .title = " DISK WRITE ", .description = "The I/O rate of write(2) in bytes per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [IO_RATE] = { .name = "IO_RATE", .title = " DISK R/W ", .description = "Total I/O rate in bytes per second", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, }, + [CGROUP] = { .name = "CGROUP", .title = " CGROUP ", .description = "Which cgroup the process is in", .flags = PROCESS_FLAG_LINUX_CGROUP, }, + [OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, .defaultSortDesc = true, }, + [PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = 0, .defaultSortDesc = true, }, + [M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it.", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, + [M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, + [M_PSSWP] = { .name = "M_PSSWP", .title = " PSSWP ", .description = "shows proportional swap share of this mapping, Unlike \"Swap\", this does not take into account swapped out page of underlying shmem objects.", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, }, + [CTXT] = { .name = "CTXT", .title = " CTXT ", .description = "Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches)", .flags = PROCESS_FLAG_LINUX_CTXT, .defaultSortDesc = true, }, + [SECATTR] = { .name = "SECATTR", .title = " Security Attribute ", .description = "Security attribute of the process (e.g. SELinux or AppArmor)", .flags = PROCESS_FLAG_LINUX_SECATTR, }, + [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process", .flags = 0, }, + [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process", .flags = 0, }, + [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, +}; + +Process* PCPProcess_new(const Settings* settings) { + PCPProcess* this = xCalloc(1, sizeof(PCPProcess)); + Object_setClass(this, Class(PCPProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + PCPProcess* this = (PCPProcess*) cast; + Process_done((Process*)cast); + free(this->cgroup); + free(this->secattr); + free(this); +} + +static void PCPProcess_printDelay(float delay_percent, char* buffer, int n) { + if (isnan(delay_percent)) { + xSnprintf(buffer, n, " N/A "); + } else { + xSnprintf(buffer, n, "%4.1f ", delay_percent); + } +} + +static void PCPProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const PCPProcess* pp = (const PCPProcess*) this; + bool coloring = this->settings->highlightMegabytes; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + int n = sizeof(buffer) - 1; + switch ((int)field) { + case CMINFLT: Process_printCount(str, pp->cminflt, coloring); return; + case CMAJFLT: Process_printCount(str, pp->cmajflt, coloring); return; + case M_DRS: Process_printBytes(str, pp->m_drs, coloring); return; + case M_DT: Process_printBytes(str, pp->m_dt, coloring); return; + case M_LRS: Process_printBytes(str, pp->m_lrs, coloring); return; + case M_TRS: Process_printBytes(str, pp->m_trs, coloring); return; + case M_SHARE: Process_printBytes(str, pp->m_share, coloring); return; + case M_PSS: Process_printKBytes(str, pp->m_pss, coloring); return; + case M_SWAP: Process_printKBytes(str, pp->m_swap, coloring); return; + case M_PSSWP: Process_printKBytes(str, pp->m_psswp, coloring); return; + case UTIME: Process_printTime(str, pp->utime, coloring); return; + case STIME: Process_printTime(str, pp->stime, coloring); return; + case CUTIME: Process_printTime(str, pp->cutime, coloring); return; + case CSTIME: Process_printTime(str, pp->cstime, coloring); return; + case RCHAR: Process_printBytes(str, pp->io_rchar, coloring); return; + case WCHAR: Process_printBytes(str, pp->io_wchar, coloring); return; + case SYSCR: Process_printCount(str, pp->io_syscr, coloring); return; + case SYSCW: Process_printCount(str, pp->io_syscw, coloring); return; + case RBYTES: Process_printBytes(str, pp->io_read_bytes, coloring); return; + case WBYTES: Process_printBytes(str, pp->io_write_bytes, coloring); return; + case CNCLWB: Process_printBytes(str, pp->io_cancelled_write_bytes, coloring); return; + case IO_READ_RATE: Process_printRate(str, pp->io_rate_read_bps, coloring); return; + case IO_WRITE_RATE: Process_printRate(str, pp->io_rate_write_bps, coloring); return; + case IO_RATE: { + double totalRate = NAN; + if (!isnan(pp->io_rate_read_bps) && !isnan(pp->io_rate_write_bps)) + totalRate = pp->io_rate_read_bps + pp->io_rate_write_bps; + else if (!isnan(pp->io_rate_read_bps)) + totalRate = pp->io_rate_read_bps; + else if (!isnan(pp->io_rate_write_bps)) + totalRate = pp->io_rate_write_bps; + else + totalRate = NAN; + Process_printRate(str, totalRate, coloring); + return; + } + case CGROUP: xSnprintf(buffer, n, "%-10s ", pp->cgroup ? pp->cgroup : ""); break; + case OOM: xSnprintf(buffer, n, "%4u ", pp->oom); break; + case PERCENT_CPU_DELAY: + PCPProcess_printDelay(pp->cpu_delay_percent, buffer, n); + break; + case PERCENT_IO_DELAY: + PCPProcess_printDelay(pp->blkio_delay_percent, buffer, n); + break; + case PERCENT_SWAP_DELAY: + PCPProcess_printDelay(pp->swapin_delay_percent, buffer, n); + break; + case CTXT: + if (pp->ctxt_diff > 1000) { + attr |= A_BOLD; + } + xSnprintf(buffer, n, "%5lu ", pp->ctxt_diff); + break; + case SECATTR: snprintf(buffer, n, "%-30s ", pp->secattr ? pp->secattr : "?"); break; + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static double adjustNaN(double num) { + if (isnan(num)) + return -0.0005; + + return num; +} + +static int PCPProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const PCPProcess* p1 = (const PCPProcess*)v1; + const PCPProcess* p2 = (const PCPProcess*)v2; + + switch (key) { + case M_DRS: + return SPACESHIP_NUMBER(p1->m_drs, p2->m_drs); + case M_DT: + return SPACESHIP_NUMBER(p1->m_dt, p2->m_dt); + case M_LRS: + return SPACESHIP_NUMBER(p1->m_lrs, p2->m_lrs); + case M_TRS: + return SPACESHIP_NUMBER(p1->m_trs, p2->m_trs); + case M_SHARE: + return SPACESHIP_NUMBER(p1->m_share, p2->m_share); + case M_PSS: + return SPACESHIP_NUMBER(p1->m_pss, p2->m_pss); + case M_SWAP: + return SPACESHIP_NUMBER(p1->m_swap, p2->m_swap); + case M_PSSWP: + return SPACESHIP_NUMBER(p1->m_psswp, p2->m_psswp); + case UTIME: + return SPACESHIP_NUMBER(p1->utime, p2->utime); + case CUTIME: + return SPACESHIP_NUMBER(p1->cutime, p2->cutime); + case STIME: + return SPACESHIP_NUMBER(p1->stime, p2->stime); + case CSTIME: + return SPACESHIP_NUMBER(p1->cstime, p2->cstime); + case RCHAR: + return SPACESHIP_NUMBER(p1->io_rchar, p2->io_rchar); + case WCHAR: + return SPACESHIP_NUMBER(p1->io_wchar, p2->io_wchar); + case SYSCR: + return SPACESHIP_NUMBER(p1->io_syscr, p2->io_syscr); + case SYSCW: + return SPACESHIP_NUMBER(p1->io_syscw, p2->io_syscw); + case RBYTES: + return SPACESHIP_NUMBER(p1->io_read_bytes, p2->io_read_bytes); + case WBYTES: + return SPACESHIP_NUMBER(p1->io_write_bytes, p2->io_write_bytes); + case CNCLWB: + return SPACESHIP_NUMBER(p1->io_cancelled_write_bytes, p2->io_cancelled_write_bytes); + case IO_READ_RATE: + return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps), adjustNaN(p2->io_rate_read_bps)); + case IO_WRITE_RATE: + return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_write_bps)); + case IO_RATE: + return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps) + adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_read_bps) + adjustNaN(p2->io_rate_write_bps)); + case CGROUP: + return SPACESHIP_NULLSTR(p1->cgroup, p2->cgroup); + case OOM: + return SPACESHIP_NUMBER(p1->oom, p2->oom); + case PERCENT_CPU_DELAY: + return SPACESHIP_NUMBER(p1->cpu_delay_percent, p2->cpu_delay_percent); + case PERCENT_IO_DELAY: + return SPACESHIP_NUMBER(p1->blkio_delay_percent, p2->blkio_delay_percent); + case PERCENT_SWAP_DELAY: + return SPACESHIP_NUMBER(p1->swapin_delay_percent, p2->swapin_delay_percent); + case CTXT: + return SPACESHIP_NUMBER(p1->ctxt_diff, p2->ctxt_diff); + case SECATTR: + return SPACESHIP_NULLSTR(p1->secattr, p2->secattr); + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass PCPProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = PCPProcess_writeField, + .compareByKey = PCPProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,97 @@ +#ifndef HEADER_PCPProcess +#define HEADER_PCPProcess +/* +htop - PCPProcess.h +(C) 2014 Hisham H. Muhammad +(C) 2020 htop dev team +(C) 2020-2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +#include "Object.h" +#include "Process.h" +#include "RichString.h" +#include "Settings.h" + + +#define PROCESS_FLAG_LINUX_CGROUP 0x0800 +#define PROCESS_FLAG_LINUX_OOM 0x1000 +#define PROCESS_FLAG_LINUX_SMAPS 0x2000 +#define PROCESS_FLAG_LINUX_CTXT 0x4000 +#define PROCESS_FLAG_LINUX_SECATTR 0x8000 + +typedef struct PCPProcess_ { + Process super; + unsigned long int cminflt; + unsigned long int cmajflt; + unsigned long long int utime; + unsigned long long int stime; + unsigned long long int cutime; + unsigned long long int cstime; + long m_share; + long m_pss; + long m_swap; + long m_psswp; + long m_trs; + long m_drs; + long m_lrs; + long m_dt; + + /* Data read (in kilobytes) */ + unsigned long long io_rchar; + + /* Data written (in kilobytes) */ + unsigned long long io_wchar; + + /* Number of read(2) syscalls */ + unsigned long long io_syscr; + + /* Number of write(2) syscalls */ + unsigned long long io_syscw; + + /* Storage data read (in kilobytes) */ + unsigned long long io_read_bytes; + + /* Storage data written (in kilobytes) */ + unsigned long long io_write_bytes; + + /* Storage data cancelled (in kilobytes) */ + unsigned long long io_cancelled_write_bytes; + + /* Point in time of last io scan (in seconds elapsed since the Epoch) */ + unsigned long long io_last_scan_time; + + double io_rate_read_bps; + double io_rate_write_bps; + char* cgroup; + unsigned int oom; + unsigned long long int delay_read_time; + unsigned long long cpu_delay_total; + unsigned long long blkio_delay_total; + unsigned long long swapin_delay_total; + float cpu_delay_percent; + float blkio_delay_percent; + float swapin_delay_percent; + unsigned long ctxt_total; + unsigned long ctxt_diff; + char* secattr; + unsigned long long int last_mlrs_calctime; +} PCPProcess; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +extern const ProcessClass PCPProcess_class; + +Process* PCPProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +bool Process_isThread(const Process* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,673 @@ +/* +htop - PCPProcessList.c +(C) 2014 Hisham H. Muhammad +(C) 2020-2021 htop dev team +(C) 2020-2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "pcp/PCPProcessList.h" + +#include + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "Process.h" +#include "Settings.h" +#include "XUtils.h" + +#include "pcp/PCPProcess.h" + + +static int PCPProcessList_computeCPUcount(void) { + int cpus; + if ((cpus = Platform_getMaxCPU()) <= 0) + cpus = Metric_instanceCount(PCP_PERCPU_SYSTEM); + return cpus > 1 ? cpus : 1; +} + +static void PCPProcessList_updateCPUcount(PCPProcessList* this) { + ProcessList* pl = &(this->super); + unsigned int cpus = PCPProcessList_computeCPUcount(); + if (cpus == pl->cpuCount) + return; + + pl->cpuCount = cpus; + free(this->percpu); + free(this->values); + + this->percpu = xCalloc(cpus, sizeof(pmAtomValue *)); + for (unsigned int i = 0; i < cpus; i++) + this->percpu[i] = xCalloc(CPU_METRIC_COUNT, sizeof(pmAtomValue)); + this->values = xCalloc(cpus, sizeof(pmAtomValue)); +} + +static char* setUser(UsersTable* this, unsigned int uid, int pid, int offset) { + char* name = Hashtable_get(this->users, uid); + if (name) + return name; + + pmAtomValue value; + if (Metric_instance(PCP_PROC_ID_USER, pid, offset, &value, PM_TYPE_STRING)) { + Hashtable_put(this->users, uid, value.cp); + name = value.cp; + } + return name; +} + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + PCPProcessList* this = xCalloc(1, sizeof(PCPProcessList)); + ProcessList* super = &(this->super); + + ProcessList_init(super, Class(PCPProcess), usersTable, dynamicMeters, pidMatchList, userId); + + struct timeval timestamp; + gettimeofday(×tamp, NULL); + this->timestamp = pmtimevalToReal(×tamp); + + this->cpu = xCalloc(CPU_METRIC_COUNT, sizeof(pmAtomValue)); + PCPProcessList_updateCPUcount(this); + + return super; +} + +void ProcessList_delete(ProcessList* pl) { + PCPProcessList* this = (PCPProcessList*) pl; + ProcessList_done(pl); + free(this->values); + for (unsigned int i = 0; i < pl->cpuCount; i++) + free(this->percpu[i]); + free(this->percpu); + free(this->cpu); + free(this); +} + +static inline unsigned long Metric_instance_s32(int metric, int pid, int offset, unsigned long fallback) { + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_32)) + return value.l; + return fallback; +} + +static inline unsigned long Metric_instance_u32(int metric, int pid, int offset, unsigned long fallback) { + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_U32)) + return value.ul; + return fallback; +} + +static inline unsigned long long Metric_instance_u64(int metric, int pid, int offset, unsigned long long fallback) { + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_U64)) + return value.ull; + return fallback; +} + +static inline unsigned long long Metric_instance_time(int metric, int pid, int offset) { + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_U64)) + return value.ull / 10; + return 0; +} + +static inline unsigned long long Metric_instance_ONE_K(int metric, int pid, int offset) { + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_U64)) + return value.ull / ONE_K; + return ULLONG_MAX; +} + +static inline char Metric_instance_char(int metric, int pid, int offset, char fallback) { + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_STRING)) { + char uchar = value.cp[0]; + free(value.cp); + return uchar; + } + return fallback; +} + +static void PCPProcessList_updateID(Process* process, int pid, int offset) { + process->tgid = Metric_instance_u32(PCP_PROC_TGID, pid, offset, 1); + process->ppid = Metric_instance_u32(PCP_PROC_PPID, pid, offset, 1); + process->state = Metric_instance_char(PCP_PROC_STATE, pid, offset, '?'); +} + +static void PCPProcessList_updateInfo(Process* process, int pid, int offset, char* command, size_t commLen) { + PCPProcess* pp = (PCPProcess*) process; + pmAtomValue value; + + if (!Metric_instance(PCP_PROC_CMD, pid, offset, &value, PM_TYPE_STRING)) + value.cp = xStrdup(""); + String_safeStrncpy(command, value.cp, commLen); + free(value.cp); + + process->pgrp = Metric_instance_u32(PCP_PROC_PGRP, pid, offset, 0); + process->session = Metric_instance_u32(PCP_PROC_SESSION, pid, offset, 0); + process->tty_nr = Metric_instance_u32(PCP_PROC_TTY, pid, offset, 0); + process->tpgid = Metric_instance_u32(PCP_PROC_TTYPGRP, pid, offset, 0); + process->minflt = Metric_instance_u32(PCP_PROC_MINFLT, pid, offset, 0); + pp->cminflt = Metric_instance_u32(PCP_PROC_CMINFLT, pid, offset, 0); + process->majflt = Metric_instance_u32(PCP_PROC_MAJFLT, pid, offset, 0); + pp->cmajflt = Metric_instance_u32(PCP_PROC_CMAJFLT, pid, offset, 0); + pp->utime = Metric_instance_time(PCP_PROC_UTIME, pid, offset); + pp->stime = Metric_instance_time(PCP_PROC_STIME, pid, offset); + pp->cutime = Metric_instance_time(PCP_PROC_CUTIME, pid, offset); + pp->cstime = Metric_instance_time(PCP_PROC_CSTIME, pid, offset); + process->priority = Metric_instance_u32(PCP_PROC_PRIORITY, pid, offset, 0); + process->nice = Metric_instance_s32(PCP_PROC_NICE, pid, offset, 0); + process->nlwp = Metric_instance_u32(PCP_PROC_THREADS, pid, offset, 0); + process->starttime_ctime = Metric_instance_time(PCP_PROC_STARTTIME, pid, offset); + process->processor = Metric_instance_u32(PCP_PROC_PROCESSOR, pid, offset, 0); + + process->time = pp->utime + pp->stime; +} + +static void PCPProcessList_updateIO(PCPProcess* pp, int pid, int offset, unsigned long long now) { + pmAtomValue value; + + pp->io_rchar = Metric_instance_ONE_K(PCP_PROC_IO_RCHAR, pid, offset); + pp->io_wchar = Metric_instance_ONE_K(PCP_PROC_IO_WCHAR, pid, offset); + pp->io_syscr = Metric_instance_u64(PCP_PROC_IO_SYSCR, pid, offset, ULLONG_MAX); + pp->io_syscw = Metric_instance_u64(PCP_PROC_IO_SYSCW, pid, offset, ULLONG_MAX); + pp->io_cancelled_write_bytes = Metric_instance_ONE_K(PCP_PROC_IO_CANCELLED, pid, offset); + + if (Metric_instance(PCP_PROC_IO_READB, pid, offset, &value, PM_TYPE_U64)) { + unsigned long long last_read = pp->io_read_bytes; + pp->io_read_bytes = value.ull / ONE_K; + pp->io_rate_read_bps = ONE_K * (pp->io_read_bytes - last_read) / + (now - pp->io_last_scan_time); + } else { + pp->io_read_bytes = ULLONG_MAX; + pp->io_rate_read_bps = NAN; + } + + if (Metric_instance(PCP_PROC_IO_WRITEB, pid, offset, &value, PM_TYPE_U64)) { + unsigned long long last_write = pp->io_write_bytes; + pp->io_write_bytes = value.ull; + pp->io_rate_write_bps = ONE_K * (pp->io_write_bytes - last_write) / + (now - pp->io_last_scan_time); + } else { + pp->io_write_bytes = ULLONG_MAX; + pp->io_rate_write_bps = NAN; + } + + pp->io_last_scan_time = now; +} + +static void PCPProcessList_updateMemory(PCPProcess* pp, int pid, int offset) { + pp->super.m_virt = Metric_instance_u32(PCP_PROC_MEM_SIZE, pid, offset, 0); + pp->super.m_resident = Metric_instance_u32(PCP_PROC_MEM_RSS, pid, offset, 0); + pp->m_share = Metric_instance_u32(PCP_PROC_MEM_SHARE, pid, offset, 0); + pp->m_trs = Metric_instance_u32(PCP_PROC_MEM_TEXTRS, pid, offset, 0); + pp->m_lrs = Metric_instance_u32(PCP_PROC_MEM_LIBRS, pid, offset, 0); + pp->m_drs = Metric_instance_u32(PCP_PROC_MEM_DATRS, pid, offset, 0); + pp->m_dt = Metric_instance_u32(PCP_PROC_MEM_DIRTY, pid, offset, 0); +} + +static void PCPProcessList_updateSmaps(PCPProcess* pp, pid_t pid, int offset) { + pp->m_pss = Metric_instance_u64(PCP_PROC_SMAPS_PSS, pid, offset, 0); + pp->m_swap = Metric_instance_u64(PCP_PROC_SMAPS_SWAP, pid, offset, 0); + pp->m_psswp = Metric_instance_u64(PCP_PROC_SMAPS_SWAPPSS, pid, offset, 0); +} + +static void PCPProcessList_readOomData(PCPProcess* pp, int pid, int offset) { + pp->oom = Metric_instance_u32(PCP_PROC_OOMSCORE, pid, offset, 0); +} + +static void PCPProcessList_readCtxtData(PCPProcess* pp, int pid, int offset) { + pmAtomValue value; + unsigned long ctxt = 0; + + if (Metric_instance(PCP_PROC_VCTXSW, pid, offset, &value, PM_TYPE_U32)) + ctxt += value.ul; + if (Metric_instance(PCP_PROC_NVCTXSW, pid, offset, &value, PM_TYPE_U32)) + ctxt += value.ul; + + pp->ctxt_diff = ctxt > pp->ctxt_total ? ctxt - pp->ctxt_total : 0; + pp->ctxt_total = ctxt; +} + +static char* setString(Metric metric, int pid, int offset, char* string) { + if (string) + free(string); + pmAtomValue value; + if (Metric_instance(metric, pid, offset, &value, PM_TYPE_STRING)) + string = value.cp; + else + string = NULL; + return string; +} + +static void PCPProcessList_updateTTY(Process* process, int pid, int offset) { + process->tty_name = setString(PCP_PROC_TTYNAME, pid, offset, process->tty_name); +} + +static void PCPProcessList_readCGroups(PCPProcess* pp, int pid, int offset) { + pp->cgroup = setString(PCP_PROC_CGROUPS, pid, offset, pp->cgroup); +} + +static void PCPProcessList_readSecattrData(PCPProcess* pp, int pid, int offset) { + pp->secattr = setString(PCP_PROC_LABELS, pid, offset, pp->secattr); +} + +static void PCPProcessList_readCwd(PCPProcess* pp, int pid, int offset) { + pp->super.procCwd = setString(PCP_PROC_CWD, pid, offset, pp->super.procCwd); +} + +static void PCPProcessList_updateUsername(Process* process, int pid, int offset, UsersTable* users) { + process->st_uid = Metric_instance_u32(PCP_PROC_ID_UID, pid, offset, 0); + process->user = setUser(users, process->st_uid, pid, offset); +} + +static void PCPProcessList_updateCmdline(Process* process, int pid, int offset, const char* comm) { + pmAtomValue value; + if (!Metric_instance(PCP_PROC_PSARGS, pid, offset, &value, PM_TYPE_STRING)) { + if (process->state != 'Z') + process->isKernelThread = true; + Process_updateCmdline(process, NULL, 0, 0); + return; + } + + char* command = value.cp; + int length = strlen(command); + if (command[0] != '(') { + process->isKernelThread = false; + } else { + ++command; + --length; + if (command[length - 1] == ')') + command[--length] = '\0'; + process->isKernelThread = true; + } + + int tokenStart = 0; + for (int i = 0; i < length; i++) { + /* htop considers the next character after the last / that is before + * basenameOffset, as the start of the basename in cmdline - see + * Process_writeCommand */ + if (command[i] == '/') + tokenStart = i + 1; + } + int tokenEnd = length; + + Process_updateCmdline(process, command, tokenStart, tokenEnd); + free(value.cp); + + Process_updateComm(process, comm); + + if (Metric_instance(PCP_PROC_EXE, pid, offset, &value, PM_TYPE_STRING)) { + Process_updateExe(process, value.cp); + free(value.cp); + } +} + +static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period, struct timeval* tv) { + ProcessList* pl = (ProcessList*) this; + const Settings* settings = pl->settings; + + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + + unsigned long long now = tv->tv_sec * 1000LL + tv->tv_usec / 1000LL; + int pid = -1, offset = -1; + + /* for every process ... */ + while (Metric_iterate(PCP_PROC_PID, &pid, &offset)) { + + bool preExisting; + Process* proc = ProcessList_getProcess(pl, pid, &preExisting, PCPProcess_new); + PCPProcess* pp = (PCPProcess*) proc; + PCPProcessList_updateID(proc, pid, offset); + proc->isUserlandThread = proc->pid != proc->tgid; + + /* + * These conditions will not trigger on first occurrence, cause we need to + * add the process to the ProcessList and do all one time scans + * (e.g. parsing the cmdline to detect a kernel thread) + * But it will short-circuit subsequent scans. + */ + if (preExisting && hideKernelThreads && Process_isKernelThread(proc)) { + proc->updated = true; + proc->show = false; + if (proc->state == 'R') + pl->runningTasks++; + pl->kernelThreads++; + pl->totalTasks++; + continue; + } + if (preExisting && hideUserlandThreads && Process_isUserlandThread(proc)) { + proc->updated = true; + proc->show = false; + if (proc->state == 'R') + pl->runningTasks++; + pl->userlandThreads++; + pl->totalTasks++; + continue; + } + + if (settings->flags & PROCESS_FLAG_IO) + PCPProcessList_updateIO(pp, pid, offset, now); + + PCPProcessList_updateMemory(pp, pid, offset); + + if ((settings->flags & PROCESS_FLAG_LINUX_SMAPS) && + (Process_isKernelThread(proc) == false)) { + if (Metric_enabled(PCP_PROC_SMAPS_PSS)) + PCPProcessList_updateSmaps(pp, pid, offset); + } + + char command[MAX_NAME + 1]; + unsigned int tty_nr = proc->tty_nr; + unsigned long long int lasttimes = pp->utime + pp->stime; + + PCPProcessList_updateInfo(proc, pid, offset, command, sizeof(command)); + proc->starttime_ctime += Platform_getBootTime(); + if (tty_nr != proc->tty_nr) + PCPProcessList_updateTTY(proc, pid, offset); + + float percent_cpu = (pp->utime + pp->stime - lasttimes) / period * 100.0; + proc->percent_cpu = isnan(percent_cpu) ? + 0.0 : CLAMP(percent_cpu, 0.0, pl->cpuCount * 100.0); + proc->percent_mem = proc->m_resident / (double)pl->totalMem * 100.0; + + PCPProcessList_updateUsername(proc, pid, offset, pl->usersTable); + + if (!preExisting) { + PCPProcessList_updateCmdline(proc, pid, offset, command); + Process_fillStarttimeBuffer(proc); + ProcessList_add(pl, proc); + } else if (settings->updateProcessNames && proc->state != 'Z') { + PCPProcessList_updateCmdline(proc, pid, offset, command); + } + + if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) + PCPProcessList_readCGroups(pp, pid, offset); + + if (settings->flags & PROCESS_FLAG_LINUX_OOM) + PCPProcessList_readOomData(pp, pid, offset); + + if (settings->flags & PROCESS_FLAG_LINUX_CTXT) + PCPProcessList_readCtxtData(pp, pid, offset); + + if (settings->flags & PROCESS_FLAG_LINUX_SECATTR) + PCPProcessList_readSecattrData(pp, pid, offset); + + if (settings->flags & PROCESS_FLAG_CWD) + PCPProcessList_readCwd(pp, pid, offset); + + if (proc->state == 'Z' && !proc->cmdline && command[0]) { + Process_updateCmdline(proc, command, 0, strlen(command)); + } else if (Process_isThread(proc)) { + if ((settings->showThreadNames || Process_isKernelThread(proc)) && command[0]) { + Process_updateCmdline(proc, command, 0, strlen(command)); + } + + if (Process_isKernelThread(proc)) { + pl->kernelThreads++; + } else { + pl->userlandThreads++; + } + } + + /* Set at the end when we know if a new entry is a thread */ + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || + (hideUserlandThreads && Process_isUserlandThread(proc))); + + pl->totalTasks++; + if (proc->state == 'R') + pl->runningTasks++; + proc->updated = true; + } + return true; +} + +static void PCPProcessList_updateMemoryInfo(ProcessList* super) { + unsigned long long int freeMem = 0; + unsigned long long int swapFreeMem = 0; + unsigned long long int sreclaimableMem = 0; + super->totalMem = super->usedMem = super->cachedMem = 0; + super->usedSwap = super->totalSwap = super->sharedMem = 0; + + pmAtomValue value; + if (Metric_values(PCP_MEM_TOTAL, &value, 1, PM_TYPE_U64) != NULL) + super->totalMem = value.ull; + if (Metric_values(PCP_MEM_FREE, &value, 1, PM_TYPE_U64) != NULL) + freeMem = value.ull; + if (Metric_values(PCP_MEM_BUFFERS, &value, 1, PM_TYPE_U64) != NULL) + super->buffersMem = value.ull; + if (Metric_values(PCP_MEM_SRECLAIM, &value, 1, PM_TYPE_U64) != NULL) + sreclaimableMem = value.ull; + if (Metric_values(PCP_MEM_SHARED, &value, 1, PM_TYPE_U64) != NULL) + super->sharedMem = value.ull; + if (Metric_values(PCP_MEM_CACHED, &value, 1, PM_TYPE_U64) != NULL) + super->cachedMem = value.ull + sreclaimableMem - super->sharedMem; + const memory_t usedDiff = freeMem + super->cachedMem + sreclaimableMem + super->buffersMem; + super->usedMem = (super->totalMem >= usedDiff) ? + super->totalMem - usedDiff : super->totalMem - freeMem; + if (Metric_values(PCP_MEM_AVAILABLE, &value, 1, PM_TYPE_U64) != NULL) + super->availableMem = MINIMUM(value.ull, super->totalMem); + else + super->availableMem = freeMem; + if (Metric_values(PCP_MEM_SWAPFREE, &value, 1, PM_TYPE_U64) != NULL) + swapFreeMem = value.ull; + if (Metric_values(PCP_MEM_SWAPTOTAL, &value, 1, PM_TYPE_U64) != NULL) + super->totalSwap = value.ull; + if (Metric_values(PCP_MEM_SWAPCACHED, &value, 1, PM_TYPE_U64) != NULL) + super->cachedSwap = value.ull; + super->usedSwap = super->totalSwap - swapFreeMem - super->cachedSwap; +} + +/* make copies of previously sampled values to avoid overwrite */ +static inline void PCPProcessList_backupCPUTime(pmAtomValue* values) { + /* the PERIOD fields (must) mirror the TIME fields */ + for (int metric = CPU_TOTAL_TIME; metric < CPU_TOTAL_PERIOD; metric++) { + values[metric + CPU_TOTAL_PERIOD] = values[metric]; + } +} + +static inline void PCPProcessList_saveCPUTimePeriod(pmAtomValue* values, CPUMetric previous, pmAtomValue* latest) { + pmAtomValue* value; + + /* new value for period */ + value = &values[previous]; + if (latest->ull > value->ull) + value->ull = latest->ull - value->ull; + else + value->ull = 0; + + /* new value for time */ + value = &values[previous - CPU_TOTAL_PERIOD]; + value->ull = latest->ull; +} + +/* using copied sampled values and new values, calculate derivations */ +static void PCPProcessList_deriveCPUTime(pmAtomValue* values) { + + pmAtomValue* usertime = &values[CPU_USER_TIME]; + pmAtomValue* guesttime = &values[CPU_GUEST_TIME]; + usertime->ull -= guesttime->ull; + + pmAtomValue* nicetime = &values[CPU_NICE_TIME]; + pmAtomValue* guestnicetime = &values[CPU_GUESTNICE_TIME]; + nicetime->ull -= guestnicetime->ull; + + pmAtomValue* idletime = &values[CPU_IDLE_TIME]; + pmAtomValue* iowaittime = &values[CPU_IOWAIT_TIME]; + pmAtomValue* idlealltime = &values[CPU_IDLE_ALL_TIME]; + idlealltime->ull = idletime->ull + iowaittime->ull; + + pmAtomValue* systemtime = &values[CPU_SYSTEM_TIME]; + pmAtomValue* irqtime = &values[CPU_IRQ_TIME]; + pmAtomValue* softirqtime = &values[CPU_SOFTIRQ_TIME]; + pmAtomValue* systalltime = &values[CPU_SYSTEM_ALL_TIME]; + systalltime->ull = systemtime->ull + irqtime->ull + softirqtime->ull; + + pmAtomValue* virtalltime = &values[CPU_GUEST_TIME]; + virtalltime->ull = guesttime->ull + guestnicetime->ull; + + pmAtomValue* stealtime = &values[CPU_STEAL_TIME]; + pmAtomValue* totaltime = &values[CPU_TOTAL_TIME]; + totaltime->ull = usertime->ull + nicetime->ull + systalltime->ull + + idlealltime->ull + stealtime->ull + virtalltime->ull; + + PCPProcessList_saveCPUTimePeriod(values, CPU_USER_PERIOD, usertime); + PCPProcessList_saveCPUTimePeriod(values, CPU_NICE_PERIOD, nicetime); + PCPProcessList_saveCPUTimePeriod(values, CPU_SYSTEM_PERIOD, systemtime); + PCPProcessList_saveCPUTimePeriod(values, CPU_SYSTEM_ALL_PERIOD, systalltime); + PCPProcessList_saveCPUTimePeriod(values, CPU_IDLE_ALL_PERIOD, idlealltime); + PCPProcessList_saveCPUTimePeriod(values, CPU_IDLE_PERIOD, idletime); + PCPProcessList_saveCPUTimePeriod(values, CPU_IOWAIT_PERIOD, iowaittime); + PCPProcessList_saveCPUTimePeriod(values, CPU_IRQ_PERIOD, irqtime); + PCPProcessList_saveCPUTimePeriod(values, CPU_SOFTIRQ_PERIOD, softirqtime); + PCPProcessList_saveCPUTimePeriod(values, CPU_STEAL_PERIOD, stealtime); + PCPProcessList_saveCPUTimePeriod(values, CPU_GUEST_PERIOD, virtalltime); + PCPProcessList_saveCPUTimePeriod(values, CPU_TOTAL_PERIOD, totaltime); +} + +static void PCPProcessList_updateAllCPUTime(PCPProcessList* this, Metric metric, CPUMetric cpumetric) +{ + pmAtomValue* value = &this->cpu[cpumetric]; + if (Metric_values(metric, value, 1, PM_TYPE_U64) == NULL) + memset(&value, 0, sizeof(pmAtomValue)); +} + +static void PCPProcessList_updatePerCPUTime(PCPProcessList* this, Metric metric, CPUMetric cpumetric) +{ + int cpus = this->super.cpuCount; + if (Metric_values(metric, this->values, cpus, PM_TYPE_U64) == NULL) + memset(this->values, 0, cpus * sizeof(pmAtomValue)); + for (int i = 0; i < cpus; i++) + this->percpu[i][cpumetric].ull = this->values[i].ull; +} + +static void PCPProcessList_updatePerCPUReal(PCPProcessList* this, Metric metric, CPUMetric cpumetric) +{ + int cpus = this->super.cpuCount; + if (Metric_values(metric, this->values, cpus, PM_TYPE_DOUBLE) == NULL) + memset(this->values, 0, cpus * sizeof(pmAtomValue)); + for (int i = 0; i < cpus; i++) + this->percpu[i][cpumetric].d = this->values[i].d; +} + +static inline void PCPProcessList_scanZfsArcstats(PCPProcessList* this) { + unsigned long long int dbufSize = 0; + unsigned long long int dnodeSize = 0; + unsigned long long int bonusSize = 0; + pmAtomValue value; + + memset(&this->zfs, 0, sizeof(ZfsArcStats)); + if (Metric_values(PCP_ZFS_ARC_ANON_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.anon = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_C_MAX, &value, 1, PM_TYPE_U64)) + this->zfs.max = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_BONUS_SIZE, &value, 1, PM_TYPE_U64)) + bonusSize = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_DBUF_SIZE, &value, 1, PM_TYPE_U64)) + dbufSize = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_DNODE_SIZE, &value, 1, PM_TYPE_U64)) + dnodeSize = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_COMPRESSED_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.compressed = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_UNCOMPRESSED_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.uncompressed = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_HDR_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.header = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_MFU_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.MFU = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_MRU_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.MRU = value.ull / ONE_K; + if (Metric_values(PCP_ZFS_ARC_SIZE, &value, 1, PM_TYPE_U64)) + this->zfs.size = value.ull / ONE_K; + + this->zfs.other = (dbufSize + dnodeSize + bonusSize) / ONE_K; + this->zfs.enabled = (this->zfs.size > 0); + this->zfs.isCompressed = (this->zfs.compressed > 0); +} + +static void PCPProcessList_updateHeader(ProcessList* super, const Settings* settings) { + PCPProcessList_updateMemoryInfo(super); + + PCPProcessList* this = (PCPProcessList*) super; + PCPProcessList_updateCPUcount(this); + + PCPProcessList_backupCPUTime(this->cpu); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_USER, CPU_USER_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_NICE, CPU_NICE_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_SYSTEM, CPU_SYSTEM_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_IDLE, CPU_IDLE_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_IOWAIT, CPU_IOWAIT_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_IRQ, CPU_IRQ_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_SOFTIRQ, CPU_SOFTIRQ_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_STEAL, CPU_STEAL_TIME); + PCPProcessList_updateAllCPUTime(this, PCP_CPU_GUEST, CPU_GUEST_TIME); + PCPProcessList_deriveCPUTime(this->cpu); + + for (unsigned int i = 0; i < super->cpuCount; i++) + PCPProcessList_backupCPUTime(this->percpu[i]); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_USER, CPU_USER_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_NICE, CPU_NICE_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_SYSTEM, CPU_SYSTEM_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_IDLE, CPU_IDLE_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_IOWAIT, CPU_IOWAIT_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_IRQ, CPU_IRQ_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_SOFTIRQ, CPU_SOFTIRQ_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_STEAL, CPU_STEAL_TIME); + PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_GUEST, CPU_GUEST_TIME); + for (unsigned int i = 0; i < super->cpuCount; i++) + PCPProcessList_deriveCPUTime(this->percpu[i]); + + if (settings->showCPUFrequency) + PCPProcessList_updatePerCPUReal(this, PCP_HINV_CPUCLOCK, CPU_FREQUENCY); + + PCPProcessList_scanZfsArcstats(this); +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + PCPProcessList* this = (PCPProcessList*) super; + const Settings* settings = super->settings; + bool enabled = !pauseProcessUpdate; + + bool flagged = settings->showCPUFrequency; + Metric_enable(PCP_HINV_CPUCLOCK, flagged); + + /* In pause mode do not sample per-process metric values at all */ + for (int metric = PCP_PROC_PID; metric < PCP_METRIC_COUNT; metric++) + Metric_enable(metric, enabled); + + flagged = settings->flags & PROCESS_FLAG_LINUX_CGROUP; + Metric_enable(PCP_PROC_CGROUPS, flagged && enabled); + flagged = settings->flags & PROCESS_FLAG_LINUX_OOM; + Metric_enable(PCP_PROC_OOMSCORE, flagged && enabled); + flagged = settings->flags & PROCESS_FLAG_LINUX_CTXT; + Metric_enable(PCP_PROC_VCTXSW, flagged && enabled); + Metric_enable(PCP_PROC_NVCTXSW, flagged && enabled); + flagged = settings->flags & PROCESS_FLAG_LINUX_SECATTR; + Metric_enable(PCP_PROC_LABELS, flagged && enabled); + + /* Sample smaps metrics on every second pass to improve performance */ + static int smaps_flag; + smaps_flag = !!smaps_flag; + Metric_enable(PCP_PROC_SMAPS_PSS, smaps_flag && enabled); + Metric_enable(PCP_PROC_SMAPS_SWAP, smaps_flag && enabled); + Metric_enable(PCP_PROC_SMAPS_SWAPPSS, smaps_flag && enabled); + + struct timeval timestamp; + Metric_fetch(×tamp); + + double sample = this->timestamp; + this->timestamp = pmtimevalToReal(×tamp); + + PCPProcessList_updateHeader(super, settings); + + /* In pause mode only update global data for meters (CPU, memory, etc) */ + if (pauseProcessUpdate) + return; + + double period = (this->timestamp - sample) * 100; + PCPProcessList_updateProcesses(this, period, ×tamp); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/PCPProcessList.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,72 @@ +#ifndef HEADER_PCPProcessList +#define HEADER_PCPProcessList +/* +htop - PCPProcessList.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" + +#include "pcp/Platform.h" +#include "zfs/ZfsArcStats.h" + + +typedef enum CPUMetric_ { + CPU_TOTAL_TIME, + CPU_USER_TIME, + CPU_SYSTEM_TIME, + CPU_SYSTEM_ALL_TIME, + CPU_IDLE_ALL_TIME, + CPU_IDLE_TIME, + CPU_NICE_TIME, + CPU_IOWAIT_TIME, + CPU_IRQ_TIME, + CPU_SOFTIRQ_TIME, + CPU_STEAL_TIME, + CPU_GUEST_TIME, + CPU_GUESTNICE_TIME, + + CPU_TOTAL_PERIOD, + CPU_USER_PERIOD, + CPU_SYSTEM_PERIOD, + CPU_SYSTEM_ALL_PERIOD, + CPU_IDLE_ALL_PERIOD, + CPU_IDLE_PERIOD, + CPU_NICE_PERIOD, + CPU_IOWAIT_PERIOD, + CPU_IRQ_PERIOD, + CPU_SOFTIRQ_PERIOD, + CPU_STEAL_PERIOD, + CPU_GUEST_PERIOD, + CPU_GUESTNICE_PERIOD, + + CPU_FREQUENCY, + + CPU_METRIC_COUNT +} CPUMetric; + +typedef struct PCPProcessList_ { + ProcessList super; + double timestamp; /* previous sample timestamp */ + pmAtomValue* cpu; /* aggregate values for each metric */ + pmAtomValue** percpu; /* per-processor values for each metric */ + pmAtomValue* values; /* per-processor buffer for just one metric */ + ZfsArcStats zfs; +} PCPProcessList; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* pl); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/Platform.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,926 @@ +/* +htop - linux/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2020-2021 htop dev team +(C) 2020-2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "pcp/Platform.h" + +#include + +#include "BatteryMeter.h" +#include "ClockMeter.h" +#include "Compat.h" +#include "CPUMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "DiskIOMeter.h" +#include "DynamicMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MainPanel.h" +#include "MemoryMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Object.h" +#include "Panel.h" +#include "ProcessList.h" +#include "ProvideCurses.h" +#include "Settings.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" +#include "XUtils.h" + +#include "linux/PressureStallMeter.h" +#include "linux/ZramMeter.h" +#include "linux/ZramStats.h" +#include "pcp/PCPDynamicMeter.h" +#include "pcp/PCPProcess.h" +#include "pcp/PCPProcessList.h" +#include "zfs/ZfsArcMeter.h" +#include "zfs/ZfsArcStats.h" +#include "zfs/ZfsCompressedArcMeter.h" + + +typedef struct Platform_ { + int context; /* PMAPI(3) context identifier */ + unsigned int totalMetrics; /* total number of all metrics */ + const char** names; /* name array indexed by Metric */ + pmID* pmids; /* all known metric identifiers */ + pmID* fetch; /* enabled identifiers for sampling */ + pmDesc* descs; /* metric desc array indexed by Metric */ + pmResult* result; /* sample values result indexed by Metric */ + PCPDynamicMeters meters; /* dynamic meters via configuration files */ + struct timeval offset; /* time offset used in archive mode only */ + long long btime; /* boottime in seconds since the epoch */ + char* release; /* uname and distro from this context */ + int pidmax; /* maximum platform process identifier */ + int ncpu; /* maximum processor count configured */ +} Platform; + +Platform* pcp; + +ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, (int)M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +int Platform_numberOfFields = LAST_PROCESSFIELD; + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &DynamicMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + &PressureStallCPUSomeMeter_class, + &PressureStallIOSomeMeter_class, + &PressureStallIOFullMeter_class, + &PressureStallMemorySomeMeter_class, + &PressureStallMemoryFullMeter_class, + &ZfsArcMeter_class, + &ZfsCompressedArcMeter_class, + &ZramMeter_class, + &DiskIOMeter_class, + &NetworkIOMeter_class, + &SysArchMeter_class, + NULL +}; + +static const char* Platform_metricNames[] = { + [PCP_CONTROL_THREADS] = "proc.control.perclient.threads", + + [PCP_HINV_NCPU] = "hinv.ncpu", + [PCP_HINV_CPUCLOCK] = "hinv.cpu.clock", + [PCP_UNAME_SYSNAME] = "kernel.uname.sysname", + [PCP_UNAME_RELEASE] = "kernel.uname.release", + [PCP_UNAME_MACHINE] = "kernel.uname.machine", + [PCP_UNAME_DISTRO] = "kernel.uname.distro", + [PCP_LOAD_AVERAGE] = "kernel.all.load", + [PCP_PID_MAX] = "kernel.all.pid_max", + [PCP_UPTIME] = "kernel.all.uptime", + [PCP_BOOTTIME] = "kernel.all.boottime", + [PCP_CPU_USER] = "kernel.all.cpu.user", + [PCP_CPU_NICE] = "kernel.all.cpu.nice", + [PCP_CPU_SYSTEM] = "kernel.all.cpu.sys", + [PCP_CPU_IDLE] = "kernel.all.cpu.idle", + [PCP_CPU_IOWAIT] = "kernel.all.cpu.wait.total", + [PCP_CPU_IRQ] = "kernel.all.cpu.intr", + [PCP_CPU_SOFTIRQ] = "kernel.all.cpu.irq.soft", + [PCP_CPU_STEAL] = "kernel.all.cpu.steal", + [PCP_CPU_GUEST] = "kernel.all.cpu.guest", + [PCP_CPU_GUESTNICE] = "kernel.all.cpu.guest_nice", + [PCP_PERCPU_USER] = "kernel.percpu.cpu.user", + [PCP_PERCPU_NICE] = "kernel.percpu.cpu.nice", + [PCP_PERCPU_SYSTEM] = "kernel.percpu.cpu.sys", + [PCP_PERCPU_IDLE] = "kernel.percpu.cpu.idle", + [PCP_PERCPU_IOWAIT] = "kernel.percpu.cpu.wait.total", + [PCP_PERCPU_IRQ] = "kernel.percpu.cpu.intr", + [PCP_PERCPU_SOFTIRQ] = "kernel.percpu.cpu.irq.soft", + [PCP_PERCPU_STEAL] = "kernel.percpu.cpu.steal", + [PCP_PERCPU_GUEST] = "kernel.percpu.cpu.guest", + [PCP_PERCPU_GUESTNICE] = "kernel.percpu.cpu.guest_nice", + [PCP_MEM_TOTAL] = "mem.physmem", + [PCP_MEM_FREE] = "mem.util.free", + [PCP_MEM_AVAILABLE] = "mem.util.available", + [PCP_MEM_BUFFERS] = "mem.util.bufmem", + [PCP_MEM_CACHED] = "mem.util.cached", + [PCP_MEM_SHARED] = "mem.util.shmem", + [PCP_MEM_SRECLAIM] = "mem.util.slabReclaimable", + [PCP_MEM_SWAPCACHED] = "mem.util.swapCached", + [PCP_MEM_SWAPTOTAL] = "mem.util.swapTotal", + [PCP_MEM_SWAPFREE] = "mem.util.swapFree", + [PCP_DISK_READB] = "disk.all.read_bytes", + [PCP_DISK_WRITEB] = "disk.all.write_bytes", + [PCP_DISK_ACTIVE] = "disk.all.avactive", + [PCP_NET_RECVB] = "network.all.in.bytes", + [PCP_NET_SENDB] = "network.all.out.bytes", + [PCP_NET_RECVP] = "network.all.in.packets", + [PCP_NET_SENDP] = "network.all.out.packets", + + [PCP_PSI_CPUSOME] = "kernel.all.pressure.cpu.some.avg", + [PCP_PSI_IOSOME] = "kernel.all.pressure.io.some.avg", + [PCP_PSI_IOFULL] = "kernel.all.pressure.io.full.avg", + [PCP_PSI_MEMSOME] = "kernel.all.pressure.memory.some.avg", + [PCP_PSI_MEMFULL] = "kernel.all.pressure.memory.full.avg", + + [PCP_ZFS_ARC_ANON_SIZE] = "zfs.arc.anon_size", + [PCP_ZFS_ARC_BONUS_SIZE] = "zfs.arc.bonus_size", + [PCP_ZFS_ARC_COMPRESSED_SIZE] = "zfs.arc.compressed_size", + [PCP_ZFS_ARC_UNCOMPRESSED_SIZE] = "zfs.arc.uncompressed_size", + [PCP_ZFS_ARC_C_MAX] = "zfs.arc.c_max", + [PCP_ZFS_ARC_DBUF_SIZE] = "zfs.arc.dbuf_size", + [PCP_ZFS_ARC_DNODE_SIZE] = "zfs.arc.dnode_size", + [PCP_ZFS_ARC_HDR_SIZE] = "zfs.arc.hdr_size", + [PCP_ZFS_ARC_MFU_SIZE] = "zfs.arc.mfu.size", + [PCP_ZFS_ARC_MRU_SIZE] = "zfs.arc.mru.size", + [PCP_ZFS_ARC_SIZE] = "zfs.arc.size", + + [PCP_ZRAM_CAPACITY] = "zram.capacity", + [PCP_ZRAM_ORIGINAL] = "zram.mm_stat.data_size.original", + [PCP_ZRAM_COMPRESSED] = "zram.mm_stat.data_size.compressed", + + [PCP_PROC_PID] = "proc.psinfo.pid", + [PCP_PROC_PPID] = "proc.psinfo.ppid", + [PCP_PROC_TGID] = "proc.psinfo.tgid", + [PCP_PROC_PGRP] = "proc.psinfo.pgrp", + [PCP_PROC_SESSION] = "proc.psinfo.session", + [PCP_PROC_STATE] = "proc.psinfo.sname", + [PCP_PROC_TTY] = "proc.psinfo.tty", + [PCP_PROC_TTYPGRP] = "proc.psinfo.tty_pgrp", + [PCP_PROC_MINFLT] = "proc.psinfo.minflt", + [PCP_PROC_MAJFLT] = "proc.psinfo.maj_flt", + [PCP_PROC_CMINFLT] = "proc.psinfo.cmin_flt", + [PCP_PROC_CMAJFLT] = "proc.psinfo.cmaj_flt", + [PCP_PROC_UTIME] = "proc.psinfo.utime", + [PCP_PROC_STIME] = "proc.psinfo.stime", + [PCP_PROC_CUTIME] = "proc.psinfo.cutime", + [PCP_PROC_CSTIME] = "proc.psinfo.cstime", + [PCP_PROC_PRIORITY] = "proc.psinfo.priority", + [PCP_PROC_NICE] = "proc.psinfo.nice", + [PCP_PROC_THREADS] = "proc.psinfo.threads", + [PCP_PROC_STARTTIME] = "proc.psinfo.start_time", + [PCP_PROC_PROCESSOR] = "proc.psinfo.processor", + [PCP_PROC_CMD] = "proc.psinfo.cmd", + [PCP_PROC_PSARGS] = "proc.psinfo.psargs", + [PCP_PROC_CGROUPS] = "proc.psinfo.cgroups", + [PCP_PROC_OOMSCORE] = "proc.psinfo.oom_score", + [PCP_PROC_VCTXSW] = "proc.psinfo.vctxsw", + [PCP_PROC_NVCTXSW] = "proc.psinfo.nvctxsw", + [PCP_PROC_LABELS] = "proc.psinfo.labels", + [PCP_PROC_ENVIRON] = "proc.psinfo.environ", + [PCP_PROC_TTYNAME] = "proc.psinfo.ttyname", + [PCP_PROC_EXE] = "proc.psinfo.exe", + [PCP_PROC_CWD] = "proc.psinfo.cwd", + [PCP_PROC_ID_UID] = "proc.id.uid", + [PCP_PROC_ID_USER] = "proc.id.uid_nm", + [PCP_PROC_IO_RCHAR] = "proc.io.rchar", + [PCP_PROC_IO_WCHAR] = "proc.io.wchar", + [PCP_PROC_IO_SYSCR] = "proc.io.syscr", + [PCP_PROC_IO_SYSCW] = "proc.io.syscw", + [PCP_PROC_IO_READB] = "proc.io.read_bytes", + [PCP_PROC_IO_WRITEB] = "proc.io.write_bytes", + [PCP_PROC_IO_CANCELLED] = "proc.io.cancelled_write_bytes", + [PCP_PROC_MEM_SIZE] = "proc.memory.size", + [PCP_PROC_MEM_RSS] = "proc.memory.rss", + [PCP_PROC_MEM_SHARE] = "proc.memory.share", + [PCP_PROC_MEM_TEXTRS] = "proc.memory.textrss", + [PCP_PROC_MEM_LIBRS] = "proc.memory.librss", + [PCP_PROC_MEM_DATRS] = "proc.memory.datrss", + [PCP_PROC_MEM_DIRTY] = "proc.memory.dirty", + [PCP_PROC_SMAPS_PSS] = "proc.smaps.pss", + [PCP_PROC_SMAPS_SWAP] = "proc.smaps.swap", + [PCP_PROC_SMAPS_SWAPPSS] = "proc.smaps.swappss", + + [PCP_METRIC_COUNT] = NULL +}; + +const pmDesc* Metric_desc(Metric metric) { + return &pcp->descs[metric]; +} + +pmAtomValue* Metric_values(Metric metric, pmAtomValue* atom, int count, int type) { + if (pcp->result == NULL) + return NULL; + + pmValueSet* vset = pcp->result->vset[metric]; + if (!vset || vset->numval <= 0) + return NULL; + + /* extract requested number of values as requested type */ + const pmDesc* desc = &pcp->descs[metric]; + for (int i = 0; i < vset->numval; i++) { + if (i == count) + break; + const pmValue* value = &vset->vlist[i]; + int sts = pmExtractValue(vset->valfmt, value, desc->type, &atom[i], type); + if (sts < 0) { + if (pmDebugOptions.appl0) + fprintf(stderr, "Error: cannot extract metric value: %s\n", + pmErrStr(sts)); + memset(&atom[i], 0, sizeof(pmAtomValue)); + } + } + return atom; +} + +int Metric_instanceCount(Metric metric) { + pmValueSet* vset = pcp->result->vset[metric]; + if (vset) + return vset->numval; + return 0; +} + +int Metric_instanceOffset(Metric metric, int inst) { + pmValueSet* vset = pcp->result->vset[metric]; + if (!vset || vset->numval <= 0) + return 0; + + /* search for optimal offset for subsequent inst lookups to begin */ + for (int i = 0; i < vset->numval; i++) { + if (inst == vset->vlist[i].inst) + return i; + } + return 0; +} + +static pmAtomValue* Metric_extract(Metric metric, int inst, int offset, pmValueSet* vset, pmAtomValue* atom, int type) { + + /* extract value (using requested type) of given metric instance */ + const pmDesc* desc = &pcp->descs[metric]; + const pmValue* value = &vset->vlist[offset]; + int sts = pmExtractValue(vset->valfmt, value, desc->type, atom, type); + if (sts < 0) { + if (pmDebugOptions.appl0) + fprintf(stderr, "Error: cannot extract %s instance %d value: %s\n", + pcp->names[metric], inst, pmErrStr(sts)); + memset(atom, 0, sizeof(pmAtomValue)); + } + return atom; +} + +pmAtomValue* Metric_instance(Metric metric, int inst, int offset, pmAtomValue* atom, int type) { + + pmValueSet* vset = pcp->result->vset[metric]; + if (!vset || vset->numval <= 0) + return NULL; + + /* fast-path using heuristic offset based on expected location */ + if (offset >= 0 && offset < vset->numval && inst == vset->vlist[offset].inst) + return Metric_extract(metric, inst, offset, vset, atom, type); + + /* slow-path using a linear search for the requested instance */ + for (int i = 0; i < vset->numval; i++) { + if (inst == vset->vlist[i].inst) + return Metric_extract(metric, inst, i, vset, atom, type); + } + return NULL; +} + +/* + * Iterate over a set of instances (incl PM_IN_NULL) + * returning the next instance identifier and offset. + * + * Start it off by passing offset -1 into the routine. + */ +bool Metric_iterate(Metric metric, int* instp, int* offsetp) { + if (!pcp->result) + return false; + + pmValueSet* vset = pcp->result->vset[metric]; + if (!vset || vset->numval <= 0) + return false; + + int offset = *offsetp; + offset = (offset < 0) ? 0 : offset + 1; + if (offset > vset->numval - 1) + return false; + + *offsetp = offset; + *instp = vset->vlist[offset].inst; + return true; +} + +/* Switch on/off a metric for value fetching (sampling) */ +void Metric_enable(Metric metric, bool enable) { + pcp->fetch[metric] = enable ? pcp->pmids[metric] : PM_ID_NULL; +} + +bool Metric_enabled(Metric metric) { + return pcp->fetch[metric] != PM_ID_NULL; +} + +void Metric_enableThreads(void) { + pmValueSet* vset = xCalloc(1, sizeof(pmValueSet)); + vset->vlist[0].inst = PM_IN_NULL; + vset->vlist[0].value.lval = 1; + vset->valfmt = PM_VAL_INSITU; + vset->numval = 1; + vset->pmid = pcp->pmids[PCP_CONTROL_THREADS]; + + pmResult* result = xCalloc(1, sizeof(pmResult)); + result->vset[0] = vset; + result->numpmid = 1; + + int sts = pmStore(result); + if (sts < 0 && pmDebugOptions.appl0) + fprintf(stderr, "Error: cannot enable threads: %s\n", pmErrStr(sts)); + + pmFreeResult(result); +} + +bool Metric_fetch(struct timeval* timestamp) { + if (pcp->result) { + pmFreeResult(pcp->result); + pcp->result = NULL; + } + int sts = pmFetch(pcp->totalMetrics, pcp->fetch, &pcp->result); + if (sts < 0) { + if (pmDebugOptions.appl0) + fprintf(stderr, "Error: cannot fetch metric values: %s\n", + pmErrStr(sts)); + return false; + } + if (timestamp) + *timestamp = pcp->result->timestamp; + return true; +} + +int Platform_addMetric(Metric id, const char* name) { + unsigned int i = (unsigned int)id; + + if (i >= PCP_METRIC_COUNT && i >= pcp->totalMetrics) { + /* added via configuration files */ + unsigned int j = pcp->totalMetrics + 1; + pcp->fetch = xRealloc(pcp->fetch, j * sizeof(pmID)); + pcp->pmids = xRealloc(pcp->pmids, j * sizeof(pmID)); + pcp->names = xRealloc(pcp->names, j * sizeof(char*)); + pcp->descs = xRealloc(pcp->descs, j * sizeof(pmDesc)); + memset(&pcp->descs[i], 0, sizeof(pmDesc)); + } + + pcp->pmids[i] = pcp->fetch[i] = PM_ID_NULL; + pcp->names[i] = name; + return ++pcp->totalMetrics; +} + +/* global state from the environment and command line arguments */ +pmOptions opts; + +void Platform_init(void) { + const char* source; + if (opts.context == PM_CONTEXT_ARCHIVE) { + source = opts.archives[0]; + } else if (opts.context == PM_CONTEXT_HOST) { + source = opts.nhosts > 0 ? opts.hosts[0] : "local:"; + } else { + opts.context = PM_CONTEXT_HOST; + source = "local:"; + } + + int sts; + sts = pmNewContext(opts.context, source); + /* with no host requested, fallback to PM_CONTEXT_LOCAL shared libraries */ + if (sts < 0 && opts.context == PM_CONTEXT_HOST && opts.nhosts == 0) { + opts.context = PM_CONTEXT_LOCAL; + sts = pmNewContext(opts.context, NULL); + } + if (sts < 0) { + fprintf(stderr, "Cannot setup PCP metric source: %s\n", pmErrStr(sts)); + exit(1); + } + /* setup timezones and other general startup preparation completion */ + if (pmGetContextOptions(sts, &opts) < 0 || opts.errors) { + pmflush(); + exit(1); + } + + pcp = xCalloc(1, sizeof(Platform)); + pcp->context = sts; + pcp->fetch = xCalloc(PCP_METRIC_COUNT, sizeof(pmID)); + pcp->pmids = xCalloc(PCP_METRIC_COUNT, sizeof(pmID)); + pcp->names = xCalloc(PCP_METRIC_COUNT, sizeof(char*)); + pcp->descs = xCalloc(PCP_METRIC_COUNT, sizeof(pmDesc)); + + if (opts.context == PM_CONTEXT_ARCHIVE) { + gettimeofday(&pcp->offset, NULL); + pmtimevalDec(&pcp->offset, &opts.start); + } + + for (unsigned int i = 0; i < PCP_METRIC_COUNT; i++) + Platform_addMetric(i, Platform_metricNames[i]); + pcp->meters.offset = PCP_METRIC_COUNT; + + PCPDynamicMeters_init(&pcp->meters); + + sts = pmLookupName(pcp->totalMetrics, pcp->names, pcp->pmids); + if (sts < 0) { + fprintf(stderr, "Error: cannot lookup metric names: %s\n", pmErrStr(sts)); + exit(1); + } + + for (unsigned int i = 0; i < pcp->totalMetrics; i++) { + pcp->fetch[i] = PM_ID_NULL; /* default is to not sample */ + + /* expect some metrics to be missing - e.g. PMDA not available */ + if (pcp->pmids[i] == PM_ID_NULL) + continue; + + sts = pmLookupDesc(pcp->pmids[i], &pcp->descs[i]); + if (sts < 0) { + if (pmDebugOptions.appl0) + fprintf(stderr, "Error: cannot lookup metric %s(%s): %s\n", + pcp->names[i], pmIDStr(pcp->pmids[i]), pmErrStr(sts)); + pcp->pmids[i] = PM_ID_NULL; + continue; + } + } + + /* set proc.control.perclient.threads to 1 for live contexts */ + Metric_enableThreads(); + + /* extract values needed for setup - e.g. cpu count, pid_max */ + Metric_enable(PCP_PID_MAX, true); + Metric_enable(PCP_BOOTTIME, true); + Metric_enable(PCP_HINV_NCPU, true); + Metric_enable(PCP_PERCPU_SYSTEM, true); + Metric_enable(PCP_UNAME_SYSNAME, true); + Metric_enable(PCP_UNAME_RELEASE, true); + Metric_enable(PCP_UNAME_MACHINE, true); + Metric_enable(PCP_UNAME_DISTRO, true); + + Metric_fetch(NULL); + + for (Metric metric = 0; metric < PCP_PROC_PID; metric++) + Metric_enable(metric, true); + Metric_enable(PCP_PID_MAX, false); /* needed one time only */ + Metric_enable(PCP_BOOTTIME, false); + Metric_enable(PCP_UNAME_SYSNAME, false); + Metric_enable(PCP_UNAME_RELEASE, false); + Metric_enable(PCP_UNAME_MACHINE, false); + Metric_enable(PCP_UNAME_DISTRO, false); + + /* first sample (fetch) performed above, save constants */ + Platform_getBootTime(); + Platform_getRelease(0); + Platform_getMaxCPU(); + Platform_getMaxPid(); +} + +void Platform_done(void) { + pmDestroyContext(pcp->context); + if (pcp->result) + pmFreeResult(pcp->result); + free(pcp->release); + free(pcp->fetch); + free(pcp->pmids); + free(pcp->names); + free(pcp->descs); + free(pcp); +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void)keys; +} + +int Platform_getUptime(void) { + pmAtomValue value; + if (Metric_values(PCP_UPTIME, &value, 1, PM_TYPE_32) == NULL) + return 0; + return value.l; +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + *one = *five = *fifteen = 0.0; + + pmAtomValue values[3] = {0}; + if (Metric_values(PCP_LOAD_AVERAGE, values, 3, PM_TYPE_DOUBLE) != NULL) { + *one = values[0].d; + *five = values[1].d; + *fifteen = values[2].d; + } +} + +int Platform_getMaxCPU(void) { + if (pcp->ncpu) + return pcp->ncpu; + + pmAtomValue value; + if (Metric_values(PCP_HINV_NCPU, &value, 1, PM_TYPE_32) != NULL) + pcp->ncpu = value.l; + else + pcp->ncpu = -1; + return pcp->ncpu; +} + +int Platform_getMaxPid(void) { + if (pcp->pidmax) + return pcp->pidmax; + + pmAtomValue value; + if (Metric_values(PCP_PID_MAX, &value, 1, PM_TYPE_32) == NULL) + return -1; + pcp->pidmax = value.l; + return pcp->pidmax; +} + +long long Platform_getBootTime(void) { + if (pcp->btime) + return pcp->btime; + + pmAtomValue value; + if (Metric_values(PCP_BOOTTIME, &value, 1, PM_TYPE_64) != NULL) + pcp->btime = value.ll; + return pcp->btime; +} + +static double Platform_setOneCPUValues(Meter* this, pmAtomValue* values) { + + unsigned long long value = values[CPU_TOTAL_PERIOD].ull; + double total = (double) (value == 0 ? 1 : value); + double percent; + + double* v = this->values; + v[CPU_METER_NICE] = values[CPU_NICE_PERIOD].ull / total * 100.0; + v[CPU_METER_NORMAL] = values[CPU_USER_PERIOD].ull / total * 100.0; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = values[CPU_SYSTEM_PERIOD].ull / total * 100.0; + v[CPU_METER_IRQ] = values[CPU_IRQ_PERIOD].ull / total * 100.0; + v[CPU_METER_SOFTIRQ] = values[CPU_SOFTIRQ_PERIOD].ull / total * 100.0; + v[CPU_METER_STEAL] = values[CPU_STEAL_PERIOD].ull / total * 100.0; + v[CPU_METER_GUEST] = values[CPU_GUEST_PERIOD].ull / total * 100.0; + v[CPU_METER_IOWAIT] = values[CPU_IOWAIT_PERIOD].ull / total * 100.0; + this->curItems = 8; + if (this->pl->settings->accountGuestInCPUMeter) + percent = v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6]; + else + percent = v[0] + v[1] + v[2] + v[3] + v[4]; + } else { + v[2] = values[CPU_SYSTEM_ALL_PERIOD].ull / total * 100.0; + value = values[CPU_STEAL_PERIOD].ull + values[CPU_GUEST_PERIOD].ull; + v[3] = value / total * 100.0; + this->curItems = 4; + percent = v[0] + v[1] + v[2] + v[3]; + } + percent = CLAMP(percent, 0.0, 100.0); + if (isnan(percent)) + percent = 0.0; + + v[CPU_METER_FREQUENCY] = values[CPU_FREQUENCY].d; + v[CPU_METER_TEMPERATURE] = NAN; + + return percent; +} + +double Platform_setCPUValues(Meter* this, int cpu) { + const PCPProcessList* pl = (const PCPProcessList*) this->pl; + if (cpu <= 0) /* use aggregate values */ + return Platform_setOneCPUValues(this, pl->cpu); + return Platform_setOneCPUValues(this, pl->percpu[cpu - 1]); +} + +void Platform_setMemoryValues(Meter* this) { + const ProcessList* pl = this->pl; + const PCPProcessList* ppl = (const PCPProcessList*) pl; + + this->total = pl->totalMem; + this->values[0] = pl->usedMem; + this->values[1] = pl->buffersMem; + this->values[2] = pl->sharedMem; + this->values[3] = pl->cachedMem; + this->values[4] = pl->availableMem; + + if (ppl->zfs.enabled != 0) { + this->values[0] -= ppl->zfs.size; + this->values[3] += ppl->zfs.size; + } +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = pl->cachedSwap; +} + +void Platform_setZramValues(Meter* this) { + int i, count = Metric_instanceCount(PCP_ZRAM_CAPACITY); + if (!count) { + this->total = 0; + this->values[0] = 0; + this->values[1] = 0; + return; + } + + pmAtomValue* values = xCalloc(count, sizeof(pmAtomValue)); + ZramStats stats = {0}; + + if (Metric_values(PCP_ZRAM_CAPACITY, values, count, PM_TYPE_U64)) { + for (i = 0; i < count; i++) + stats.totalZram += values[i].ull; + } + if (Metric_values(PCP_ZRAM_ORIGINAL, values, count, PM_TYPE_U64)) { + for (i = 0; i < count; i++) + stats.usedZramOrig += values[i].ull; + } + if (Metric_values(PCP_ZRAM_COMPRESSED, values, count, PM_TYPE_U64)) { + for (i = 0; i < count; i++) + stats.usedZramComp += values[i].ull; + } + + free(values); + + this->total = stats.totalZram; + this->values[0] = stats.usedZramComp; + this->values[1] = stats.usedZramOrig; +} + +void Platform_setZfsArcValues(Meter* this) { + const PCPProcessList* ppl = (const PCPProcessList*) this->pl; + + ZfsArcMeter_readStats(this, &(ppl->zfs)); +} + +void Platform_setZfsCompressedArcValues(Meter* this) { + const PCPProcessList* ppl = (const PCPProcessList*) this->pl; + + ZfsCompressedArcMeter_readStats(this, &(ppl->zfs)); +} + +void Platform_getHostname(char* buffer, size_t size) { + const char* hostname = pmGetContextHostName(pcp->context); + String_safeStrncpy(buffer, hostname, size); +} + +void Platform_getRelease(char** string) { + /* fast-path - previously-formatted string */ + if (string) { + *string = pcp->release; + return; + } + + /* first call, extract just-sampled values */ + pmAtomValue sysname, release, machine, distro; + if (!Metric_values(PCP_UNAME_SYSNAME, &sysname, 1, PM_TYPE_STRING)) + sysname.cp = NULL; + if (!Metric_values(PCP_UNAME_RELEASE, &release, 1, PM_TYPE_STRING)) + release.cp = NULL; + if (!Metric_values(PCP_UNAME_MACHINE, &machine, 1, PM_TYPE_STRING)) + machine.cp = NULL; + if (!Metric_values(PCP_UNAME_DISTRO, &distro, 1, PM_TYPE_STRING)) + distro.cp = NULL; + + size_t length = 16; /* padded for formatting characters */ + if (sysname.cp) + length += strlen(sysname.cp); + if (release.cp) + length += strlen(release.cp); + if (machine.cp) + length += strlen(machine.cp); + if (distro.cp) + length += strlen(distro.cp); + pcp->release = xCalloc(1, length); + + if (sysname.cp) { + strcat(pcp->release, sysname.cp); + strcat(pcp->release, " "); + } + if (release.cp) { + strcat(pcp->release, release.cp); + strcat(pcp->release, " "); + } + if (machine.cp) { + strcat(pcp->release, "["); + strcat(pcp->release, machine.cp); + strcat(pcp->release, "] "); + } + if (distro.cp) { + if (pcp->release[0] != '\0') { + strcat(pcp->release, "@ "); + strcat(pcp->release, distro.cp); + } else { + strcat(pcp->release, distro.cp); + } + strcat(pcp->release, " "); + } + + if (pcp->release) /* cull trailing space */ + pcp->release[strlen(pcp->release)] = '\0'; + + free(distro.cp); + free(machine.cp); + free(release.cp); + free(sysname.cp); +} + +char* Platform_getProcessEnv(pid_t pid) { + pmAtomValue value; + if (!Metric_instance(PCP_PROC_ENVIRON, pid, 0, &value, PM_TYPE_STRING)) + return NULL; + return value.cp; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred) { + *ten = *sixty = *threehundred = 0; + + Metric metric; + if (String_eq(file, "cpu")) + metric = PCP_PSI_CPUSOME; + else if (String_eq(file, "io")) + metric = some ? PCP_PSI_IOSOME : PCP_PSI_IOFULL; + else if (String_eq(file, "mem")) + metric = some ? PCP_PSI_MEMSOME : PCP_PSI_MEMFULL; + else + return; + + pmAtomValue values[3] = {0}; + if (Metric_values(metric, values, 3, PM_TYPE_DOUBLE) != NULL) { + *ten = values[0].d; + *sixty = values[1].d; + *threehundred = values[2].d; + } +} + +bool Platform_getDiskIO(DiskIOData* data) { + memset(data, 0, sizeof(*data)); + + pmAtomValue value; + if (Metric_values(PCP_DISK_READB, &value, 1, PM_TYPE_U64) != NULL) + data->totalBytesRead = value.ull; + if (Metric_values(PCP_DISK_WRITEB, &value, 1, PM_TYPE_U64) != NULL) + data->totalBytesWritten = value.ull; + if (Metric_values(PCP_DISK_ACTIVE, &value, 1, PM_TYPE_U64) != NULL) + data->totalMsTimeSpend = value.ull; + return true; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + memset(data, 0, sizeof(*data)); + + pmAtomValue value; + if (Metric_values(PCP_NET_RECVB, &value, 1, PM_TYPE_U64) != NULL) + data->bytesReceived = value.ull; + if (Metric_values(PCP_NET_SENDB, &value, 1, PM_TYPE_U64) != NULL) + data->bytesTransmitted = value.ull; + if (Metric_values(PCP_NET_RECVP, &value, 1, PM_TYPE_U64) != NULL) + data->packetsReceived = value.ull; + if (Metric_values(PCP_NET_SENDP, &value, 1, PM_TYPE_U64) != NULL) + data->packetsTransmitted = value.ull; + return true; +} + +void Platform_getBattery(double* level, ACPresence* isOnAC) { + *level = NAN; + *isOnAC = AC_ERROR; +} + +void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { + printf( +" --host=HOSTSPEC metrics source is PMCD at HOSTSPEC [see PCPIntro(1)]\n" +" --hostzone set reporting timezone to local time of metrics source\n" +" --timezone=TZ set reporting timezone\n"); +} + +bool Platform_getLongOption(int opt, ATTR_UNUSED int argc, char** argv) { + /* libpcp export without a header definition */ + extern void __pmAddOptHost(pmOptions*, char*); + + switch (opt) { + case PLATFORM_LONGOPT_HOST: /* --host=HOSTSPEC */ + if (argv[optind][0] == '\0') + return false; + __pmAddOptHost(&opts, optarg); + return true; + + case PLATFORM_LONGOPT_HOSTZONE: /* --hostzone */ + if (opts.timezone) { + pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname()); + opts.errors++; + } else { + opts.tzflag = 1; + } + return true; + + case PLATFORM_LONGOPT_TIMEZONE: /* --timezone=TZ */ + if (argv[optind][0] == '\0') + return false; + if (opts.tzflag) { + pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname()); + opts.errors++; + } else { + opts.timezone = optarg; + } + return true; + + default: + break; + } + return false; +} + +void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + if (gettimeofday(tv, NULL) == 0) { + /* shift by start offset to stay in lock-step with realtime (archives) */ + if (pcp->offset.tv_sec || pcp->offset.tv_usec) + pmtimevalDec(tv, &pcp->offset); + *msec = ((uint64_t)tv->tv_sec * 1000) + ((uint64_t)tv->tv_usec / 1000); + } else { + memset(tv, 0, sizeof(struct timeval)); + *msec = 0; + } +} + +void Platform_gettime_monotonic(uint64_t* msec) { + if (pcp->result) { + struct timeval* tv = &pcp->result->timestamp; + *msec = ((uint64_t)tv->tv_sec * 1000) + ((uint64_t)tv->tv_usec / 1000); + } else { + *msec = 0; + } +} + +Hashtable* Platform_dynamicMeters(void) { + return pcp->meters.table; +} + +void Platform_dynamicMeterInit(Meter* meter) { + PCPDynamicMeter* this = Hashtable_get(pcp->meters.table, meter->param); + if (this) + PCPDynamicMeter_enable(this); +} + +void Platform_dynamicMeterUpdateValues(Meter* meter) { + PCPDynamicMeter* this = Hashtable_get(pcp->meters.table, meter->param); + if (this) + PCPDynamicMeter_updateValues(this, meter); +} + +void Platform_dynamicMeterDisplay(const Meter* meter, RichString* out) { + PCPDynamicMeter* this = Hashtable_get(pcp->meters.table, meter->param); + if (this) + PCPDynamicMeter_display(this, meter, out); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/Platform.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,273 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - pcp/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2020-2021 htop dev team +(C) 2020-2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +/* use htop config.h values for these macros, not pcp values */ +#undef PACKAGE_URL +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#undef PACKAGE_BUGREPORT + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Hashtable.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "SysArchMeter.h" + + +extern ProcessField Platform_defaultFields[]; + +extern int Platform_numberOfFields; + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +long long Platform_getBootTime(void); + +int Platform_getMaxCPU(void); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +void Platform_setZramValues(Meter* this); + +void Platform_setZfsArcValues(Meter* this); + +void Platform_setZfsCompressedArcValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +void Platform_getHostname(char* buffer, size_t size); + +void Platform_getRelease(char** string); + +enum { + PLATFORM_LONGOPT_HOST = 128, + PLATFORM_LONGOPT_TIMEZONE, + PLATFORM_LONGOPT_HOSTZONE, +}; + +#define PLATFORM_LONG_OPTIONS \ + {PMLONGOPT_HOST, optional_argument, 0, PLATFORM_LONGOPT_HOST}, \ + {PMLONGOPT_TIMEZONE, optional_argument, 0, PLATFORM_LONGOPT_TIMEZONE}, \ + {PMLONGOPT_HOSTZONE, optional_argument, 0, PLATFORM_LONGOPT_HOSTZONE}, \ + +void Platform_longOptionsUsage(const char* name); + +bool Platform_getLongOption(int opt, int argc, char** argv); + +extern pmOptions opts; + + +typedef enum Metric_ { + PCP_CONTROL_THREADS, /* proc.control.perclient.threads */ + + PCP_HINV_NCPU, /* hinv.ncpu */ + PCP_HINV_CPUCLOCK, /* hinv.cpu.clock */ + PCP_UNAME_SYSNAME, /* kernel.uname.sysname */ + PCP_UNAME_RELEASE, /* kernel.uname.release */ + PCP_UNAME_MACHINE, /* kernel.uname.machine */ + PCP_UNAME_DISTRO, /* kernel.uname.distro */ + PCP_LOAD_AVERAGE, /* kernel.all.load */ + PCP_PID_MAX, /* kernel.all.pid_max */ + PCP_UPTIME, /* kernel.all.uptime */ + PCP_BOOTTIME, /* kernel.all.boottime */ + PCP_CPU_USER, /* kernel.all.cpu.user */ + PCP_CPU_NICE, /* kernel.all.cpu.nice */ + PCP_CPU_SYSTEM, /* kernel.all.cpu.sys */ + PCP_CPU_IDLE, /* kernel.all.cpu.idle */ + PCP_CPU_IOWAIT, /* kernel.all.cpu.wait.total */ + PCP_CPU_IRQ, /* kernel.all.cpu.intr */ + PCP_CPU_SOFTIRQ, /* kernel.all.cpu.irq.soft */ + PCP_CPU_STEAL, /* kernel.all.cpu.steal */ + PCP_CPU_GUEST, /* kernel.all.cpu.guest */ + PCP_CPU_GUESTNICE, /* kernel.all.cpu.guest_nice */ + PCP_PERCPU_USER, /* kernel.percpu.cpu.user */ + PCP_PERCPU_NICE, /* kernel.percpu.cpu.nice */ + PCP_PERCPU_SYSTEM, /* kernel.percpu.cpu.sys */ + PCP_PERCPU_IDLE, /* kernel.percpu.cpu.idle */ + PCP_PERCPU_IOWAIT, /* kernel.percpu.cpu.wait.total */ + PCP_PERCPU_IRQ, /* kernel.percpu.cpu.intr */ + PCP_PERCPU_SOFTIRQ, /* kernel.percpu.cpu.irq.soft */ + PCP_PERCPU_STEAL, /* kernel.percpu.cpu.steal */ + PCP_PERCPU_GUEST, /* kernel.percpu.cpu.guest */ + PCP_PERCPU_GUESTNICE, /* kernel.percpu.cpu.guest_nice */ + PCP_MEM_TOTAL, /* mem.physmem */ + PCP_MEM_FREE, /* mem.util.free */ + PCP_MEM_BUFFERS, /* mem.util.bufmem */ + PCP_MEM_CACHED, /* mem.util.cached */ + PCP_MEM_SHARED, /* mem.util.shared */ + PCP_MEM_AVAILABLE, /* mem.util.available */ + PCP_MEM_SRECLAIM, /* mem.util.slabReclaimable */ + PCP_MEM_SWAPCACHED, /* mem.util.swapCached */ + PCP_MEM_SWAPTOTAL, /* mem.util.swapTotal */ + PCP_MEM_SWAPFREE, /* mem.util.swapFree */ + PCP_DISK_READB, /* disk.all.read_bytes */ + PCP_DISK_WRITEB, /* disk.all.write_bytes */ + PCP_DISK_ACTIVE, /* disk.all.avactive */ + PCP_NET_RECVB, /* network.all.in.bytes */ + PCP_NET_SENDB, /* network.all.out.bytes */ + PCP_NET_RECVP, /* network.all.in.packets */ + PCP_NET_SENDP, /* network.all.out.packets */ + PCP_PSI_CPUSOME, /* kernel.all.pressure.cpu.some.avg */ + PCP_PSI_IOSOME, /* kernel.all.pressure.io.some.avg */ + PCP_PSI_IOFULL, /* kernel.all.pressure.io.full.avg */ + PCP_PSI_MEMSOME, /* kernel.all.pressure.memory.some.avg */ + PCP_PSI_MEMFULL, /* kernel.all.pressure.memory.full.avg */ + PCP_ZFS_ARC_ANON_SIZE, /* zfs.arc.anon_size */ + PCP_ZFS_ARC_BONUS_SIZE, /* zfs.arc.bonus_size */ + PCP_ZFS_ARC_COMPRESSED_SIZE, /* zfs.arc.compressed_size */ + PCP_ZFS_ARC_UNCOMPRESSED_SIZE, /* zfs.arc.uncompressed_size */ + PCP_ZFS_ARC_C_MAX, /* zfs.arc.c_max */ + PCP_ZFS_ARC_DBUF_SIZE, /* zfs.arc.dbuf_size */ + PCP_ZFS_ARC_DNODE_SIZE, /* zfs.arc.dnode_size */ + PCP_ZFS_ARC_HDR_SIZE, /* zfs.arc.hdr_size */ + PCP_ZFS_ARC_MFU_SIZE, /* zfs.arc.mfu_size */ + PCP_ZFS_ARC_MRU_SIZE, /* zfs.arc.mru_size */ + PCP_ZFS_ARC_SIZE, /* zfs.arc.size */ + PCP_ZRAM_CAPACITY, /* zram.capacity */ + PCP_ZRAM_ORIGINAL, /* zram.mm_stat.data_size.original */ + PCP_ZRAM_COMPRESSED, /* zram.mm_stat.data_size.compressed */ + + PCP_PROC_PID, /* proc.psinfo.pid */ + PCP_PROC_PPID, /* proc.psinfo.ppid */ + PCP_PROC_TGID, /* proc.psinfo.tgid */ + PCP_PROC_PGRP, /* proc.psinfo.pgrp */ + PCP_PROC_SESSION, /* proc.psinfo.session */ + PCP_PROC_STATE, /* proc.psinfo.sname */ + PCP_PROC_TTY, /* proc.psinfo.tty */ + PCP_PROC_TTYPGRP, /* proc.psinfo.tty_pgrp */ + PCP_PROC_MINFLT, /* proc.psinfo.minflt */ + PCP_PROC_MAJFLT, /* proc.psinfo.maj_flt */ + PCP_PROC_CMINFLT, /* proc.psinfo.cmin_flt */ + PCP_PROC_CMAJFLT, /* proc.psinfo.cmaj_flt */ + PCP_PROC_UTIME, /* proc.psinfo.utime */ + PCP_PROC_STIME, /* proc.psinfo.stime */ + PCP_PROC_CUTIME, /* proc.psinfo.cutime */ + PCP_PROC_CSTIME, /* proc.psinfo.cstime */ + PCP_PROC_PRIORITY, /* proc.psinfo.priority */ + PCP_PROC_NICE, /* proc.psinfo.nice */ + PCP_PROC_THREADS, /* proc.psinfo.threads */ + PCP_PROC_STARTTIME, /* proc.psinfo.start_time */ + PCP_PROC_PROCESSOR, /* proc.psinfo.processor */ + PCP_PROC_CMD, /* proc.psinfo.cmd */ + PCP_PROC_PSARGS, /* proc.psinfo.psargs */ + PCP_PROC_CGROUPS, /* proc.psinfo.cgroups */ + PCP_PROC_OOMSCORE, /* proc.psinfo.oom_score */ + PCP_PROC_VCTXSW, /* proc.psinfo.vctxsw */ + PCP_PROC_NVCTXSW, /* proc.psinfo.nvctxsw */ + PCP_PROC_LABELS, /* proc.psinfo.labels */ + PCP_PROC_ENVIRON, /* proc.psinfo.environ */ + PCP_PROC_TTYNAME, /* proc.psinfo.ttyname */ + PCP_PROC_EXE, /* proc.psinfo.exe */ + PCP_PROC_CWD, /* proc.psinfo.cwd */ + + PCP_PROC_ID_UID, /* proc.id.uid */ + PCP_PROC_ID_USER, /* proc.id.uid_nm */ + + PCP_PROC_IO_RCHAR, /* proc.io.rchar */ + PCP_PROC_IO_WCHAR, /* proc.io.wchar */ + PCP_PROC_IO_SYSCR, /* proc.io.syscr */ + PCP_PROC_IO_SYSCW, /* proc.io.syscw */ + PCP_PROC_IO_READB, /* proc.io.read_bytes */ + PCP_PROC_IO_WRITEB, /* proc.io.write_bytes */ + PCP_PROC_IO_CANCELLED, /* proc.io.cancelled_write_bytes */ + + PCP_PROC_MEM_SIZE, /* proc.memory.size */ + PCP_PROC_MEM_RSS, /* proc.memory.rss */ + PCP_PROC_MEM_SHARE, /* proc.memory.share */ + PCP_PROC_MEM_TEXTRS, /* proc.memory.textrss */ + PCP_PROC_MEM_LIBRS, /* proc.memory.librss */ + PCP_PROC_MEM_DATRS, /* proc.memory.datrss */ + PCP_PROC_MEM_DIRTY, /* proc.memory.dirty */ + + PCP_PROC_SMAPS_PSS, /* proc.smaps.pss */ + PCP_PROC_SMAPS_SWAP, /* proc.smaps.swap */ + PCP_PROC_SMAPS_SWAPPSS, /* proc.smaps.swappss */ + + PCP_METRIC_COUNT /* total metric count */ +} Metric; + +void Metric_enable(Metric metric, bool enable); + +bool Metric_enabled(Metric metric); + +void Metric_enableThreads(void); + +bool Metric_fetch(struct timeval* timestamp); + +bool Metric_iterate(Metric metric, int* instp, int* offsetp); + +pmAtomValue* Metric_values(Metric metric, pmAtomValue* atom, int count, int type); + +const pmDesc* Metric_desc(Metric metric); + +int Metric_instanceCount(Metric metric); + +int Metric_instanceOffset(Metric metric, int inst); + +pmAtomValue* Metric_instance(Metric metric, int inst, int offset, pmAtomValue* atom, int type); + +int Platform_addMetric(Metric id, const char* name); + +void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec); + +void Platform_gettime_monotonic(uint64_t* msec); + +Hashtable* Platform_dynamicMeters(void); + +void Platform_dynamicMeterInit(Meter* meter); + +void Platform_dynamicMeterUpdateValues(Meter* meter); + +void Platform_dynamicMeterDisplay(const Meter* meter, RichString* out); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,51 @@ +#ifndef HEADER_PCPProcessField +#define HEADER_PCPProcessField +/* +htop - pcp/ProcessField.h +(C) 2014 Hisham H. Muhammad +(C) 2021 htop dev team +(C) 2020-2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + CMINFLT = 11, \ + CMAJFLT = 13, \ + UTIME = 14, \ + STIME = 15, \ + CUTIME = 16, \ + CSTIME = 17, \ + M_SHARE = 41, \ + M_TRS = 42, \ + M_DRS = 43, \ + M_LRS = 44, \ + M_DT = 45, \ + CTID = 100, \ + RCHAR = 103, \ + WCHAR = 104, \ + SYSCR = 105, \ + SYSCW = 106, \ + RBYTES = 107, \ + WBYTES = 108, \ + CNCLWB = 109, \ + IO_READ_RATE = 110, \ + IO_WRITE_RATE = 111, \ + IO_RATE = 112, \ + CGROUP = 113, \ + OOM = 114, \ + PERCENT_CPU_DELAY = 116, \ + PERCENT_IO_DELAY = 117, \ + PERCENT_SWAP_DELAY = 118, \ + M_PSS = 119, \ + M_SWAP = 120, \ + M_PSSWP = 121, \ + CTXT = 122, \ + SECATTR = 123, \ + \ + DUMMY_BUMP_FIELD = CWD, \ + // End of list + + +#endif /* HEADER_PCPProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp-htop.c pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp-htop.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/pcp-htop.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/pcp-htop.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,26 @@ +/* +htop - pcp-htop.c +(C) 2004-2011 Hisham H. Muhammad +(C) 2020-2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include + +#include "CommandLine.h" +#include "Platform.h" + + +int main(int argc, char** argv) { + const char* name = "pcp-htop"; + pmSetProgname(name); + + /* extract environment variables */ + opts.flags |= PM_OPTFLAG_ENV_ONLY; + (void)pmGetOptions(argc, argv, &opts); + + return CommandLine_run(name, argc, argv); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Process.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Process.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Process.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Process.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,1227 @@ +/* +htop - Process.c +(C) 2004-2015 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "Process.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "Settings.h" +#include "XUtils.h" + +#if defined(MAJOR_IN_MKDEV) +#include +#endif + + +/* Used to identify kernel threads in Comm and Exe columns */ +static const char* const kthreadID = "KTHREAD"; + +static uid_t Process_getuid = (uid_t)-1; + +int Process_pidDigits = 7; + +void Process_setupColumnWidths() { + int maxPid = Platform_getMaxPid(); + if (maxPid == -1) + return; + + Process_pidDigits = ceil(log10(maxPid)); + assert(Process_pidDigits <= PROCESS_MAX_PID_DIGITS); +} + +void Process_printBytes(RichString* str, unsigned long long number, bool coloring) { + char buffer[16]; + int len; + + int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; + int processMegabytesColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS]; + int processGigabytesColor = coloring ? CRT_colors[PROCESS_GIGABYTES] : CRT_colors[PROCESS]; + int shadowColor = coloring ? CRT_colors[PROCESS_SHADOW] : CRT_colors[PROCESS]; + int processColor = CRT_colors[PROCESS]; + + if (number == ULLONG_MAX) { + //Invalid number + RichString_appendAscii(str, shadowColor, " N/A "); + return; + } + + number /= ONE_K; + + if (number < 1000) { + //Plain number, no markings + len = xSnprintf(buffer, sizeof(buffer), "%5llu ", number); + RichString_appendnAscii(str, processColor, buffer, len); + } else if (number < 100000) { + //2 digit MB, 3 digit KB + len = xSnprintf(buffer, sizeof(buffer), "%2llu", number / 1000); + RichString_appendnAscii(str, processMegabytesColor, buffer, len); + number %= 1000; + len = xSnprintf(buffer, sizeof(buffer), "%03llu ", number); + RichString_appendnAscii(str, processColor, buffer, len); + } else if (number < 1000 * ONE_K) { + //3 digit MB + number /= ONE_K; + len = xSnprintf(buffer, sizeof(buffer), "%4lluM ", number); + RichString_appendnAscii(str, processMegabytesColor, buffer, len); + } else if (number < 10000 * ONE_K) { + //1 digit GB, 3 digit MB + number /= ONE_K; + len = xSnprintf(buffer, sizeof(buffer), "%1llu", number / 1000); + RichString_appendnAscii(str, processGigabytesColor, buffer, len); + number %= 1000; + len = xSnprintf(buffer, sizeof(buffer), "%03lluM ", number); + RichString_appendnAscii(str, processMegabytesColor, buffer, len); + } else if (number < 100000 * ONE_K) { + //2 digit GB, 1 digit MB + number /= 100 * ONE_K; + len = xSnprintf(buffer, sizeof(buffer), "%2llu", number / 10); + RichString_appendnAscii(str, processGigabytesColor, buffer, len); + number %= 10; + len = xSnprintf(buffer, sizeof(buffer), ".%1llu", number); + RichString_appendnAscii(str, processMegabytesColor, buffer, len); + RichString_appendAscii(str, processGigabytesColor, "G "); + } else if (number < 1000 * ONE_M) { + //3 digit GB + number /= ONE_M; + len = xSnprintf(buffer, sizeof(buffer), "%4lluG ", number); + RichString_appendnAscii(str, processGigabytesColor, buffer, len); + } else if (number < 10000ULL * ONE_M) { + //1 digit TB, 3 digit GB + number /= ONE_M; + len = xSnprintf(buffer, sizeof(buffer), "%1llu", number / 1000); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + number %= 1000; + len = xSnprintf(buffer, sizeof(buffer), "%03lluG ", number); + RichString_appendnAscii(str, processGigabytesColor, buffer, len); + } else if (number < 100000 * ONE_M) { + //2 digit TB, 1 digit GB + number /= 100 * ONE_M; + len = xSnprintf(buffer, sizeof(buffer), "%2llu", number / 10); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + number %= 10; + len = xSnprintf(buffer, sizeof(buffer), ".%1llu", number); + RichString_appendnAscii(str, processGigabytesColor, buffer, len); + RichString_appendAscii(str, largeNumberColor, "T "); + } else if (number < 10000ULL * ONE_G) { + //3 digit TB or 1 digit PB, 3 digit TB + number /= ONE_G; + len = xSnprintf(buffer, sizeof(buffer), "%4lluT ", number); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + } else { + //2 digit PB and above + len = xSnprintf(buffer, sizeof(buffer), "%4.1lfP ", (double)number / ONE_T); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + } +} + +void Process_printKBytes(RichString* str, unsigned long long number, bool coloring) { + if (number == ULLONG_MAX) + Process_printBytes(str, ULLONG_MAX, coloring); + else + Process_printBytes(str, number * ONE_K, coloring); +} + +void Process_printCount(RichString* str, unsigned long long number, bool coloring) { + char buffer[13]; + + int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; + int processMegabytesColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS]; + int processColor = CRT_colors[PROCESS]; + int processShadowColor = coloring ? CRT_colors[PROCESS_SHADOW] : CRT_colors[PROCESS]; + + if (number == ULLONG_MAX) { + RichString_appendAscii(str, CRT_colors[PROCESS_SHADOW], " N/A "); + } else if (number >= 100000LL * ONE_DECIMAL_T) { + xSnprintf(buffer, sizeof(buffer), "%11llu ", number / ONE_DECIMAL_G); + RichString_appendnAscii(str, largeNumberColor, buffer, 12); + } else if (number >= 100LL * ONE_DECIMAL_T) { + xSnprintf(buffer, sizeof(buffer), "%11llu ", number / ONE_DECIMAL_M); + RichString_appendnAscii(str, largeNumberColor, buffer, 8); + RichString_appendnAscii(str, processMegabytesColor, buffer + 8, 4); + } else if (number >= 10LL * ONE_DECIMAL_G) { + xSnprintf(buffer, sizeof(buffer), "%11llu ", number / ONE_DECIMAL_K); + RichString_appendnAscii(str, largeNumberColor, buffer, 5); + RichString_appendnAscii(str, processMegabytesColor, buffer + 5, 3); + RichString_appendnAscii(str, processColor, buffer + 8, 4); + } else { + xSnprintf(buffer, sizeof(buffer), "%11llu ", number); + RichString_appendnAscii(str, largeNumberColor, buffer, 2); + RichString_appendnAscii(str, processMegabytesColor, buffer + 2, 3); + RichString_appendnAscii(str, processColor, buffer + 5, 3); + RichString_appendnAscii(str, processShadowColor, buffer + 8, 4); + } +} + +void Process_printTime(RichString* str, unsigned long long totalHundredths, bool coloring) { + char buffer[10]; + int len; + + unsigned long long totalSeconds = totalHundredths / 100; + unsigned long long hours = totalSeconds / 3600; + unsigned long long days = totalSeconds / 86400; + int minutes = (totalSeconds / 60) % 60; + int seconds = totalSeconds % 60; + int hundredths = totalHundredths - (totalSeconds * 100); + + int yearColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS]; + int dayColor = coloring ? CRT_colors[PROCESS_GIGABYTES] : CRT_colors[PROCESS]; + int hourColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS]; + int defColor = CRT_colors[PROCESS]; + + if (days >= /* Ignore leapyears */365) { + int years = days / 365; + int daysLeft = days - 365 * years; + + if (daysLeft >= 100) { + len = xSnprintf(buffer, sizeof(buffer), "%3dy", years); + RichString_appendnAscii(str, yearColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%3dd ", daysLeft); + RichString_appendnAscii(str, dayColor, buffer, len); + } else if (daysLeft >= 10) { + len = xSnprintf(buffer, sizeof(buffer), "%4dy", years); + RichString_appendnAscii(str, yearColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%2dd ", daysLeft); + RichString_appendnAscii(str, dayColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%5dy", years); + RichString_appendnAscii(str, yearColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%1dd ", daysLeft); + RichString_appendnAscii(str, dayColor, buffer, len); + } + } else if (days >= 100) { + int hoursLeft = hours - days * 24; + + if (hoursLeft >= 10) { + len = xSnprintf(buffer, sizeof(buffer), "%4llud", days); + RichString_appendnAscii(str, dayColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%2dh ", hoursLeft); + RichString_appendnAscii(str, hourColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%5llud", days); + RichString_appendnAscii(str, dayColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%1dh ", hoursLeft); + RichString_appendnAscii(str, hourColor, buffer, len); + } + } else if (hours >= 100) { + int minutesLeft = totalSeconds / 60 - hours * 60; + + if (minutesLeft >= 10) { + len = xSnprintf(buffer, sizeof(buffer), "%4lluh", hours); + RichString_appendnAscii(str, hourColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%2dm ", minutesLeft); + RichString_appendnAscii(str, defColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%5lluh", hours); + RichString_appendnAscii(str, hourColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%1dm ", minutesLeft); + RichString_appendnAscii(str, defColor, buffer, len); + } + } else if (hours > 0) { + len = xSnprintf(buffer, sizeof(buffer), "%2lluh", hours); + RichString_appendnAscii(str, hourColor, buffer, len); + len = xSnprintf(buffer, sizeof(buffer), "%02d:%02d ", minutes, seconds); + RichString_appendnAscii(str, defColor, buffer, len); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%2d:%02d.%02d ", minutes, seconds, hundredths); + RichString_appendnAscii(str, defColor, buffer, len); + } +} + +void Process_fillStarttimeBuffer(Process* this) { + struct tm date; + (void) localtime_r(&this->starttime_ctime, &date); + strftime(this->starttime_show, sizeof(this->starttime_show) - 1, (this->starttime_ctime > (time(NULL) - 86400)) ? "%R " : "%b%d ", &date); +} + +/* + * TASK_COMM_LEN is defined to be 16 for /proc/[pid]/comm in man proc(5), but it is + * not available in an userspace header - so define it. + * + * Note: This is taken from LINUX headers, but implicitly taken for other platforms + * for sake of brevity. + * + * Note: when colorizing a basename with the comm prefix, the entire basename + * (not just the comm prefix) is colorized for better readability, and it is + * implicit that only upto (TASK_COMM_LEN - 1) could be comm. + */ +#define TASK_COMM_LEN 16 + +static bool findCommInCmdline(const char* comm, const char* cmdline, int cmdlineBasenameStart, int* pCommStart, int* pCommEnd) { + /* Try to find procComm in tokenized cmdline - this might in rare cases + * mis-identify a string or fail, if comm or cmdline had been unsuitably + * modified by the process */ + const char* tokenBase; + size_t tokenLen; + const size_t commLen = strlen(comm); + + if (cmdlineBasenameStart < 0) + return false; + + for (const char* token = cmdline + cmdlineBasenameStart; *token;) { + for (tokenBase = token; *token && *token != '\n'; ++token) { + if (*token == '/') { + tokenBase = token + 1; + } + } + tokenLen = token - tokenBase; + + if ((tokenLen == commLen || (tokenLen > commLen && commLen == (TASK_COMM_LEN - 1))) && + strncmp(tokenBase, comm, commLen) == 0) { + *pCommStart = tokenBase - cmdline; + *pCommEnd = token - cmdline; + return true; + } + + if (*token) { + do { + ++token; + } while (*token && '\n' == *token); + } + } + return false; +} + +static int matchCmdlinePrefixWithExeSuffix(const char* cmdline, int cmdlineBaseOffset, const char* exe, int exeBaseOffset, int exeBaseLen) { + int matchLen; /* matching length to be returned */ + char delim; /* delimiter following basename */ + + /* cmdline prefix is an absolute path: it must match whole exe. */ + if (cmdline[0] == '/') { + matchLen = exeBaseLen + exeBaseOffset; + if (strncmp(cmdline, exe, matchLen) == 0) { + delim = cmdline[matchLen]; + if (delim == 0 || delim == '\n' || delim == ' ') { + return matchLen; + } + } + return 0; + } + + /* cmdline prefix is a relative path: We need to first match the basename at + * cmdlineBaseOffset and then reverse match the cmdline prefix with the exe + * suffix. But there is a catch: Some processes modify their cmdline in ways + * that make htop's identification of the basename in cmdline unreliable. + * For e.g. /usr/libexec/gdm-session-worker modifies its cmdline to + * "gdm-session-worker [pam/gdm-autologin]" and htop ends up with + * proccmdlineBasenameEnd at "gdm-autologin]". This issue could arise with + * chrome as well as it stores in cmdline its concatenated argument vector, + * without NUL delimiter between the arguments (which may contain a '/') + * + * So if needed, we adjust cmdlineBaseOffset to the previous (if any) + * component of the cmdline relative path, and retry the procedure. */ + bool delimFound; /* if valid basename delimiter found */ + do { + /* match basename */ + matchLen = exeBaseLen + cmdlineBaseOffset; + if (cmdlineBaseOffset < exeBaseOffset && + strncmp(cmdline + cmdlineBaseOffset, exe + exeBaseOffset, exeBaseLen) == 0) { + delim = cmdline[matchLen]; + if (delim == 0 || delim == '\n' || delim == ' ') { + int i, j; + /* reverse match the cmdline prefix and exe suffix */ + for (i = cmdlineBaseOffset - 1, j = exeBaseOffset - 1; + i >= 0 && j >= 0 && cmdline[i] == exe[j]; --i, --j) + ; + + /* full match, with exe suffix being a valid relative path */ + if (i < 0 && j >= 0 && exe[j] == '/') + return matchLen; + } + } + + /* Try to find the previous potential cmdlineBaseOffset - it would be + * preceded by '/' or nothing, and delimited by ' ' or '\n' */ + for (delimFound = false, cmdlineBaseOffset -= 2; cmdlineBaseOffset > 0; --cmdlineBaseOffset) { + if (delimFound) { + if (cmdline[cmdlineBaseOffset - 1] == '/') { + break; + } + } else if (cmdline[cmdlineBaseOffset] == ' ' || cmdline[cmdlineBaseOffset] == '\n') { + delimFound = true; + } + } + } while (delimFound); + + return 0; +} + +/* stpcpy, but also converts newlines to spaces */ +static inline char* stpcpyWithNewlineConversion(char* dstStr, const char* srcStr) { + for (; *srcStr; ++srcStr) { + *dstStr++ = (*srcStr == '\n') ? ' ' : *srcStr; + } + *dstStr = 0; + return dstStr; +} + +/* + * This function makes the merged Command string. It also stores the offsets of the + * basename, comm w.r.t the merged Command string - these offsets will be used by + * Process_writeCommand() for coloring. The merged Command string is also + * returned by Process_getCommandStr() for searching, sorting and filtering. + */ +void Process_makeCommandStr(Process* this) { + ProcessMergedCommand* mc = &this->mergedCommand; + const Settings* settings = this->settings; + + bool showMergedCommand = settings->showMergedCommand; + bool showProgramPath = settings->showProgramPath; + bool searchCommInCmdline = settings->findCommInCmdline; + bool stripExeFromCmdline = settings->stripExeFromCmdline; + bool showThreadNames = settings->showThreadNames; + + /* Nothing to do to (Re)Generate the Command string, if the process is: + * - a kernel thread, or + * - a zombie from before being under htop's watch, or + * - a user thread and showThreadNames is not set */ + if (Process_isKernelThread(this)) + return; + if (this->state == 'Z' && !this->mergedCommand.str) + return; + if (Process_isUserlandThread(this) && settings->showThreadNames) + return; + + /* this->mergedCommand.str needs updating only if its state or contents changed. + * Its content is based on the fields cmdline, comm, and exe. */ + if ( + mc->prevMergeSet == showMergedCommand && + mc->prevPathSet == showProgramPath && + mc->prevCommSet == searchCommInCmdline && + mc->prevCmdlineSet == stripExeFromCmdline && + mc->prevShowThreadNames == showThreadNames && + !mc->cmdlineChanged && + !mc->commChanged && + !mc->exeChanged + ) { + return; + } + + /* The field separtor "│" has been chosen such that it will not match any + * valid string used for searching or filtering */ + const char* SEPARATOR = CRT_treeStr[TREE_STR_VERT]; + const int SEPARATOR_LEN = strlen(SEPARATOR); + + /* Check for any changed fields since we last built this string */ + if (mc->cmdlineChanged || mc->commChanged || mc->exeChanged) { + free(mc->str); + /* Accommodate the column text, two field separators and terminating NUL */ + size_t maxLen = 2 * SEPARATOR_LEN + 1; + maxLen += this->cmdline ? strlen(this->cmdline) : strlen("(zombie)"); + maxLen += this->procComm ? strlen(this->procComm) : 0; + maxLen += this->procExe ? strlen(this->procExe) : 0; + + mc->str = xCalloc(1, maxLen); + } + + /* Preserve the settings used in this run */ + mc->prevMergeSet = showMergedCommand; + mc->prevPathSet = showProgramPath; + mc->prevCommSet = searchCommInCmdline; + mc->prevCmdlineSet = stripExeFromCmdline; + mc->prevShowThreadNames = showThreadNames; + + /* Mark everything as unchanged */ + mc->cmdlineChanged = false; + mc->commChanged = false; + mc->exeChanged = false; + + /* Reset all locations that need extra handling when actually displaying */ + mc->highlightCount = 0; + memset(mc->highlights, 0, sizeof(mc->highlights)); + + size_t mbMismatch = 0; + #define WRITE_HIGHLIGHT(_offset, _length, _attr, _flags) \ + do { \ + /* Check if we still have capacity */ \ + assert(mc->highlightCount < ARRAYSIZE(mc->highlights)); \ + if (mc->highlightCount >= ARRAYSIZE(mc->highlights)) \ + continue; \ + \ + mc->highlights[mc->highlightCount].offset = str - strStart + (_offset) - mbMismatch; \ + mc->highlights[mc->highlightCount].length = _length; \ + mc->highlights[mc->highlightCount].attr = _attr; \ + mc->highlights[mc->highlightCount].flags = _flags; \ + mc->highlightCount++; \ + } while (0) + + #define WRITE_SEPARATOR \ + do { \ + WRITE_HIGHLIGHT(0, 1, CRT_colors[FAILED_READ], CMDLINE_HIGHLIGHT_FLAG_SEPARATOR); \ + mbMismatch += SEPARATOR_LEN - 1; \ + str = stpcpy(str, SEPARATOR); \ + } while (0) + + const int baseAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_BASENAME] : CRT_colors[PROCESS_BASENAME]; + const int commAttr = Process_isThread(this) ? CRT_colors[PROCESS_THREAD_COMM] : CRT_colors[PROCESS_COMM]; + const int delExeAttr = CRT_colors[FAILED_READ]; + const int delLibAttr = CRT_colors[PROCESS_TAG]; + + /* Establish some shortcuts to data we need */ + const char* cmdline = this->cmdline; + const char* procComm = this->procComm; + const char* procExe = this->procExe; + + char* strStart = mc->str; + char* str = strStart; + + int cmdlineBasenameStart = this->cmdlineBasenameStart; + int cmdlineBasenameEnd = this->cmdlineBasenameEnd; + + if (!cmdline) { + cmdlineBasenameStart = 0; + cmdlineBasenameEnd = 0; + cmdline = "(zombie)"; + } + + assert(cmdlineBasenameStart >= 0); + assert(cmdlineBasenameStart <= (int)strlen(cmdline)); + + if (!showMergedCommand || !procExe || !procComm) { /* fall back to cmdline */ + if (showMergedCommand && showThreadNames && !procExe && procComm && strlen(procComm)) { /* Prefix column with comm */ + if (strncmp(cmdline + cmdlineBasenameStart, procComm, MINIMUM(TASK_COMM_LEN - 1, strlen(procComm))) != 0) { + WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); + str = stpcpy(str, procComm); + + WRITE_SEPARATOR; + } + } + + if (cmdlineBasenameEnd > cmdlineBasenameStart) + WRITE_HIGHLIGHT(showProgramPath ? cmdlineBasenameStart : 0, cmdlineBasenameEnd - cmdlineBasenameStart, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); + (void)stpcpyWithNewlineConversion(str, cmdline + (showProgramPath ? 0 : cmdlineBasenameStart)); + + return; + } + + int exeLen = strlen(this->procExe); + int exeBasenameOffset = this->procExeBasenameOffset; + int exeBasenameLen = exeLen - exeBasenameOffset; + + assert(exeBasenameOffset >= 0); + assert(exeBasenameOffset <= (int)strlen(procExe)); + + bool haveCommInExe = false; + if (procExe && procComm && showThreadNames) { + haveCommInExe = strncmp(procExe + exeBasenameOffset, procComm, TASK_COMM_LEN - 1) == 0; + } + + /* Start with copying exe */ + if (showProgramPath) { + if (haveCommInExe) + WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); + WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); + if (this->procExeDeleted) + WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, delExeAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED); + else if (this->usesDeletedLib) + WRITE_HIGHLIGHT(exeBasenameOffset, exeBasenameLen, delLibAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED); + str = stpcpy(str, procExe); + } else { + if (haveCommInExe) + WRITE_HIGHLIGHT(0, exeBasenameLen, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); + WRITE_HIGHLIGHT(0, exeBasenameLen, baseAttr, CMDLINE_HIGHLIGHT_FLAG_BASENAME); + if (this->procExeDeleted) + WRITE_HIGHLIGHT(0, exeBasenameLen, delExeAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED); + else if (this->usesDeletedLib) + WRITE_HIGHLIGHT(0, exeBasenameLen, delLibAttr, CMDLINE_HIGHLIGHT_FLAG_DELETED); + str = stpcpy(str, procExe + exeBasenameOffset); + } + + bool haveCommInCmdline = false; + int commStart = 0; + int commEnd = 0; + + /* Try to match procComm with procExe's basename: This is reliable (predictable) */ + if (searchCommInCmdline) { + /* commStart/commEnd will be adjusted later along with cmdline */ + haveCommInCmdline = showThreadNames && findCommInCmdline(procComm, cmdline, cmdlineBasenameStart, &commStart, &commEnd); + } + + int matchLen = matchCmdlinePrefixWithExeSuffix(cmdline, cmdlineBasenameStart, procExe, exeBasenameOffset, exeBasenameLen); + + bool haveCommField = false; + + if (!haveCommInExe && !haveCommInCmdline && procComm && showThreadNames) { + WRITE_SEPARATOR; + WRITE_HIGHLIGHT(0, strlen(procComm), commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); + str = stpcpy(str, procComm); + haveCommField = true; + } + + if (matchLen) { + /* strip the matched exe prefix */ + cmdline += matchLen; + + commStart -= matchLen; + commEnd -= matchLen; + } + + if (!matchLen || (haveCommField && *cmdline)) { + /* cmdline will be a separate field */ + WRITE_SEPARATOR; + } + + if (!haveCommInExe && haveCommInCmdline && !haveCommField && showThreadNames) + WRITE_HIGHLIGHT(commStart, commEnd - commStart, commAttr, CMDLINE_HIGHLIGHT_FLAG_COMM); + + /* Display cmdline if it hasn't been consumed by procExe */ + if (*cmdline) + (void)stpcpyWithNewlineConversion(str, cmdline); + + #undef WRITE_SEPARATOR + #undef WRITE_HIGHLIGHT +} + +void Process_writeCommand(const Process* this, int attr, int baseAttr, RichString* str) { + (void)baseAttr; + + const ProcessMergedCommand* mc = &this->mergedCommand; + + int strStart = RichString_size(str); + + const bool highlightBaseName = this->settings->highlightBaseName; + const bool highlightSeparator = true; + const bool highlightDeleted = this->settings->highlightDeletedExe; + + if (!this->mergedCommand.str) { + int len = 0; + const char* cmdline = this->cmdline; + + if (highlightBaseName || !this->settings->showProgramPath) { + int basename = 0; + for (int i = 0; i < this->cmdlineBasenameEnd; i++) { + if (cmdline[i] == '/') { + basename = i + 1; + } else if (cmdline[i] == ':') { + len = i + 1; + break; + } + } + if (len == 0) { + if (this->settings->showProgramPath) { + strStart += basename; + } else { + cmdline += basename; + } + len = this->cmdlineBasenameEnd - basename; + } + } + + RichString_appendWide(str, attr, cmdline); + + if (this->settings->highlightBaseName) { + RichString_setAttrn(str, baseAttr, strStart, len); + } + + return; + } + + RichString_appendWide(str, attr, this->mergedCommand.str); + + for (size_t i = 0, hlCount = CLAMP(mc->highlightCount, 0, ARRAYSIZE(mc->highlights)); i < hlCount; i++) { + const ProcessCmdlineHighlight* hl = &mc->highlights[i]; + + if (!hl->length) + continue; + + if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_SEPARATOR) + if (!highlightSeparator) + continue; + + if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_BASENAME) + if (!highlightBaseName) + continue; + + if (hl->flags & CMDLINE_HIGHLIGHT_FLAG_DELETED) + if (!highlightDeleted) + continue; + + RichString_setAttrn(str, hl->attr, strStart + hl->offset, hl->length); + } +} + +void Process_printRate(RichString* str, double rate, bool coloring) { + char buffer[16]; + + int largeNumberColor = CRT_colors[LARGE_NUMBER]; + int processMegabytesColor = CRT_colors[PROCESS_MEGABYTES]; + int processColor = CRT_colors[PROCESS]; + int shadowColor = CRT_colors[PROCESS_SHADOW]; + + if (!coloring) { + largeNumberColor = CRT_colors[PROCESS]; + processMegabytesColor = CRT_colors[PROCESS]; + } + + if (isnan(rate)) { + RichString_appendAscii(str, shadowColor, " N/A "); + } else if (rate < 0.005) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f B/s ", rate); + RichString_appendnAscii(str, shadowColor, buffer, len); + } else if (rate < ONE_K) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f B/s ", rate); + RichString_appendnAscii(str, processColor, buffer, len); + } else if (rate < ONE_M) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f K/s ", rate / ONE_K); + RichString_appendnAscii(str, processColor, buffer, len); + } else if (rate < ONE_G) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f M/s ", rate / ONE_M); + RichString_appendnAscii(str, processMegabytesColor, buffer, len); + } else if (rate < ONE_T) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f G/s ", rate / ONE_G); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + } else if (rate < ONE_P) { + int len = snprintf(buffer, sizeof(buffer), "%7.2f T/s ", rate / ONE_T); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + } else { + int len = snprintf(buffer, sizeof(buffer), "%7.2f P/s ", rate / ONE_P); + RichString_appendnAscii(str, largeNumberColor, buffer, len); + } +} + +void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width) { + int columns = width; + RichString_appendnWideColumns(str, attr, content, strlen(content), &columns); + RichString_appendChr(str, attr, ' ', width + 1 - columns); +} + +void Process_writeField(const Process* this, RichString* str, ProcessField field) { + char buffer[256]; + size_t n = sizeof(buffer); + int attr = CRT_colors[DEFAULT_COLOR]; + bool coloring = this->settings->highlightMegabytes; + + switch (field) { + case COMM: { + int baseattr = CRT_colors[PROCESS_BASENAME]; + if (this->settings->highlightThreads && Process_isThread(this)) { + attr = CRT_colors[PROCESS_THREAD]; + baseattr = CRT_colors[PROCESS_THREAD_BASENAME]; + } + if (!this->settings->treeView || this->indent == 0) { + Process_writeCommand(this, attr, baseattr, str); + return; + } + + char* buf = buffer; + int maxIndent = 0; + bool lastItem = (this->indent < 0); + int indent = (this->indent < 0 ? -this->indent : this->indent); + + for (int i = 0; i < 32; i++) { + if (indent & (1U << i)) { + maxIndent = i + 1; + } + } + + for (int i = 0; i < maxIndent - 1; i++) { + int written, ret; + if (indent & (1 << i)) { + ret = xSnprintf(buf, n, "%s ", CRT_treeStr[TREE_STR_VERT]); + } else { + ret = xSnprintf(buf, n, " "); + } + if (ret < 0 || (size_t)ret >= n) { + written = n; + } else { + written = ret; + } + buf += written; + n -= written; + } + + const char* draw = CRT_treeStr[lastItem ? TREE_STR_BEND : TREE_STR_RTEE]; + xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] ); + RichString_appendWide(str, CRT_colors[PROCESS_TREE], buffer); + Process_writeCommand(this, attr, baseattr, str); + return; + } + case PROC_COMM: { + const char* procComm; + if (this->procComm) { + attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM]; + procComm = this->procComm; + } else { + attr = CRT_colors[PROCESS_SHADOW]; + procComm = Process_isKernelThread(this) ? kthreadID : "N/A"; + } + + Process_printLeftAlignedField(str, attr, procComm, TASK_COMM_LEN - 1); + return; + } + case PROC_EXE: { + const char* procExe; + if (this->procExe) { + attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_BASENAME : PROCESS_BASENAME]; + if (this->settings->highlightDeletedExe) { + if (this->procExeDeleted) + attr = CRT_colors[FAILED_READ]; + else if (this->usesDeletedLib) + attr = CRT_colors[PROCESS_TAG]; + } + procExe = this->procExe + this->procExeBasenameOffset; + } else { + attr = CRT_colors[PROCESS_SHADOW]; + procExe = Process_isKernelThread(this) ? kthreadID : "N/A"; + } + + Process_printLeftAlignedField(str, attr, procExe, TASK_COMM_LEN - 1); + return; + } + case CWD: { + const char* cwd; + if (!this->procCwd) { + attr = CRT_colors[PROCESS_SHADOW]; + cwd = "N/A"; + } else if (String_startsWith(this->procCwd, "/proc/") && strstr(this->procCwd, " (deleted)") != NULL) { + attr = CRT_colors[PROCESS_SHADOW]; + cwd = "main thread terminated"; + } else { + cwd = this->procCwd; + } + Process_printLeftAlignedField(str, attr, cwd, 25); + return; + } + case ELAPSED: Process_printTime(str, /* convert to hundreds of a second */ this->processList->realtimeMs / 10 - 100 * this->starttime_ctime, coloring); return; + case MAJFLT: Process_printCount(str, this->majflt, coloring); return; + case MINFLT: Process_printCount(str, this->minflt, coloring); return; + case M_RESIDENT: Process_printKBytes(str, this->m_resident, coloring); return; + case M_VIRT: Process_printKBytes(str, this->m_virt, coloring); return; + case NICE: + xSnprintf(buffer, n, "%3ld ", this->nice); + attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY] + : this->nice > 0 ? CRT_colors[PROCESS_LOW_PRIORITY] + : CRT_colors[PROCESS_SHADOW]; + break; + case NLWP: + if (this->nlwp == 1) + attr = CRT_colors[PROCESS_SHADOW]; + + xSnprintf(buffer, n, "%4ld ", this->nlwp); + break; + case PERCENT_CPU: + case PERCENT_NORM_CPU: { + float cpuPercentage = this->percent_cpu; + if (field == PERCENT_NORM_CPU) { + cpuPercentage /= this->processList->cpuCount; + } + if (cpuPercentage > 999.9F) { + xSnprintf(buffer, n, "%4u ", (unsigned int)cpuPercentage); + } else if (cpuPercentage > 99.9F) { + xSnprintf(buffer, n, "%3u. ", (unsigned int)cpuPercentage); + } else { + if (cpuPercentage < 0.05F) + attr = CRT_colors[PROCESS_SHADOW]; + + xSnprintf(buffer, n, "%4.1f ", cpuPercentage); + } + break; + } + case PERCENT_MEM: + if (this->percent_mem > 99.9F) { + xSnprintf(buffer, n, "100. "); + } else { + if (this->percent_mem < 0.05F) + attr = CRT_colors[PROCESS_SHADOW]; + + xSnprintf(buffer, n, "%4.1f ", this->percent_mem); + } + break; + case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break; + case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pid); break; + case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->ppid); break; + case PRIORITY: + if (this->priority <= -100) + xSnprintf(buffer, n, " RT "); + else + xSnprintf(buffer, n, "%3ld ", this->priority); + break; + case PROCESSOR: xSnprintf(buffer, n, "%3d ", Settings_cpuId(this->settings, this->processor)); break; + case SESSION: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->session); break; + case STARTTIME: xSnprintf(buffer, n, "%s", this->starttime_show); break; + case STATE: + xSnprintf(buffer, n, "%c ", this->state); + switch (this->state) { + case 'R': + attr = CRT_colors[PROCESS_R_STATE]; + break; + case 'D': + attr = CRT_colors[PROCESS_D_STATE]; + break; + case 'I': + case 'S': + attr = CRT_colors[PROCESS_SHADOW]; + break; + } + break; + case ST_UID: xSnprintf(buffer, n, "%5d ", this->st_uid); break; + case TIME: Process_printTime(str, this->time, coloring); return; + case TGID: + if (this->tgid == this->pid) + attr = CRT_colors[PROCESS_SHADOW]; + + xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tgid); + break; + case TPGID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->tpgid); break; + case TTY: + if (!this->tty_name) { + attr = CRT_colors[PROCESS_SHADOW]; + xSnprintf(buffer, n, "(no tty) "); + } else { + const char* name = String_startsWith(this->tty_name, "/dev/") ? (this->tty_name + strlen("/dev/")) : this->tty_name; + xSnprintf(buffer, n, "%-8s ", name); + } + break; + case USER: + if (Process_getuid != this->st_uid) + attr = CRT_colors[PROCESS_SHADOW]; + + if (this->user) { + Process_printLeftAlignedField(str, attr, this->user, 9); + return; + } + + xSnprintf(buffer, n, "%-9d ", this->st_uid); + break; + default: + assert(0 && "Process_writeField: default key reached"); /* should never be reached */ + xSnprintf(buffer, n, "- "); + } + RichString_appendAscii(str, attr, buffer); +} + +void Process_display(const Object* cast, RichString* out) { + const Process* this = (const Process*) cast; + const ProcessField* fields = this->settings->fields; + for (int i = 0; fields[i]; i++) + As_Process(this)->writeField(this, out, fields[i]); + + if (this->settings->shadowOtherUsers && this->st_uid != Process_getuid) { + RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]); + } + + if (this->tag == true) { + RichString_setAttr(out, CRT_colors[PROCESS_TAG]); + } + + if (this->settings->highlightChanges) { + if (Process_isTomb(this)) { + out->highlightAttr = CRT_colors[PROCESS_TOMB]; + } else if (Process_isNew(this)) { + out->highlightAttr = CRT_colors[PROCESS_NEW]; + } + } + + assert(RichString_size(out) > 0); +} + +void Process_done(Process* this) { + assert (this != NULL); + free(this->cmdline); + free(this->procComm); + free(this->procExe); + free(this->procCwd); + free(this->mergedCommand.str); + free(this->tty_name); +} + +/* This function returns the string displayed in Command column, so that sorting + * happens on what is displayed - whether comm, full path, basename, etc.. So + * this follows Process_writeField(COMM) and Process_writeCommand */ +const char* Process_getCommandStr(const Process* this) { + if ((Process_isUserlandThread(this) && this->settings->showThreadNames) || !this->mergedCommand.str) { + return this->cmdline; + } + + return this->mergedCommand.str; +} + +const ProcessClass Process_class = { + .super = { + .extends = Class(Object), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = Process_writeField, + .getCommandStr = Process_getCommandStr, +}; + +void Process_init(Process* this, const Settings* settings) { + this->settings = settings; + this->tag = false; + this->showChildren = true; + this->show = true; + this->updated = false; + this->cmdlineBasenameEnd = -1; + this->st_uid = (uid_t)-1; + + if (Process_getuid == (uid_t)-1) { + Process_getuid = getuid(); + } +} + +void Process_toggleTag(Process* this) { + this->tag = !this->tag; +} + +bool Process_isNew(const Process* this) { + assert(this->processList); + if (this->processList->monotonicMs >= this->seenStampMs) { + return this->processList->monotonicMs - this->seenStampMs <= 1000 * (uint64_t)this->processList->settings->highlightDelaySecs; + } + return false; +} + +bool Process_isTomb(const Process* this) { + return this->tombStampMs > 0; +} + +bool Process_setPriority(Process* this, int priority) { + if (Settings_isReadonly()) + return false; + + int old_prio = getpriority(PRIO_PROCESS, this->pid); + int err = setpriority(PRIO_PROCESS, this->pid, priority); + + if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) { + this->nice = priority; + } + return (err == 0); +} + +bool Process_changePriorityBy(Process* this, Arg delta) { + return Process_setPriority(this, this->nice + delta.i); +} + +bool Process_sendSignal(Process* this, Arg sgn) { + return kill(this->pid, sgn.i) == 0; +} + +int Process_pidCompare(const void* v1, const void* v2) { + const Process* p1 = (const Process*)v1; + const Process* p2 = (const Process*)v2; + + return SPACESHIP_NUMBER(p1->pid, p2->pid); +} + +int Process_compare(const void* v1, const void* v2) { + const Process* p1 = (const Process*)v1; + const Process* p2 = (const Process*)v2; + + const Settings* settings = p1->settings; + + ProcessField key = Settings_getActiveSortKey(settings); + + int result = Process_compareByKey(p1, p2, key); + + // Implement tie-breaker (needed to make tree mode more stable) + if (!result) + return SPACESHIP_NUMBER(p1->pid, p2->pid); + + return (Settings_getActiveDirection(settings) == 1) ? result : -result; +} + +static uint8_t stateCompareValue(char state) { + switch (state) { + + case 'S': + return 10; + + case 'I': + return 9; + + case 'X': + return 8; + + case 'Z': + return 7; + + case 't': + return 6; + + case 'T': + return 5; + + case 'L': + return 4; + + case 'D': + return 3; + + case 'R': + return 2; + + case '?': + return 1; + + default: + return 0; + } +} + +int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) { + int r; + + switch (key) { + case PERCENT_CPU: + case PERCENT_NORM_CPU: + return SPACESHIP_NUMBER(p1->percent_cpu, p2->percent_cpu); + case PERCENT_MEM: + return SPACESHIP_NUMBER(p1->m_resident, p2->m_resident); + case COMM: + return SPACESHIP_NULLSTR(Process_getCommand(p1), Process_getCommand(p2)); + case PROC_COMM: { + const char* comm1 = p1->procComm ? p1->procComm : (Process_isKernelThread(p1) ? kthreadID : ""); + const char* comm2 = p2->procComm ? p2->procComm : (Process_isKernelThread(p2) ? kthreadID : ""); + return SPACESHIP_NULLSTR(comm1, comm2); + } + case PROC_EXE: { + const char* exe1 = p1->procExe ? (p1->procExe + p1->procExeBasenameOffset) : (Process_isKernelThread(p1) ? kthreadID : ""); + const char* exe2 = p2->procExe ? (p2->procExe + p2->procExeBasenameOffset) : (Process_isKernelThread(p2) ? kthreadID : ""); + return SPACESHIP_NULLSTR(exe1, exe2); + } + case CWD: + return SPACESHIP_NULLSTR(p1->procCwd, p2->procCwd); + case ELAPSED: + r = -SPACESHIP_NUMBER(p1->starttime_ctime, p2->starttime_ctime); + return r != 0 ? r : SPACESHIP_NUMBER(p1->pid, p2->pid); + case MAJFLT: + return SPACESHIP_NUMBER(p1->majflt, p2->majflt); + case MINFLT: + return SPACESHIP_NUMBER(p1->minflt, p2->minflt); + case M_RESIDENT: + return SPACESHIP_NUMBER(p1->m_resident, p2->m_resident); + case M_VIRT: + return SPACESHIP_NUMBER(p1->m_virt, p2->m_virt); + case NICE: + return SPACESHIP_NUMBER(p1->nice, p2->nice); + case NLWP: + return SPACESHIP_NUMBER(p1->nlwp, p2->nlwp); + case PGRP: + return SPACESHIP_NUMBER(p1->pgrp, p2->pgrp); + case PID: + return SPACESHIP_NUMBER(p1->pid, p2->pid); + case PPID: + return SPACESHIP_NUMBER(p1->ppid, p2->ppid); + case PRIORITY: + return SPACESHIP_NUMBER(p1->priority, p2->priority); + case PROCESSOR: + return SPACESHIP_NUMBER(p1->processor, p2->processor); + case SESSION: + return SPACESHIP_NUMBER(p1->session, p2->session); + case STARTTIME: + r = SPACESHIP_NUMBER(p1->starttime_ctime, p2->starttime_ctime); + return r != 0 ? r : SPACESHIP_NUMBER(p1->pid, p2->pid); + case STATE: + return SPACESHIP_NUMBER(stateCompareValue(p1->state), stateCompareValue(p2->state)); + case ST_UID: + return SPACESHIP_NUMBER(p1->st_uid, p2->st_uid); + case TIME: + return SPACESHIP_NUMBER(p1->time, p2->time); + case TGID: + return SPACESHIP_NUMBER(p1->tgid, p2->tgid); + case TPGID: + return SPACESHIP_NUMBER(p1->tpgid, p2->tpgid); + case TTY: + /* Order no tty last */ + return SPACESHIP_DEFAULTSTR(p1->tty_name, p2->tty_name, "\x7F"); + case USER: + return SPACESHIP_NULLSTR(p1->user, p2->user); + default: + assert(0 && "Process_compareByKey_Base: default key reached"); /* should never be reached */ + return SPACESHIP_NUMBER(p1->pid, p2->pid); + } +} + +void Process_updateComm(Process* this, const char* comm) { + if (!this->procComm && !comm) + return; + + if (this->procComm && comm && String_eq(this->procComm, comm)) + return; + + free(this->procComm); + this->procComm = comm ? xStrdup(comm) : NULL; + this->mergedCommand.commChanged = true; +} + +static int skipPotentialPath(const char* cmdline, int end) { + if (cmdline[0] != '/') + return 0; + + int slash = 0; + for (int i = 1; i < end; i++) { + if (cmdline[i] == '/' && cmdline[i + 1] != '\0') { + slash = i + 1; + continue; + } + + if (cmdline[i] == ' ' && cmdline[i - 1] != '\\') + return slash; + + if (cmdline[i] == ':' && cmdline[i + 1] == ' ') + return slash; + } + + return slash; +} + +void Process_updateCmdline(Process* this, const char* cmdline, int basenameStart, int basenameEnd) { + assert(basenameStart >= 0); + assert((cmdline && basenameStart < (int)strlen(cmdline)) || (!cmdline && basenameStart == 0)); + assert((basenameEnd > basenameStart) || (basenameEnd == 0 && basenameStart == 0)); + assert((cmdline && basenameEnd <= (int)strlen(cmdline)) || (!cmdline && basenameEnd == 0)); + + if (!this->cmdline && !cmdline) + return; + + if (this->cmdline && cmdline && String_eq(this->cmdline, cmdline)) + return; + + free(this->cmdline); + this->cmdline = cmdline ? xStrdup(cmdline) : NULL; + this->cmdlineBasenameStart = (basenameStart || !cmdline) ? basenameStart : skipPotentialPath(cmdline, basenameEnd); + this->cmdlineBasenameEnd = basenameEnd; + this->mergedCommand.cmdlineChanged = true; +} + +void Process_updateExe(Process* this, const char* exe) { + if (!this->procExe && !exe) + return; + + if (this->procExe && exe && String_eq(this->procExe, exe)) + return; + + free(this->procExe); + if (exe) { + this->procExe = xStrdup(exe); + const char* lastSlash = strrchr(exe, '/'); + this->procExeBasenameOffset = (lastSlash && *(lastSlash + 1) != '\0' && lastSlash != exe) ? (lastSlash - exe + 1) : 0; + } else { + this->procExe = NULL; + this->procExeBasenameOffset = 0; + } + this->mergedCommand.exeChanged = true; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Process.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Process.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Process.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Process.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,397 @@ +#ifndef HEADER_Process +#define HEADER_Process +/* +htop - Process.h +(C) 2004-2015 Hisham H. Muhammad +(C) 2020 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +#include "Object.h" +#include "ProcessField.h" +#include "RichString.h" + + +#define PROCESS_FLAG_IO 0x00000001 +#define PROCESS_FLAG_CWD 0x00000002 + +#define DEFAULT_HIGHLIGHT_SECS 5 + +typedef enum ProcessField_ { + NULL_PROCESSFIELD = 0, + PID = 1, + COMM = 2, + STATE = 3, + PPID = 4, + PGRP = 5, + SESSION = 6, + TTY = 7, + TPGID = 8, + MINFLT = 10, + MAJFLT = 12, + PRIORITY = 18, + NICE = 19, + STARTTIME = 21, + PROCESSOR = 38, + M_VIRT = 39, + M_RESIDENT = 40, + ST_UID = 46, + PERCENT_CPU = 47, + PERCENT_MEM = 48, + USER = 49, + TIME = 50, + NLWP = 51, + TGID = 52, + PERCENT_NORM_CPU = 53, + ELAPSED = 54, + PROC_COMM = 124, + PROC_EXE = 125, + CWD = 126, + + /* Platform specific fields, defined in ${platform}/ProcessField.h */ + PLATFORM_PROCESS_FIELDS + + LAST_PROCESSFIELD +} ProcessField; + +struct Settings_; + +/* Holds information about regions of the cmdline that should be + * highlighted (e.g. program basename, delimiter, comm). */ +typedef struct ProcessCmdlineHighlight_ { + size_t offset; /* first character to highlight */ + size_t length; /* How many characters to highlight, zero if unused */ + int attr; /* The attributes used to highlight */ + int flags; /* Special flags used for selective highlighting, zero for always */ +} ProcessCmdlineHighlight; + +/* ProcessMergedCommand is populated by Process_makeCommandStr: It + * contains the merged Command string, and the information needed by + * Process_writeCommand to color the string. str will be NULL for kernel + * threads and zombies */ +typedef struct ProcessMergedCommand_ { + char* str; /* merged Command string */ + size_t highlightCount; /* how many portions of cmdline to highlight */ + ProcessCmdlineHighlight highlights[8]; /* which portions of cmdline to highlight */ + bool separateComm : 1; /* whether comm is a separate field */ + bool unmatchedExe : 1; /* whether exe matched with cmdline */ + bool cmdlineChanged : 1; /* whether cmdline changed */ + bool exeChanged : 1; /* whether exe changed */ + bool commChanged : 1; /* whether comm changed */ + bool prevMergeSet : 1; /* whether showMergedCommand was set */ + bool prevPathSet : 1; /* whether showProgramPath was set */ + bool prevCommSet : 1; /* whether findCommInCmdline was set */ + bool prevCmdlineSet : 1; /* whether stripExeFromCmdline was set */ + bool prevShowThreadNames : 1; /* whether showThreadNames was set */ +} ProcessMergedCommand; + +typedef struct Process_ { + /* Super object for emulated OOP */ + Object super; + + /* Pointer to quasi-global data structures */ + const struct ProcessList_* processList; + const struct Settings_* settings; + + /* Process identifier */ + pid_t pid; + + /* Parent process identifier */ + pid_t ppid; + + /* Thread group identifier */ + pid_t tgid; + + /* Process group identifier */ + int pgrp; + + /* Session identifier */ + int session; + + /* Foreground group identifier of the controlling terminal */ + int tpgid; + + /* This is a kernel (helper) task */ + bool isKernelThread; + + /* This is a userland thread / LWP */ + bool isUserlandThread; + + /* Controlling terminal identifier of the process */ + unsigned long int tty_nr; + + /* Controlling terminal name of the process */ + char* tty_name; + + /* User identifier */ + uid_t st_uid; + + /* User name */ + const char* user; + + /* Process runtime (in hundredth of a second) */ + unsigned long long int time; + + /* + * Process name including arguments. + * Use Process_getCommand() for Command actually displayed. + */ + char* cmdline; + + /* End Offset in cmdline of the process basename */ + int cmdlineBasenameEnd; + + /* Start Offset in cmdline of the process basename */ + int cmdlineBasenameStart; + + /* The process' "command" name */ + char* procComm; + + /* The main process executable */ + char* procExe; + + /* The process/thread working directory */ + char* procCwd; + + /* Offset in procExe of the process basename */ + int procExeBasenameOffset; + + /* Tells if the executable has been replaced in the filesystem since start */ + bool procExeDeleted; + + /* Tells if the process uses replaced shared libraries since start */ + bool usesDeletedLib; + + /* CPU number last executed on */ + int processor; + + /* CPU usage during last cycle (in percent) */ + float percent_cpu; + + /* Memory usage during last cycle (in percent) */ + float percent_mem; + + /* Scheduling priority */ + long int priority; + + /* Nice value */ + long int nice; + + /* Number of threads in this process */ + long int nlwp; + + /* Process start time (in seconds elapsed since the Epoch) */ + time_t starttime_ctime; + + /* Process start time (cached formatted string) */ + char starttime_show[8]; + + /* Total program size (in kilobytes) */ + long m_virt; + + /* Resident set size (in kilobytes) */ + long m_resident; + + /* Number of minor faults the process has made which have not required loading a memory page from disk */ + unsigned long int minflt; + + /* Number of major faults the process has made which have required loading a memory page from disk */ + unsigned long int majflt; + + /* + * Process state (platform dependent): + * D - Waiting + * I - Idle + * L - Acquiring lock + * R - Running + * S - Sleeping + * T - Stopped (on a signal) + * X - Dead + * Z - Zombie + * t - Tracing stop + * ? - Unknown + */ + char state; + + /* Whether the process was updated during the current scan */ + bool updated; + + /* Whether the process was tagged by the user */ + bool tag; + + /* Whether to display this process */ + bool show; + + /* Whether this process was shown last cycle */ + bool wasShown; + + /* Whether to show children of this process in tree-mode */ + bool showChildren; + + /* + * Internal time counts for showing new and exited processes. + */ + uint64_t seenStampMs; + uint64_t tombStampMs; + + /* + * Internal state for tree-mode. + */ + int indent; + unsigned int tree_left; + unsigned int tree_right; + unsigned int tree_depth; + unsigned int tree_index; + + /* + * Internal state for merged Command display + */ + ProcessMergedCommand mergedCommand; +} Process; + +typedef struct ProcessFieldData_ { + /* Name (displayed in setup menu) */ + const char* name; + + /* Title (display in main screen); must have same width as the printed values */ + const char* title; + + /* Description (displayed in setup menu) */ + const char* description; + + /* Scan flag to enable scan-method otherwise not run */ + uint32_t flags; + + /* Whether the values are process identifies; adjusts the width of title and values if true */ + bool pidColumn; + + /* Whether the column should be sorted in descending order by default */ + bool defaultSortDesc; +} ProcessFieldData; + +// Implemented in platform-specific code: +void Process_writeField(const Process* this, RichString* str, ProcessField field); +int Process_compare(const void* v1, const void* v2); +void Process_delete(Object* cast); +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; +#define PROCESS_MAX_PID_DIGITS 19 +extern int Process_pidDigits; + +typedef Process* (*Process_New)(const struct Settings_*); +typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField); +typedef int (*Process_CompareByKey)(const Process*, const Process*, ProcessField); +typedef const char* (*Process_GetCommandStr)(const Process*); + +typedef struct ProcessClass_ { + const ObjectClass super; + const Process_WriteField writeField; + const Process_CompareByKey compareByKey; + const Process_GetCommandStr getCommandStr; +} ProcessClass; + +#define As_Process(this_) ((const ProcessClass*)((this_)->super.klass)) + +#define Process_getCommand(this_) (As_Process(this_)->getCommandStr ? As_Process(this_)->getCommandStr((const Process*)(this_)) : Process_getCommandStr((const Process*)(this_))) +#define Process_compareByKey(p1_, p2_, key_) (As_Process(p1_)->compareByKey ? (As_Process(p1_)->compareByKey(p1_, p2_, key_)) : Process_compareByKey_Base(p1_, p2_, key_)) + +static inline pid_t Process_getParentPid(const Process* this) { + return this->tgid == this->pid ? this->ppid : this->tgid; +} + +static inline bool Process_isChildOf(const Process* this, pid_t pid) { + return pid == Process_getParentPid(this); +} + +static inline bool Process_isKernelThread(const Process* this) { + return this->isKernelThread; +} + +static inline bool Process_isUserlandThread(const Process* this) { + return this->isUserlandThread; +} + +static inline bool Process_isThread(const Process* this) { + return Process_isUserlandThread(this) || Process_isKernelThread(this); +} + +#define CMDLINE_HIGHLIGHT_FLAG_SEPARATOR 0x00000001 +#define CMDLINE_HIGHLIGHT_FLAG_BASENAME 0x00000002 +#define CMDLINE_HIGHLIGHT_FLAG_COMM 0x00000004 +#define CMDLINE_HIGHLIGHT_FLAG_DELETED 0x00000008 + +#define ONE_K 1024UL +#define ONE_M (ONE_K * ONE_K) +#define ONE_G (ONE_M * ONE_K) +#define ONE_T (1ULL * ONE_G * ONE_K) +#define ONE_P (1ULL * ONE_T * ONE_K) + +#define ONE_DECIMAL_K 1000UL +#define ONE_DECIMAL_M (ONE_DECIMAL_K * ONE_DECIMAL_K) +#define ONE_DECIMAL_G (ONE_DECIMAL_M * ONE_DECIMAL_K) +#define ONE_DECIMAL_T (1ULL * ONE_DECIMAL_G * ONE_DECIMAL_K) +#define ONE_DECIMAL_P (1ULL * ONE_DECIMAL_T * ONE_DECIMAL_K) + +void Process_setupColumnWidths(void); + +/* Takes number in bytes (base 1024). Prints 6 columns. */ +void Process_printBytes(RichString* str, unsigned long long number, bool coloring); + +/* Takes number in kilo bytes (base 1024). Prints 6 columns. */ +void Process_printKBytes(RichString* str, unsigned long long number, bool coloring); + +/* Takes number as count (base 1000). Prints 12 columns. */ +void Process_printCount(RichString* str, unsigned long long number, bool coloring); + +/* Takes time in hundredths of a seconds. Prints 9 columns. */ +void Process_printTime(RichString* str, unsigned long long totalHundredths, bool coloring); + +/* Takes rate in bare unit (base 1024) per second. Prints 12 columns. */ +void Process_printRate(RichString* str, double rate, bool coloring); + +void Process_fillStarttimeBuffer(Process* this); + +void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width); + +void Process_display(const Object* cast, RichString* out); + +void Process_done(Process* this); + +extern const ProcessClass Process_class; + +void Process_init(Process* this, const struct Settings_* settings); + +void Process_toggleTag(Process* this); + +bool Process_isNew(const Process* this); + +bool Process_isTomb(const Process* this); + +bool Process_setPriority(Process* this, int priority); + +bool Process_changePriorityBy(Process* this, Arg delta); + +bool Process_sendSignal(Process* this, Arg sgn); + +int Process_pidCompare(const void* v1, const void* v2); + +int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key); + +// Avoid direct calls, use Process_getCommand instead +const char* Process_getCommandStr(const Process* this); + +void Process_updateComm(Process* this, const char* comm); +void Process_updateCmdline(Process* this, const char* cmdline, int basenameStart, int basenameEnd); +void Process_updateExe(Process* this, const char* exe); + +/* This function constructs the string that is displayed by + * Process_writeCommand and also returned by Process_getCommandStr */ +void Process_makeCommandStr(Process* this); + +void Process_writeCommand(const Process* this, int attr, int baseAttr, RichString* str); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessList.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,641 @@ +/* +htop - ProcessList.c +(C) 2004,2005 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "ProcessList.h" + +#include +#include +#include + +#include "CRT.h" +#include "Hashtable.h" +#include "Macros.h" +#include "Platform.h" +#include "Vector.h" +#include "XUtils.h" + + +ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + this->processes = Vector_new(klass, true, DEFAULT_SIZE); + this->processes2 = Vector_new(klass, true, DEFAULT_SIZE); // tree-view auxiliary buffer + + this->processTable = Hashtable_new(200, false); + this->displayTreeSet = Hashtable_new(200, false); + this->draftingTreeSet = Hashtable_new(200, false); + + this->usersTable = usersTable; + this->pidMatchList = pidMatchList; + this->dynamicMeters = dynamicMeters; + + this->userId = userId; + + // set later by platform-specific code + this->cpuCount = 0; + this->monotonicMs = 0; + + // always maintain valid realtime timestamps + Platform_gettime_realtime(&this->realtime, &this->realtimeMs); + +#ifdef HAVE_LIBHWLOC + this->topologyOk = false; + if (hwloc_topology_init(&this->topology) == 0) { + this->topologyOk = + #if HWLOC_API_VERSION < 0x00020000 + /* try to ignore the top-level machine object type */ + 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_MACHINE) && + /* ignore caches, which don't add structure */ + 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CORE) && + 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CACHE) && + 0 == hwloc_topology_set_flags(this->topology, HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) && + #else + 0 == hwloc_topology_set_all_types_filter(this->topology, HWLOC_TYPE_FILTER_KEEP_STRUCTURE) && + #endif + 0 == hwloc_topology_load(this->topology); + } +#endif + + this->following = -1; + + return this; +} + +void ProcessList_done(ProcessList* this) { +#ifdef HAVE_LIBHWLOC + if (this->topologyOk) { + hwloc_topology_destroy(this->topology); + } +#endif + + Hashtable_delete(this->draftingTreeSet); + Hashtable_delete(this->displayTreeSet); + Hashtable_delete(this->processTable); + + Vector_delete(this->processes2); + Vector_delete(this->processes); +} + +void ProcessList_setPanel(ProcessList* this, Panel* panel) { + this->panel = panel; +} + +static const char* alignedProcessFieldTitle(ProcessField field) { + const char* title = Process_fields[field].title; + if (!title) + return "- "; + + if (!Process_fields[field].pidColumn) + return title; + + static char titleBuffer[PROCESS_MAX_PID_DIGITS + /* space */ 1 + /* null-terminator */ + 1]; + xSnprintf(titleBuffer, sizeof(titleBuffer), "%*s ", Process_pidDigits, title); + + return titleBuffer; +} + +void ProcessList_printHeader(const ProcessList* this, RichString* header) { + RichString_rewind(header, RichString_size(header)); + + const Settings* settings = this->settings; + const ProcessField* fields = settings->fields; + + ProcessField key = Settings_getActiveSortKey(settings); + + for (int i = 0; fields[i]; i++) { + int color; + if (settings->treeView && settings->treeViewAlwaysByPID) { + color = CRT_colors[PANEL_HEADER_FOCUS]; + } else if (key == fields[i]) { + color = CRT_colors[PANEL_SELECTION_FOCUS]; + } else { + color = CRT_colors[PANEL_HEADER_FOCUS]; + } + + RichString_appendWide(header, color, alignedProcessFieldTitle(fields[i])); + if (key == fields[i] && RichString_getCharVal(*header, RichString_size(header) - 1) == ' ') { + RichString_rewind(header, 1); // rewind to override space + RichString_appendnWide(header, + CRT_colors[PANEL_SELECTION_FOCUS], + CRT_treeStr[Settings_getActiveDirection(this->settings) == 1 ? TREE_STR_ASC : TREE_STR_DESC], + 1); + } + if (COMM == fields[i] && settings->showMergedCommand) { + RichString_appendAscii(header, color, "(merged)"); + } + } +} + +void ProcessList_add(ProcessList* this, Process* p) { + assert(Vector_indexOf(this->processes, p, Process_pidCompare) == -1); + assert(Hashtable_get(this->processTable, p->pid) == NULL); + p->processList = this; + + // highlighting processes found in first scan by first scan marked "far in the past" + p->seenStampMs = this->monotonicMs; + + Vector_add(this->processes, p); + Hashtable_put(this->processTable, p->pid, p); + + assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1); + assert(Hashtable_get(this->processTable, p->pid) != NULL); + assert(Hashtable_count(this->processTable) == Vector_count(this->processes)); +} + +void ProcessList_remove(ProcessList* this, const Process* p) { + assert(Vector_indexOf(this->processes, p, Process_pidCompare) != -1); + assert(Hashtable_get(this->processTable, p->pid) != NULL); + + const Process* pp = Hashtable_remove(this->processTable, p->pid); + assert(pp == p); (void)pp; + + pid_t pid = p->pid; + int idx = Vector_indexOf(this->processes, p, Process_pidCompare); + assert(idx != -1); + + if (idx >= 0) { + Vector_remove(this->processes, idx); + } + + if (this->following != -1 && this->following == pid) { + this->following = -1; + Panel_setSelectionColor(this->panel, PANEL_SELECTION_FOCUS); + } + + assert(Hashtable_get(this->processTable, pid) == NULL); + assert(Hashtable_count(this->processTable) == Vector_count(this->processes)); +} + +// ProcessList_updateTreeSetLayer sorts this->displayTreeSet, +// relying only on itself. +// +// Algorithm +// +// The algorithm is based on `depth-first search`, +// even though `breadth-first search` approach may be more efficient on first glance, +// after comparison it may be not, as it's not safe to go deeper without first updating the tree structure. +// If it would be safe that approach would likely bring an advantage in performance. +// +// Each call of the function looks for a 'layer'. A 'layer' is a list of processes with the same depth. +// First it sorts a list. Then it runs the function recursively for each element of the sorted list. +// After that it updates the settings of processes. +// +// It relies on `leftBound` and `rightBound` as an optimization to cut the list size at the time it builds a 'layer'. +// +// It uses a temporary Hashtable `draftingTreeSet` because it's not safe to traverse a tree +// and at the same time make changes in it. +// +static void ProcessList_updateTreeSetLayer(ProcessList* this, unsigned int leftBound, unsigned int rightBound, unsigned int deep, unsigned int left, unsigned int right, unsigned int* index, unsigned int* treeIndex, int indent) { + + // It's guaranteed that layer_size is enough space + // but most likely it needs less. Specifically on first iteration. + int layerSize = (right - left) / 2; + + // check if we reach `children` of `leaves` + if (layerSize == 0) + return; + + Vector* layer = Vector_new(Vector_type(this->processes), false, layerSize); + + // Find all processes on the same layer (process with the same `deep` value + // and included in a range from `leftBound` to `rightBound`). + // + // This loop also keeps track of left_bound and right_bound of these processes + // in order not to lose this information once the list is sorted. + // + // The variables left_bound and right_bound are different from what the values lhs and rhs represent. + // While left_bound and right_bound define a range of processes to look at, the values given by lhs and rhs are indices into an array + // + // In the below example note how filtering a range of indices i is different from filtering for processes in the bounds left_bound < x < right_bound … + // + // The nested tree set is sorted by left value, which is guaranteed upon entry/exit of this function. + // + // i | l | r + // 1 | 1 | 9 + // 2 | 2 | 8 + // 3 | 4 | 5 + // 4 | 6 | 7 + for (unsigned int i = leftBound; i < rightBound; i++) { + Process* proc = (Process*)Hashtable_get(this->displayTreeSet, i); + assert(proc); + if (proc && proc->tree_depth == deep && proc->tree_left > left && proc->tree_right < right) { + if (Vector_size(layer) > 0) { + Process* previous_process = (Process*)Vector_get(layer, Vector_size(layer) - 1); + + // Make a 'right_bound' of previous_process in a layer the current process's index. + // + // Use 'tree_depth' as a temporal variable. + // It's safe to do as later 'tree_depth' will be renovated. + previous_process->tree_depth = proc->tree_index; + } + + Vector_add(layer, proc); + } + } + + // The loop above changes just up to process-1. + // So the last process of the layer isn't updated by the above code. + // + // Thus, if present, set the `rightBound` to the last process on the layer + if (Vector_size(layer) > 0) { + Process* previous_process = (Process*)Vector_get(layer, Vector_size(layer) - 1); + previous_process->tree_depth = rightBound; + } + + Vector_quickSort(layer); + + int size = Vector_size(layer); + for (int i = 0; i < size; i++) { + Process* proc = (Process*)Vector_get(layer, i); + + unsigned int idx = (*index)++; + int newLeft = (*treeIndex)++; + + int level = deep == 0 ? 0 : (int)deep - 1; + int currentIndent = indent == -1 ? 0 : indent | (1 << level); + int nextIndent = indent == -1 ? 0 : ((i < size - 1) ? currentIndent : indent); + + unsigned int newLeftBound = proc->tree_index; + unsigned int newRightBound = proc->tree_depth; + ProcessList_updateTreeSetLayer(this, newLeftBound, newRightBound, deep + 1, proc->tree_left, proc->tree_right, index, treeIndex, nextIndent); + + int newRight = (*treeIndex)++; + + proc->tree_left = newLeft; + proc->tree_right = newRight; + proc->tree_index = idx; + proc->tree_depth = deep; + + if (indent == -1) { + proc->indent = 0; + } else if (i == size - 1) { + proc->indent = -currentIndent; + } else { + proc->indent = currentIndent; + } + + Hashtable_put(this->draftingTreeSet, proc->tree_index, proc); + + // It's not strictly necessary to do this, but doing so anyways + // allows for checking the correctness of the inner workings. + Hashtable_remove(this->displayTreeSet, newLeftBound); + } + + Vector_delete(layer); +} + +static void ProcessList_updateTreeSet(ProcessList* this) { + unsigned int index = 0; + unsigned int tree_index = 1; + + const int vsize = Vector_size(this->processes); + + assert(Hashtable_count(this->draftingTreeSet) == 0); + assert((int)Hashtable_count(this->displayTreeSet) == vsize); + + ProcessList_updateTreeSetLayer(this, 0, vsize, 0, 0, vsize * 2 + 1, &index, &tree_index, -1); + + Hashtable* tmp = this->draftingTreeSet; + this->draftingTreeSet = this->displayTreeSet; + this->displayTreeSet = tmp; + + assert(Hashtable_count(this->draftingTreeSet) == 0); + assert((int)Hashtable_count(this->displayTreeSet) == vsize); +} + +static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level, int indent, int direction, bool show, int* node_counter, int* node_index) { + // On OpenBSD the kernel thread 'swapper' has pid 0. + // Do not treat it as root of any tree. + if (pid == 0) + return; + + Vector* children = Vector_new(Class(Process), false, DEFAULT_SIZE); + + for (int i = Vector_size(this->processes) - 1; i >= 0; i--) { + Process* process = (Process*)Vector_get(this->processes, i); + if (process->show && Process_isChildOf(process, pid)) { + process = (Process*)Vector_take(this->processes, i); + Vector_add(children, process); + } + } + + int size = Vector_size(children); + for (int i = 0; i < size; i++) { + int index = (*node_index)++; + Process* process = (Process*)Vector_get(children, i); + + int lft = (*node_counter)++; + + if (!show) { + process->show = false; + } + + int s = Vector_size(this->processes2); + if (direction == 1) { + Vector_add(this->processes2, process); + } else { + Vector_insert(this->processes2, 0, process); + } + + assert(Vector_size(this->processes2) == s + 1); (void)s; + + int nextIndent = indent | (1 << level); + ProcessList_buildTreeBranch(this, process->pid, level + 1, (i < size - 1) ? nextIndent : indent, direction, show ? process->showChildren : false, node_counter, node_index); + if (i == size - 1) { + process->indent = -nextIndent; + } else { + process->indent = nextIndent; + } + + int rht = (*node_counter)++; + + process->tree_left = lft; + process->tree_right = rht; + process->tree_depth = level + 1; + process->tree_index = index; + Hashtable_put(this->displayTreeSet, index, process); + } + Vector_delete(children); +} + +static int ProcessList_treeProcessCompare(const void* v1, const void* v2) { + const Process* p1 = (const Process*)v1; + const Process* p2 = (const Process*)v2; + + return SPACESHIP_NUMBER(p1->tree_left, p2->tree_left); +} + +static int ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) { + const Process* p1 = (const Process*)v1; + const Process* p2 = (const Process*)v2; + + return SPACESHIP_NUMBER(p1->pid, p2->pid); +} + +// Builds a sorted tree from scratch, without relying on previously gathered information +static void ProcessList_buildTree(ProcessList* this) { + int node_counter = 1; + int node_index = 0; + int direction = Settings_getActiveDirection(this->settings); + + // Sort by PID + Vector_quickSortCustomCompare(this->processes, ProcessList_treeProcessCompareByPID); + int vsize = Vector_size(this->processes); + + // Find all processes whose parent is not visible + int size; + while ((size = Vector_size(this->processes))) { + int i; + for (i = 0; i < size; i++) { + Process* process = (Process*)Vector_get(this->processes, i); + + // Immediately consume processes hidden from view + if (!process->show) { + process = (Process*)Vector_take(this->processes, i); + process->indent = 0; + process->tree_depth = 0; + process->tree_left = node_counter++; + process->tree_index = node_index++; + Vector_add(this->processes2, process); + ProcessList_buildTreeBranch(this, process->pid, 0, 0, direction, false, &node_counter, &node_index); + process->tree_right = node_counter++; + Hashtable_put(this->displayTreeSet, process->tree_index, process); + break; + } + + pid_t ppid = Process_getParentPid(process); + + // Bisect the process vector to find parent + int l = 0; + int r = size; + + // If PID corresponds with PPID (e.g. "kernel_task" (PID:0, PPID:0) + // on Mac OS X 10.11.6) cancel bisecting and regard this process as + // root. + if (process->pid == ppid) + r = 0; + + // On Linux both the init process (pid 1) and the root UMH kernel thread (pid 2) + // use a ppid of 0. As that PID can't exist, we can skip searching for it. + if (!ppid) + r = 0; + + while (l < r) { + int c = (l + r) / 2; + pid_t pid = ((Process*)Vector_get(this->processes, c))->pid; + if (ppid == pid) { + break; + } else if (ppid < pid) { + r = c; + } else { + l = c + 1; + } + } + + // If parent not found, then construct the tree with this node as root + if (l >= r) { + process = (Process*)Vector_take(this->processes, i); + process->indent = 0; + process->tree_depth = 0; + process->tree_left = node_counter++; + process->tree_index = node_index++; + Vector_add(this->processes2, process); + Hashtable_put(this->displayTreeSet, process->tree_index, process); + ProcessList_buildTreeBranch(this, process->pid, 0, 0, direction, process->showChildren, &node_counter, &node_index); + process->tree_right = node_counter++; + break; + } + } + + // There should be no loop in the process tree + assert(i < size); + } + + // Swap listings around + Vector* t = this->processes; + this->processes = this->processes2; + this->processes2 = t; + + // Check consistency of the built structures + assert(Vector_size(this->processes) == vsize); (void)vsize; + assert(Vector_size(this->processes2) == 0); +} + +void ProcessList_sort(ProcessList* this) { + if (this->settings->treeView) { + ProcessList_updateTreeSet(this); + Vector_quickSortCustomCompare(this->processes, ProcessList_treeProcessCompare); + } else { + Vector_insertionSort(this->processes); + } +} + +ProcessField ProcessList_keyAt(const ProcessList* this, int at) { + int x = 0; + const ProcessField* fields = this->settings->fields; + ProcessField field; + for (int i = 0; (field = fields[i]); i++) { + int len = strlen(alignedProcessFieldTitle(field)); + if (at >= x && at <= x + len) { + return field; + } + x += len; + } + return COMM; +} + +void ProcessList_expandTree(ProcessList* this) { + int size = Vector_size(this->processes); + for (int i = 0; i < size; i++) { + Process* process = (Process*) Vector_get(this->processes, i); + process->showChildren = true; + } +} + +void ProcessList_collapseAllBranches(ProcessList* this) { + int size = Vector_size(this->processes); + for (int i = 0; i < size; i++) { + Process* process = (Process*) Vector_get(this->processes, i); + // FreeBSD has pid 0 = kernel and pid 1 = init, so init has tree_depth = 1 + if (process->tree_depth > 0 && process->pid > 1) + process->showChildren = false; + } +} + +void ProcessList_rebuildPanel(ProcessList* this) { + const char* incFilter = this->incFilter; + + const int currPos = Panel_getSelectedIndex(this->panel); + const int currScrollV = this->panel->scrollV; + const int currSize = Panel_size(this->panel); + + Panel_prune(this->panel); + + /* Follow main process if followed a userland thread and threads are now hidden */ + const Settings* settings = this->settings; + if (this->following != -1 && settings->hideUserlandThreads) { + const Process* followedProcess = (const Process*) Hashtable_get(this->processTable, this->following); + if (followedProcess && Process_isThread(followedProcess) && Hashtable_get(this->processTable, followedProcess->tgid) != NULL) { + this->following = followedProcess->tgid; + } + } + + const int processCount = Vector_size(this->processes); + int idx = 0; + bool foundFollowed = false; + + for (int i = 0; i < processCount; i++) { + Process* p = (Process*) Vector_get(this->processes, i); + + if ( (!p->show) + || (this->userId != (uid_t) -1 && (p->st_uid != this->userId)) + || (incFilter && !(String_contains_i(Process_getCommand(p), incFilter))) + || (this->pidMatchList && !Hashtable_get(this->pidMatchList, p->tgid)) ) + continue; + + Panel_set(this->panel, idx, (Object*)p); + + if (this->following != -1 && p->pid == this->following) { + foundFollowed = true; + Panel_setSelected(this->panel, idx); + this->panel->scrollV = currScrollV; + } + idx++; + } + + if (this->following != -1 && !foundFollowed) { + /* Reset if current followed pid not found */ + this->following = -1; + Panel_setSelectionColor(this->panel, PANEL_SELECTION_FOCUS); + } + + if (this->following == -1) { + /* If the last item was selected, keep the new last item selected */ + if (currPos > 0 && currPos == currSize - 1) + Panel_setSelected(this->panel, Panel_size(this->panel) - 1); + else + Panel_setSelected(this->panel, currPos); + + this->panel->scrollV = currScrollV; + } +} + +Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_New constructor) { + Process* proc = (Process*) Hashtable_get(this->processTable, pid); + *preExisting = proc != NULL; + if (proc) { + assert(Vector_indexOf(this->processes, proc, Process_pidCompare) != -1); + assert(proc->pid == pid); + } else { + proc = constructor(this->settings); + assert(proc->cmdline == NULL); + proc->pid = pid; + } + return proc; +} + +void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) { + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + ProcessList_goThroughEntries(this, true); + return; + } + + // mark all process as "dirty" + for (int i = 0; i < Vector_size(this->processes); i++) { + Process* p = (Process*) Vector_get(this->processes, i); + p->updated = false; + p->wasShown = p->show; + p->show = true; + } + + this->totalTasks = 0; + this->userlandThreads = 0; + this->kernelThreads = 0; + this->runningTasks = 0; + + + // set scan timestamp + static bool firstScanDone = false; + if (firstScanDone) { + Platform_gettime_monotonic(&this->monotonicMs); + } else { + this->monotonicMs = 0; + firstScanDone = true; + } + + ProcessList_goThroughEntries(this, false); + + for (int i = Vector_size(this->processes) - 1; i >= 0; i--) { + Process* p = (Process*) Vector_get(this->processes, i); + Process_makeCommandStr(p); + + if (p->tombStampMs > 0) { + // remove tombed process + if (this->monotonicMs >= p->tombStampMs) { + ProcessList_remove(this, p); + } + } else if (p->updated == false) { + // process no longer exists + if (this->settings->highlightChanges && p->wasShown) { + // mark tombed + p->tombStampMs = this->monotonicMs + 1000 * this->settings->highlightDelaySecs; + } else { + // immediately remove + ProcessList_remove(this, p); + } + } + } + + if (this->settings->treeView) { + // Clear out the hashtable to avoid any left-over processes from previous build + // + // The sorting algorithm relies on the fact that + // len(this->displayTreeSet) == len(this->processes) + Hashtable_clear(this->displayTreeSet); + + ProcessList_buildTree(this); + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessList.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,124 @@ +#ifndef HEADER_ProcessList +#define HEADER_ProcessList +/* +htop - ProcessList.h +(C) 2004,2005 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include +#include +#include + +#include "Hashtable.h" +#include "Object.h" +#include "Panel.h" +#include "Process.h" +#include "RichString.h" +#include "Settings.h" +#include "UsersTable.h" +#include "Vector.h" + +#ifdef HAVE_LIBHWLOC +#include +#endif + + +#ifndef MAX_NAME +#define MAX_NAME 128 +#endif + +#ifndef MAX_READ +#define MAX_READ 2048 +#endif + +typedef unsigned long long int memory_t; +#define MEMORY_MAX ULLONG_MAX + +typedef struct ProcessList_ { + const Settings* settings; + + Vector* processes; + Vector* processes2; + Hashtable* processTable; + UsersTable* usersTable; + + Hashtable* displayTreeSet; + Hashtable* draftingTreeSet; + + Hashtable* dynamicMeters; /* runtime-discovered meters */ + + struct timeval realtime; /* time of the current sample */ + uint64_t realtimeMs; /* current time in milliseconds */ + uint64_t monotonicMs; /* same, but from monotonic clock */ + + Panel* panel; + int following; + uid_t userId; + const char* incFilter; + Hashtable* pidMatchList; + + #ifdef HAVE_LIBHWLOC + hwloc_topology_t topology; + bool topologyOk; + #endif + + unsigned int totalTasks; + unsigned int runningTasks; + unsigned int userlandThreads; + unsigned int kernelThreads; + + memory_t totalMem; + memory_t usedMem; + memory_t buffersMem; + memory_t cachedMem; + memory_t sharedMem; + memory_t availableMem; + + memory_t totalSwap; + memory_t usedSwap; + memory_t cachedSwap; + + unsigned int cpuCount; +} ProcessList; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); +void ProcessList_delete(ProcessList* pl); +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + + +ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_done(ProcessList* this); + +void ProcessList_setPanel(ProcessList* this, Panel* panel); + +void ProcessList_printHeader(const ProcessList* this, RichString* header); + +void ProcessList_add(ProcessList* this, Process* p); + +void ProcessList_remove(ProcessList* this, const Process* p); + +void ProcessList_sort(ProcessList* this); + +ProcessField ProcessList_keyAt(const ProcessList* this, int at); + +void ProcessList_expandTree(ProcessList* this); + +void ProcessList_collapseAllBranches(ProcessList* this); + +void ProcessList_rebuildPanel(ProcessList* this); + +Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_New constructor); + +void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate); + +static inline Process* ProcessList_findProcess(ProcessList* this, pid_t pid) { + return (Process*) Hashtable_get(this->processTable, pid); +} + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessLocksScreen.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessLocksScreen.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessLocksScreen.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessLocksScreen.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,105 @@ +/* +htop - ProcessLocksScreen.c +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "ProcessLocksScreen.h" + +#include +#include +#include + +#include "Panel.h" +#include "Platform.h" +#include "ProvideCurses.h" +#include "Vector.h" +#include "XUtils.h" + + +ProcessLocksScreen* ProcessLocksScreen_new(const Process* process) { + ProcessLocksScreen* this = xMalloc(sizeof(ProcessLocksScreen)); + Object_setClass(this, Class(ProcessLocksScreen)); + if (Process_isThread(process)) + this->pid = process->tgid; + else + this->pid = process->pid; + return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME"); +} + +void ProcessLocksScreen_delete(Object* this) { + free(InfoScreen_done((InfoScreen*)this)); +} + +static void ProcessLocksScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Snapshot of file locks of process %d - %s", ((ProcessLocksScreen*)this)->pid, Process_getCommand(this->process)); +} + +static inline void FileLocks_Data_clear(FileLocks_Data* data) { + free(data->locktype); + free(data->exclusive); + free(data->readwrite); + free(data->filename); +} + +static void ProcessLocksScreen_scan(InfoScreen* this) { + Panel* panel = this->display; + int idx = Panel_getSelectedIndex(panel); + Panel_prune(panel); + FileLocks_ProcessData* pdata = Platform_getProcessLocks(((ProcessLocksScreen*)this)->pid); + if (!pdata) { + InfoScreen_addLine(this, "This feature is not supported on your platform."); + } else if (pdata->error) { + InfoScreen_addLine(this, "Could not determine file locks."); + } else { + FileLocks_LockData* ldata = pdata->locks; + if (!ldata) { + InfoScreen_addLine(this, "No locks have been found for the selected process."); + } + while (ldata) { + FileLocks_Data* data = &ldata->data; + + char entry[512]; + if (ULLONG_MAX == data->end) { + xSnprintf(entry, sizeof(entry), "%10d %-10s %-10s %-10s %02x:%02x:%020"PRIu64" %20"PRIu64" %20s %s", + data->id, + data->locktype, data->exclusive, data->readwrite, + data->dev[0], data->dev[1], data->inode, + data->start, "", + data->filename ? data->filename : "" + ); + } else { + xSnprintf(entry, sizeof(entry), "%10d %-10s %-10s %-10s %02x:%02x:%020"PRIu64" %20"PRIu64" %20"PRIu64" %s", + data->id, + data->locktype, data->exclusive, data->readwrite, + data->dev[0], data->dev[1], data->inode, + data->start, data->end, + data->filename ? data->filename : "" + ); + } + + InfoScreen_addLine(this, entry); + FileLocks_Data_clear(&ldata->data); + + FileLocks_LockData* old = ldata; + ldata = ldata->next; + free(old); + } + } + free(pdata); + Vector_insertionSort(this->lines); + Vector_insertionSort(panel->items); + Panel_setSelected(panel, idx); +} + +const InfoScreenClass ProcessLocksScreen_class = { + .super = { + .extends = Class(Object), + .delete = ProcessLocksScreen_delete + }, + .scan = ProcessLocksScreen_scan, + .draw = ProcessLocksScreen_draw +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessLocksScreen.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessLocksScreen.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ProcessLocksScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ProcessLocksScreen.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,52 @@ +#ifndef HEADER_ProcessLocksScreen +#define HEADER_ProcessLocksScreen +/* +htop - ProcessLocksScreen.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +#include "InfoScreen.h" +#include "Object.h" +#include "Process.h" + + +typedef struct ProcessLocksScreen_ { + InfoScreen super; + pid_t pid; +} ProcessLocksScreen; + +typedef struct FileLocks_Data_ { + char* locktype; + char* exclusive; + char* readwrite; + char* filename; + int id; + unsigned int dev[2]; + uint64_t inode; + uint64_t start; + uint64_t end; +} FileLocks_Data; + +typedef struct FileLocks_LockData_ { + FileLocks_Data data; + struct FileLocks_LockData_* next; +} FileLocks_LockData; + +typedef struct FileLocks_ProcessData_ { + bool error; + struct FileLocks_LockData_* locks; +} FileLocks_ProcessData; + +extern const InfoScreenClass ProcessLocksScreen_class; + +ProcessLocksScreen* ProcessLocksScreen_new(const Process* process); + +void ProcessLocksScreen_delete(Object* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ProvideCurses.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ProvideCurses.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ProvideCurses.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ProvideCurses.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,34 @@ +#ifndef HEADER_ProvideCurses +#define HEADER_ProvideCurses +/* +htop - RichString.h +(C) 2004,2011 Hisham H. Muhammad +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + + +#include "config.h" + +// IWYU pragma: begin_exports + +#if defined(HAVE_NCURSESW_CURSES_H) +#include +#elif defined(HAVE_NCURSES_NCURSES_H) +#include +#elif defined(HAVE_NCURSES_CURSES_H) +#include +#elif defined(HAVE_NCURSES_H) +#include +#elif defined(HAVE_CURSES_H) +#include +#endif + +#ifdef HAVE_LIBNCURSESW +#include +#include +#endif + +// IWYU pragma: end_exports + +#endif // HEADER_ProvideCurses diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/README pcp-5.3.2/vendor/github.com/htop-dev/htop/README --- pcp-5.3.1/vendor/github.com/htop-dev/htop/README 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/README 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,167 @@ +# [![htop](htop.png)](https://htop.dev) + +[![CI](https://github.com/htop-dev/htop/workflows/CI/badge.svg)](https://github.com/htop-dev/htop/actions) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/21665/badge.svg)](https://scan.coverity.com/projects/21665) +[![Mailing List](https://img.shields.io/badge/Mailing%20List-htop-blue.svg)](https://groups.io/g/htop) +[![IRC #htop](https://img.shields.io/badge/IRC-htop-blue.svg)](https://web.libera.chat/#htop) +[![Github Release](https://img.shields.io/github/release/htop-dev/htop.svg)](https://github.com/htop-dev/htop/releases/latest) + +![Screenshot of htop](docs/images/screenshot.png?raw=true) + +## Introduction + +`htop` is a cross-platform interactive process viewer. + +`htop` allows scrolling the list of processes vertically and horizontally to see their full command lines and related information like memory and CPU consumption. + +The information displayed is configurable through a graphical setup and can be sorted and filtered interactively. + +Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs. + +Running `htop` requires `ncurses` libraries (typically named libncursesw*). + +For more information and details on how to contribute to `htop` visit [htop.dev](https://htop.dev). + +## Build instructions + +### Prerequisite +List of build-time dependencies: +* `build-essential` standard GNU autotools-based +* `autoconf` +* `autotools` +* `ncurses` + +**Note about `ncurses`:** +> htop requires ncurses 6.0. Be aware the appropriate package is sometimes still called libncurses5 (on Debian/Ubuntu). Also ncurses usually comes in two flavours: +>* With Unicode support. +>* Without Unicode support. +> +> This is also something that is reflected in the package name on Debian/Ubuntu (via the additional 'w' - 'w'ide character support). + +List of additional build-time dependencies (based on feature flags): +* `sensors` +* `hwloc` +* `libcap` + +Compiling `htop` requires the header files for `ncurses` . Install these and other required packages for C development from your package manager. + +**Debian/Ubuntu** +~~~ shell +sudo apt install libncursesw5-dev autotools-dev autoconf +~~~ + +**Fedora/RHEL** +~~~ shell +sudo dnf install ncurses-devel automake autoconf +~~~ + +### Compiling from source: +To compile from sources downloaded from the Git repository (`git clone` or downloads from [Github releases](https://github.com/htop-dev/htop/releases/)), then run: +~~~ shell +./autogen.sh && ./configure && make +~~~ + +By default `make install` will install into `/usr/local`, for changing the path use `./configure --prefix=/some/path`. + +### Install +To install on the local system run `make install`. By default `make install` installs into `/usr/local`. To change this path use `./configure --prefix=/some/path`. + +### Build Options + +`htop` has several build-time options to enable/disable additional features. + +#### Generic + + * `--enable-unicode`: + enable Unicode support + dependency: *libncursesw* + default: *yes* + * `--enable-pcp`: + enable Performance Co-Pilot support via a new pcp-htop utility + dependency: *libpcp* + default: *no* + * `--enable-hwloc`: + enable hwloc support for CPU affinity; disables Linux affinity + dependency: *libhwloc* + default: *no* + * `--enable-static`: + build a static htop binary; hwloc and delay accounting are not supported + default: *no* + * `--enable-debug`: + Enable asserts and internal sanity checks; implies a performance penalty + default: *no* + +#### Linux + + * `--enable-sensors`: + enable libsensors(3) support for reading temperature data + dependencies: *libsensors-dev*(build-time), at runtime *libsensors* is loaded via `dlopen(3)` if available + default: *check* + * `--enable-capabilities`: + enable Linux capabilities support + dependency: *libcap* + default: *check* + * `--with-proc`: + location of a Linux-compatible proc filesystem + default: */proc* + * `--enable-openvz`: + enable OpenVZ support + default: *no* + * `--enable-vserver`: + enable VServer support + default: *no* + * `--enable-ancient-vserver`: + enable ancient VServer support (implies `--enable-vserver`) + default: *no* + * `--enable-linux-affinity`: + enable Linux `sched_setaffinity(2)` and `sched_getaffinity(2)` for affinity support; conflicts with hwloc + default: *check* + * `--enable-delayacct`: + enable Linux delay accounting support + dependencies: *pkg-config*(build-time), *libnl-3* and *libnl-genl-3* + default: *check* + + +## Runtime dependencies: +`htop` has a set of fixed minimum runtime dependencies, which is kept as minimal as possible: +* `ncurses` libraries for terminal handling (wide character support). + +### Runtime optional dependencies: +`htop` has a set of fixed optional dependencies, depending on build/configure option used: +* `libdl`, if not building static and support for some of the optional libraries is enabled, is always required when support for to optionally load dependencies (i.e. `libsensors`, `systemd`) is present. +* `libcap`, user-space interfaces to the POSIX 1003.1e, is always required when `--enable-capabilities` was used to configure `htop`. +* `libsensors`, readout of temperatures and CPU speeds, is optional even when `--enable-sensors` was used to configure `htop`. +* `systemd` is optional when `--enable-static` was not used to configure `htop` (Linux only). If building statically and `libsystemd` is not found by `configure` support for the SystemD meter is disabled entirely. + +`htop` checks for the availability of the actual runtime lib as `htop` runs. + +**BSD** +On most *BSD systems you also have `kvm` as a static requirement to read all the kernel information. + +More information on required and optional dependencies can be found in [configure.ac](configure.ac). + +## Usage +See the manual page (`man htop`) or the on-line help ('F1' or 'h' inside `htop`) for a list of supported key commands. + +## Support + +If you have trouble running `htop` please consult your Operating System / Linux distribution documentation for getting support and filing bugs. + +## Bugs, development feedback + +We have a [development mailing list](https://htop.dev/mailinglist.html). Feel free to subscribe for release announcements or asking questions on the development of htop. + +You can also join our IRC channel #htop on Libera.Chat and talk to the developers there. + +If you have found an issue with the source of htop, please check whether this has already been reported in our [Github issue tracker](https://github.com/htop-dev/htop/issues). +If not, please file a new issue describing the problem you have found, the location in the source code you are referring to and a possible fix. + +## History + +`htop` was invented, developed and maintained by Hisham Muhammad from 2004 to 2019. His [legacy repository](https://github.com/hishamhm/htop/) has been archived to preserve the history. + +In 2020 a [team](https://github.com/orgs/htop-dev/people) took over the development amicably and continues to maintain `htop` collaboratively. + +## License + +GNU General Public License, version 2 (GPL-2.0) diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/RichString.c pcp-5.3.2/vendor/github.com/htop-dev/htop/RichString.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/RichString.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/RichString.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,222 @@ +/* +htop - RichString.c +(C) 2004,2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "RichString.h" + +#include +#include +#include +#include + +#include "Macros.h" +#include "XUtils.h" + + +#define charBytes(n) (sizeof(CharType) * (n)) + +static void RichString_extendLen(RichString* this, int len) { + if (this->chlen <= RICHSTRING_MAXLEN) { + if (len > RICHSTRING_MAXLEN) { + this->chptr = xMalloc(charBytes(len + 1)); + memcpy(this->chptr, this->chstr, charBytes(this->chlen)); + } + } else { + if (len <= RICHSTRING_MAXLEN) { + memcpy(this->chstr, this->chptr, charBytes(len)); + free(this->chptr); + this->chptr = this->chstr; + } else { + this->chptr = xRealloc(this->chptr, charBytes(len + 1)); + } + } + + RichString_setChar(this, len, 0); + this->chlen = len; +} + +static void RichString_setLen(RichString* this, int len) { + if (len < RICHSTRING_MAXLEN && this->chlen < RICHSTRING_MAXLEN) { + RichString_setChar(this, len, 0); + this->chlen = len; + } else { + RichString_extendLen(this, len); + } +} + +void RichString_rewind(RichString* this, int count) { + RichString_setLen(this, this->chlen - count); +} + +#ifdef HAVE_LIBNCURSESW + +static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) { + wchar_t data[len + 1]; + len = mbstowcs(data, data_c, len); + if (len <= 0) + return 0; + + int newLen = from + len; + RichString_setLen(this, newLen); + for (int i = from, j = 0; i < newLen; i++, j++) { + this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (iswprint(data[j]) ? data[j] : '?') } }; + } + + return len; +} + +int RichString_appendnWideColumns(RichString* this, int attrs, const char* data_c, int len, int* columns) { + wchar_t data[len + 1]; + len = mbstowcs(data, data_c, len); + if (len <= 0) + return 0; + + int from = this->chlen; + int newLen = from + len; + RichString_setLen(this, newLen); + int columnsWritten = 0; + int pos = from; + for (int j = 0; j < len; j++) { + wchar_t c = iswprint(data[j]) ? data[j] : '?'; + int cwidth = wcwidth(c); + if (cwidth > *columns) + break; + + *columns -= cwidth; + columnsWritten += cwidth; + + this->chptr[pos] = (CharType) { .attr = attrs & 0xffffff, .chars = { c, '\0' } }; + pos++; + } + + RichString_setLen(this, pos); + *columns = columnsWritten; + + return pos - from; +} + +static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data, int from, int len) { + int newLen = from + len; + RichString_setLen(this, newLen); + for (int i = from, j = 0; i < newLen; i++, j++) { + this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (isprint(data[j]) ? data[j] : '?') } }; + } + + return len; +} + +inline void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) { + int end = CLAMP(start + charcount, 0, this->chlen); + for (int i = start; i < end; i++) { + this->chptr[i].attr = attrs; + } +} + +void RichString_appendChr(RichString* this, int attrs, char c, int count) { + int from = this->chlen; + int newLen = from + count; + RichString_setLen(this, newLen); + for (int i = from; i < newLen; i++) { + this->chptr[i] = (CharType) { .attr = attrs, .chars = { c, 0 } }; + } +} + +int RichString_findChar(const RichString* this, char c, int start) { + const wchar_t wc = btowc(c); + const cchar_t* ch = this->chptr + start; + for (int i = start; i < this->chlen; i++) { + if (ch->chars[0] == wc) + return i; + ch++; + } + return -1; +} + +#else /* HAVE_LIBNCURSESW */ + +static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) { + int newLen = from + len; + RichString_setLen(this, newLen); + for (int i = from, j = 0; i < newLen; i++, j++) { + this->chptr[i] = (((unsigned char)data_c[j]) >= 32 ? ((unsigned char)data_c[j]) : '?') | attrs; + } + this->chptr[newLen] = 0; + + return len; +} + +int RichString_appendnWideColumns(RichString* this, int attrs, const char* data_c, int len, int* columns) { + int written = RichString_writeFromWide(this, attrs, data_c, this->chlen, MINIMUM(len, *columns)); + *columns = written; + return written; +} + +static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data_c, int from, int len) { + return RichString_writeFromWide(this, attrs, data_c, from, len); +} + +void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) { + int end = CLAMP(start + charcount, 0, this->chlen); + for (int i = start; i < end; i++) { + this->chptr[i] = (this->chptr[i] & 0xff) | attrs; + } +} + +void RichString_appendChr(RichString* this, int attrs, char c, int count) { + int from = this->chlen; + int newLen = from + count; + RichString_setLen(this, newLen); + for (int i = from; i < newLen; i++) { + this->chptr[i] = c | attrs; + } +} + +int RichString_findChar(const RichString* this, char c, int start) { + const chtype* ch = this->chptr + start; + for (int i = start; i < this->chlen; i++) { + if ((*ch & 0xff) == (chtype) c) + return i; + ch++; + } + return -1; +} + +#endif /* HAVE_LIBNCURSESW */ + +void RichString_delete(RichString* this) { + if (this->chlen > RICHSTRING_MAXLEN) { + free(this->chptr); + this->chptr = this->chstr; + } +} + +void RichString_setAttr(RichString* this, int attrs) { + RichString_setAttrn(this, attrs, 0, this->chlen); +} + +int RichString_appendWide(RichString* this, int attrs, const char* data) { + return RichString_writeFromWide(this, attrs, data, this->chlen, strlen(data)); +} + +int RichString_appendnWide(RichString* this, int attrs, const char* data, int len) { + return RichString_writeFromWide(this, attrs, data, this->chlen, len); +} + +int RichString_writeWide(RichString* this, int attrs, const char* data) { + return RichString_writeFromWide(this, attrs, data, 0, strlen(data)); +} + +int RichString_appendAscii(RichString* this, int attrs, const char* data) { + return RichString_writeFromAscii(this, attrs, data, this->chlen, strlen(data)); +} + +int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len) { + return RichString_writeFromAscii(this, attrs, data, this->chlen, len); +} + +int RichString_writeAscii(RichString* this, int attrs, const char* data) { + return RichString_writeFromAscii(this, attrs, data, 0, strlen(data)); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/RichString.h pcp-5.3.2/vendor/github.com/htop-dev/htop/RichString.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/RichString.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/RichString.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,79 @@ +#ifndef HEADER_RichString +#define HEADER_RichString +/* +htop - RichString.h +(C) 2004,2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" + +#include "ProvideCurses.h" + + +#define RichString_size(this) ((this)->chlen) +#define RichString_sizeVal(this) ((this).chlen) + +#define RichString_begin(this) RichString this; RichString_beginAllocated(this) +#define RichString_beginAllocated(this) \ + do { \ + (this).chlen = 0, \ + (this).chptr = (this).chstr; \ + RichString_setChar(&(this), 0, 0); \ + (this).highlightAttr = 0; \ + } while(0) + +#ifdef HAVE_LIBNCURSESW +#define RichString_printVal(this, y, x) mvadd_wchstr(y, x, (this).chptr) +#define RichString_printoffnVal(this, y, x, off, n) mvadd_wchnstr(y, x, (this).chptr + (off), n) +#define RichString_getCharVal(this, i) ((this).chptr[i].chars[0]) +#define RichString_setChar(this, at, ch) do { (this)->chptr[(at)] = (CharType) { .chars = { ch, 0 } }; } while (0) +#define CharType cchar_t +#else +#define RichString_printVal(this, y, x) mvaddchstr(y, x, (this).chptr) +#define RichString_printoffnVal(this, y, x, off, n) mvaddchnstr(y, x, (this).chptr + (off), n) +#define RichString_getCharVal(this, i) ((this).chptr[i] & 0xff) +#define RichString_setChar(this, at, ch) do { (this)->chptr[(at)] = ch; } while (0) +#define CharType chtype +#endif + +#define RICHSTRING_MAXLEN 350 + +typedef struct RichString_ { + int chlen; + CharType* chptr; + CharType chstr[RICHSTRING_MAXLEN + 1]; + int highlightAttr; +} RichString; + +void RichString_delete(RichString* this); + +void RichString_rewind(RichString* this, int count); + +void RichString_setAttrn(RichString* this, int attrs, int start, int charcount); + +int RichString_findChar(const RichString* this, char c, int start); + +void RichString_setAttr(RichString* this, int attrs); + +void RichString_appendChr(RichString* this, int attrs, char c, int count); + +/* All appending and writing functions return the number of written characters (not columns). */ + +int RichString_appendWide(RichString* this, int attrs, const char* data); + +int RichString_appendnWide(RichString* this, int attrs, const char* data, int len); + +/* columns takes the maximum number of columns to write and contains on return the number of columns written. */ +int RichString_appendnWideColumns(RichString* this, int attrs, const char* data, int len, int* columns); + +int RichString_writeWide(RichString* this, int attrs, const char* data); + +int RichString_appendAscii(RichString* this, int attrs, const char* data); + +int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len); + +int RichString_writeAscii(RichString* this, int attrs, const char* data); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ScreenManager.c pcp-5.3.2/vendor/github.com/htop-dev/htop/ScreenManager.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ScreenManager.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ScreenManager.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,329 @@ +/* +htop - ScreenManager.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "ScreenManager.h" + +#include +#include +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +ScreenManager* ScreenManager_new(Header* header, const Settings* settings, const State* state, bool owner) { + ScreenManager* this; + this = xMalloc(sizeof(ScreenManager)); + this->x1 = 0; + this->y1 = header->height; + this->x2 = 0; + this->y2 = -1; + this->panels = Vector_new(Class(Panel), owner, DEFAULT_SIZE); + this->panelCount = 0; + this->header = header; + this->settings = settings; + this->state = state; + this->owner = owner; + this->allowFocusChange = true; + return this; +} + +void ScreenManager_delete(ScreenManager* this) { + Vector_delete(this->panels); + free(this); +} + +inline int ScreenManager_size(const ScreenManager* this) { + return this->panelCount; +} + +void ScreenManager_add(ScreenManager* this, Panel* item, int size) { + int lastX = 0; + if (this->panelCount > 0) { + const Panel* last = (const Panel*) Vector_get(this->panels, this->panelCount - 1); + lastX = last->x + last->w + 1; + } + int height = LINES - this->y1 + this->y2; + if (size > 0) { + Panel_resize(item, size, height); + } else { + Panel_resize(item, COLS - this->x1 + this->x2 - lastX, height); + } + Panel_move(item, lastX, this->y1); + Vector_add(this->panels, item); + item->needsRedraw = true; + this->panelCount++; +} + +Panel* ScreenManager_remove(ScreenManager* this, int idx) { + assert(this->panelCount > idx); + Panel* panel = (Panel*) Vector_remove(this->panels, idx); + this->panelCount--; + return panel; +} + +void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) { + this->x1 = x1; + this->y1 = y1; + this->x2 = x2; + this->y2 = y2; + int panels = this->panelCount; + int lastX = 0; + for (int i = 0; i < panels - 1; i++) { + Panel* panel = (Panel*) Vector_get(this->panels, i); + Panel_resize(panel, panel->w, LINES - y1 + y2); + Panel_move(panel, lastX, y1); + lastX = panel->x + panel->w + 1; + } + Panel* panel = (Panel*) Vector_get(this->panels, panels - 1); + Panel_resize(panel, COLS - x1 + x2 - lastX, LINES - y1 + y2); + Panel_move(panel, lastX, y1); +} + +static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool* rescan, bool* timedOut) { + ProcessList* pl = this->header->pl; + + Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs); + double newTime = ((double)pl->realtime.tv_sec * 10) + ((double)pl->realtime.tv_usec / 100000); + + *timedOut = (newTime - *oldTime > this->settings->delay); + *rescan |= *timedOut; + + if (newTime < *oldTime) { + *rescan = true; // clock was adjusted? + } + + if (*rescan) { + *oldTime = newTime; + // scan processes first - some header values are calculated there + ProcessList_scan(pl, this->state->pauseProcessUpdate); + // always update header, especially to avoid gaps in graph meters + Header_updateData(this->header); + if (!this->state->pauseProcessUpdate && (*sortTimeout == 0 || this->settings->treeView)) { + ProcessList_sort(pl); + *sortTimeout = 1; + } + *redraw = true; + } + if (*redraw) { + ProcessList_rebuildPanel(pl); + Header_draw(this->header); + } + *rescan = false; +} + +static void ScreenManager_drawPanels(ScreenManager* this, int focus, bool force_redraw) { + const int nPanels = this->panelCount; + for (int i = 0; i < nPanels; i++) { + Panel* panel = (Panel*) Vector_get(this->panels, i); + Panel_draw(panel, + force_redraw, + i == focus, + panel != (Panel*)this->state->mainPanel || !this->state->hideProcessSelection, + State_hideFunctionBar(this->state)); + mvvline(panel->y, panel->x + panel->w, ' ', panel->h + (State_hideFunctionBar(this->state) ? 1 : 0)); + } +} + +void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) { + bool quit = false; + int focus = 0; + + Panel* panelFocus = (Panel*) Vector_get(this->panels, focus); + + double oldTime = 0.0; + + int ch = ERR; + int closeTimeout = 0; + + bool timedOut = true; + bool redraw = true; + bool force_redraw = true; + bool rescan = false; + int sortTimeout = 0; + int resetSortTimeout = 5; + + while (!quit) { + if (this->header) { + checkRecalculation(this, &oldTime, &sortTimeout, &redraw, &rescan, &timedOut); + } + + if (redraw || force_redraw) { + ScreenManager_drawPanels(this, focus, force_redraw); + force_redraw = false; + } + + int prevCh = ch; +#ifdef HAVE_SET_ESCDELAY + set_escdelay(25); +#endif + ch = getch(); + + HandlerResult result = IGNORED; +#ifdef HAVE_GETMOUSE + if (ch == KEY_MOUSE && this->settings->enableMouse) { + ch = ERR; + MEVENT mevent; + int ok = getmouse(&mevent); + if (ok == OK) { + if (mevent.bstate & BUTTON1_RELEASED) { + if (mevent.y == LINES - 1) { + ch = FunctionBar_synthesizeEvent(panelFocus->currentBar, mevent.x); + } else { + for (int i = 0; i < this->panelCount; i++) { + Panel* panel = (Panel*) Vector_get(this->panels, i); + if (mevent.x >= panel->x && mevent.x <= panel->x + panel->w) { + if (mevent.y == panel->y) { + ch = EVENT_HEADER_CLICK(mevent.x - panel->x); + break; + } else if (mevent.y > panel->y && mevent.y <= panel->y + panel->h) { + ch = KEY_MOUSE; + if (panel == panelFocus || this->allowFocusChange) { + focus = i; + panelFocus = panel; + const Object* oldSelection = Panel_getSelected(panel); + Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1); + if (Panel_getSelected(panel) == oldSelection) { + ch = KEY_RECLICK; + } + } + break; + } + } + } + } + #if NCURSES_MOUSE_VERSION > 1 + } else if (mevent.bstate & BUTTON4_PRESSED) { + ch = KEY_WHEELUP; + } else if (mevent.bstate & BUTTON5_PRESSED) { + ch = KEY_WHEELDOWN; + #endif + } + } + } +#endif + if (ch == ERR) { + if (sortTimeout > 0) + sortTimeout--; + if (prevCh == ch && !timedOut) { + closeTimeout++; + if (closeTimeout == 100) { + break; + } + } else { + closeTimeout = 0; + } + redraw = false; + continue; + } + switch (ch) { + case KEY_ALT('H'): ch = KEY_LEFT; break; + case KEY_ALT('J'): ch = KEY_DOWN; break; + case KEY_ALT('K'): ch = KEY_UP; break; + case KEY_ALT('L'): ch = KEY_RIGHT; break; + } + redraw = true; + if (Panel_eventHandlerFn(panelFocus)) { + result = Panel_eventHandler(panelFocus, ch); + } + if (result & SYNTH_KEY) { + ch = result >> 16; + } + if (result & REFRESH) { + sortTimeout = 0; + } + if (result & REDRAW) { + force_redraw = true; + } + if (result & RESCAN) { + rescan = true; + sortTimeout = 0; + } + if (result & HANDLED) { + continue; + } else if (result & BREAK_LOOP) { + quit = true; + continue; + } + + switch (ch) { + case KEY_RESIZE: + { + ScreenManager_resize(this, this->x1, this->y1, this->x2, this->y2); + continue; + } + case KEY_LEFT: + case KEY_CTRL('B'): + if (this->panelCount < 2) { + goto defaultHandler; + } + + if (!this->allowFocusChange) { + break; + } + +tryLeft: + if (focus > 0) { + focus--; + } + + panelFocus = (Panel*) Vector_get(this->panels, focus); + if (Panel_size(panelFocus) == 0 && focus > 0) { + goto tryLeft; + } + + break; + case KEY_RIGHT: + case KEY_CTRL('F'): + case 9: + if (this->panelCount < 2) { + goto defaultHandler; + } + if (!this->allowFocusChange) { + break; + } + +tryRight: + if (focus < this->panelCount - 1) { + focus++; + } + + panelFocus = (Panel*) Vector_get(this->panels, focus); + if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1) { + goto tryRight; + } + + break; + case 27: + case 'q': + case KEY_F(10): + quit = true; + continue; + default: +defaultHandler: + sortTimeout = resetSortTimeout; + Panel_onKey(panelFocus, ch); + break; + } + } + + if (lastFocus) { + *lastFocus = panelFocus; + } + + if (lastKey) { + *lastKey = ch; + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/ScreenManager.h pcp-5.3.2/vendor/github.com/htop-dev/htop/ScreenManager.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/ScreenManager.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/ScreenManager.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,47 @@ +#ifndef HEADER_ScreenManager +#define HEADER_ScreenManager +/* +htop - ScreenManager.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include + +#include "Action.h" +#include "Header.h" +#include "Panel.h" +#include "Settings.h" +#include "Vector.h" + + +typedef struct ScreenManager_ { + int x1; + int y1; + int x2; + int y2; + Vector* panels; + int panelCount; + Header* header; + const Settings* settings; + const State* state; + bool owner; + bool allowFocusChange; +} ScreenManager; + +ScreenManager* ScreenManager_new(Header* header, const Settings* settings, const State* state, bool owner); + +void ScreenManager_delete(ScreenManager* this); + +int ScreenManager_size(const ScreenManager* this); + +void ScreenManager_add(ScreenManager* this, Panel* item, int size); + +Panel* ScreenManager_remove(ScreenManager* this, int idx); + +void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2); + +void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/scripts/htop_suppressions.valgrind pcp-5.3.2/vendor/github.com/htop-dev/htop/scripts/htop_suppressions.valgrind --- pcp-5.3.1/vendor/github.com/htop-dev/htop/scripts/htop_suppressions.valgrind 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/scripts/htop_suppressions.valgrind 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,63 @@ +{ + + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:CRT_init + fun:main +} + +{ + + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:CRT_init +} + +{ + + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:wgetch + fun:ScreenManager_run + fun:Action_runSetup + fun:actionSetup + fun:MainPanel_eventHandler + fun:ScreenManager_run + fun:main +} + +{ + + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:wgetch + fun:ScreenManager_run + fun:main +} + +{ + + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:wrefresh + fun:main +} + +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:realloc + fun:_nc_doalloc + fun:_nc_tparm_analyze + fun:tparm + ... + fun:doupdate_sp + fun:wrefresh + obj:* +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/scripts/run_valgrind.sh pcp-5.3.2/vendor/github.com/htop-dev/htop/scripts/run_valgrind.sh --- pcp-5.3.1/vendor/github.com/htop-dev/htop/scripts/run_valgrind.sh 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/scripts/run_valgrind.sh 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,6 @@ +#!/bin/sh + +SCRIPT=$(readlink -f "$0") +SCRIPTDIR=$(dirname "$SCRIPT") + +valgrind --leak-check=full --show-reachable=yes --show-leak-kinds=all --track-fds=yes --errors-for-leak-kinds=all --suppressions="${SCRIPTDIR}/htop_suppressions.valgrind" "${SCRIPTDIR}/../htop" diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Settings.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Settings.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Settings.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Settings.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,504 @@ +/* +htop - Settings.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Settings.h" + +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "Macros.h" +#include "Meter.h" +#include "Platform.h" +#include "XUtils.h" + + +void Settings_delete(Settings* this) { + free(this->filename); + free(this->fields); + for (unsigned int i = 0; i < ARRAYSIZE(this->columns); i++) { + String_freeArray(this->columns[i].names); + free(this->columns[i].modes); + } + free(this); +} + +static void Settings_readMeters(Settings* this, const char* line, int column) { + char* trim = String_trim(line); + char** ids = String_split(trim, ' ', NULL); + free(trim); + this->columns[column].names = ids; +} + +static void Settings_readMeterModes(Settings* this, const char* line, int column) { + char* trim = String_trim(line); + char** ids = String_split(trim, ' ', NULL); + free(trim); + int len = 0; + for (int i = 0; ids[i]; i++) { + len++; + } + this->columns[column].len = len; + int* modes = len ? xCalloc(len, sizeof(int)) : NULL; + for (int i = 0; i < len; i++) { + modes[i] = atoi(ids[i]); + } + String_freeArray(ids); + this->columns[column].modes = modes; +} + +static void Settings_defaultMeters(Settings* this, unsigned int initialCpuCount) { + int sizes[] = { 3, 3 }; + if (initialCpuCount > 4 && initialCpuCount <= 128) { + sizes[1]++; + } + for (int i = 0; i < 2; i++) { + this->columns[i].names = xCalloc(sizes[i] + 1, sizeof(char*)); + this->columns[i].modes = xCalloc(sizes[i], sizeof(int)); + this->columns[i].len = sizes[i]; + } + int r = 0; + + if (initialCpuCount > 128) { + // Just show the average, ricers need to config for impressive screenshots + this->columns[0].names[0] = xStrdup("CPU"); + this->columns[0].modes[0] = BAR_METERMODE; + } else if (initialCpuCount > 32) { + this->columns[0].names[0] = xStrdup("LeftCPUs8"); + this->columns[0].modes[0] = BAR_METERMODE; + this->columns[1].names[r] = xStrdup("RightCPUs8"); + this->columns[1].modes[r++] = BAR_METERMODE; + } else if (initialCpuCount > 16) { + this->columns[0].names[0] = xStrdup("LeftCPUs4"); + this->columns[0].modes[0] = BAR_METERMODE; + this->columns[1].names[r] = xStrdup("RightCPUs4"); + this->columns[1].modes[r++] = BAR_METERMODE; + } else if (initialCpuCount > 8) { + this->columns[0].names[0] = xStrdup("LeftCPUs2"); + this->columns[0].modes[0] = BAR_METERMODE; + this->columns[1].names[r] = xStrdup("RightCPUs2"); + this->columns[1].modes[r++] = BAR_METERMODE; + } else if (initialCpuCount > 4) { + this->columns[0].names[0] = xStrdup("LeftCPUs"); + this->columns[0].modes[0] = BAR_METERMODE; + this->columns[1].names[r] = xStrdup("RightCPUs"); + this->columns[1].modes[r++] = BAR_METERMODE; + } else { + this->columns[0].names[0] = xStrdup("AllCPUs"); + this->columns[0].modes[0] = BAR_METERMODE; + } + this->columns[0].names[1] = xStrdup("Memory"); + this->columns[0].modes[1] = BAR_METERMODE; + this->columns[0].names[2] = xStrdup("Swap"); + this->columns[0].modes[2] = BAR_METERMODE; + this->columns[1].names[r] = xStrdup("Tasks"); + this->columns[1].modes[r++] = TEXT_METERMODE; + this->columns[1].names[r] = xStrdup("LoadAverage"); + this->columns[1].modes[r++] = TEXT_METERMODE; + this->columns[1].names[r] = xStrdup("Uptime"); + this->columns[1].modes[r++] = TEXT_METERMODE; +} + +static void readFields(ProcessField* fields, uint32_t* flags, const char* line) { + char* trim = String_trim(line); + char** ids = String_split(trim, ' ', NULL); + free(trim); + int i, j; + *flags = 0; + for (j = 0, i = 0; i < LAST_PROCESSFIELD && ids[i]; i++) { + // This "+1" is for compatibility with the older enum format. + int id = atoi(ids[i]) + 1; + if (id > 0 && id < LAST_PROCESSFIELD && Process_fields[id].name) { + fields[j] = id; + *flags |= Process_fields[id].flags; + j++; + } + } + fields[j] = NULL_PROCESSFIELD; + String_freeArray(ids); +} + +static bool Settings_read(Settings* this, const char* fileName, unsigned int initialCpuCount) { + FILE* fd = fopen(fileName, "r"); + if (!fd) + return false; + + bool didReadMeters = false; + bool didReadFields = false; + for (;;) { + char* line = String_readLine(fd); + if (!line) { + break; + } + size_t nOptions; + char** option = String_split(line, '=', &nOptions); + free (line); + if (nOptions < 2) { + String_freeArray(option); + continue; + } + if (String_eq(option[0], "fields")) { + readFields(this->fields, &(this->flags), option[1]); + didReadFields = true; + } else if (String_eq(option[0], "sort_key")) { + // This "+1" is for compatibility with the older enum format. + this->sortKey = atoi(option[1]) + 1; + } else if (String_eq(option[0], "tree_sort_key")) { + // This "+1" is for compatibility with the older enum format. + this->treeSortKey = atoi(option[1]) + 1; + } else if (String_eq(option[0], "sort_direction")) { + this->direction = atoi(option[1]); + } else if (String_eq(option[0], "tree_sort_direction")) { + this->treeDirection = atoi(option[1]); + } else if (String_eq(option[0], "tree_view")) { + this->treeView = atoi(option[1]); + } else if (String_eq(option[0], "tree_view_always_by_pid")) { + this->treeViewAlwaysByPID = atoi(option[1]); + } else if (String_eq(option[0], "all_branches_collapsed")) { + this->allBranchesCollapsed = atoi(option[1]); + } else if (String_eq(option[0], "hide_kernel_threads")) { + this->hideKernelThreads = atoi(option[1]); + } else if (String_eq(option[0], "hide_userland_threads")) { + this->hideUserlandThreads = atoi(option[1]); + } else if (String_eq(option[0], "shadow_other_users")) { + this->shadowOtherUsers = atoi(option[1]); + } else if (String_eq(option[0], "show_thread_names")) { + this->showThreadNames = atoi(option[1]); + } else if (String_eq(option[0], "show_program_path")) { + this->showProgramPath = atoi(option[1]); + } else if (String_eq(option[0], "highlight_base_name")) { + this->highlightBaseName = atoi(option[1]); + } else if (String_eq(option[0], "highlight_deleted_exe")) { + this->highlightDeletedExe = atoi(option[1]); + } else if (String_eq(option[0], "highlight_megabytes")) { + this->highlightMegabytes = atoi(option[1]); + } else if (String_eq(option[0], "highlight_threads")) { + this->highlightThreads = atoi(option[1]); + } else if (String_eq(option[0], "highlight_changes")) { + this->highlightChanges = atoi(option[1]); + } else if (String_eq(option[0], "highlight_changes_delay_secs")) { + this->highlightDelaySecs = CLAMP(atoi(option[1]), 1, 24 * 60 * 60); + } else if (String_eq(option[0], "find_comm_in_cmdline")) { + this->findCommInCmdline = atoi(option[1]); + } else if (String_eq(option[0], "strip_exe_from_cmdline")) { + this->stripExeFromCmdline = atoi(option[1]); + } else if (String_eq(option[0], "show_merged_command")) { + this->showMergedCommand = atoi(option[1]); + } else if (String_eq(option[0], "header_margin")) { + this->headerMargin = atoi(option[1]); + } else if (String_eq(option[0], "expand_system_time")) { + // Compatibility option. + this->detailedCPUTime = atoi(option[1]); + } else if (String_eq(option[0], "detailed_cpu_time")) { + this->detailedCPUTime = atoi(option[1]); + } else if (String_eq(option[0], "cpu_count_from_one")) { + this->countCPUsFromOne = atoi(option[1]); + } else if (String_eq(option[0], "cpu_count_from_zero")) { + // old (inverted) naming also supported for backwards compatibility + this->countCPUsFromOne = !atoi(option[1]); + } else if (String_eq(option[0], "show_cpu_usage")) { + this->showCPUUsage = atoi(option[1]); + } else if (String_eq(option[0], "show_cpu_frequency")) { + this->showCPUFrequency = atoi(option[1]); + #ifdef BUILD_WITH_CPU_TEMP + } else if (String_eq(option[0], "show_cpu_temperature")) { + this->showCPUTemperature = atoi(option[1]); + } else if (String_eq(option[0], "degree_fahrenheit")) { + this->degreeFahrenheit = atoi(option[1]); + #endif + } else if (String_eq(option[0], "update_process_names")) { + this->updateProcessNames = atoi(option[1]); + } else if (String_eq(option[0], "account_guest_in_cpu_meter")) { + this->accountGuestInCPUMeter = atoi(option[1]); + } else if (String_eq(option[0], "delay")) { + this->delay = CLAMP(atoi(option[1]), 1, 255); + } else if (String_eq(option[0], "color_scheme")) { + this->colorScheme = atoi(option[1]); + if (this->colorScheme < 0 || this->colorScheme >= LAST_COLORSCHEME) { + this->colorScheme = 0; + } + #ifdef HAVE_GETMOUSE + } else if (String_eq(option[0], "enable_mouse")) { + this->enableMouse = atoi(option[1]); + #endif + } else if (String_eq(option[0], "left_meters")) { + Settings_readMeters(this, option[1], 0); + didReadMeters = true; + } else if (String_eq(option[0], "right_meters")) { + Settings_readMeters(this, option[1], 1); + didReadMeters = true; + } else if (String_eq(option[0], "left_meter_modes")) { + Settings_readMeterModes(this, option[1], 0); + didReadMeters = true; + } else if (String_eq(option[0], "right_meter_modes")) { + Settings_readMeterModes(this, option[1], 1); + didReadMeters = true; + } else if (String_eq(option[0], "hide_function_bar")) { + this->hideFunctionBar = atoi(option[1]); + #ifdef HAVE_LIBHWLOC + } else if (String_eq(option[0], "topology_affinity")) { + this->topologyAffinity = !!atoi(option[1]); + #endif + } + String_freeArray(option); + } + fclose(fd); + if (!didReadMeters) { + Settings_defaultMeters(this, initialCpuCount); + } + return didReadFields; +} + +static void writeFields(FILE* fd, const ProcessField* fields, const char* name) { + fprintf(fd, "%s=", name); + const char* sep = ""; + for (int i = 0; fields[i]; i++) { + // This "-1" is for compatibility with the older enum format. + fprintf(fd, "%s%d", sep, (int) fields[i] - 1); + sep = " "; + } + fprintf(fd, "\n"); +} + +static void writeMeters(const Settings* this, FILE* fd, int column) { + const char* sep = ""; + for (int i = 0; i < this->columns[column].len; i++) { + fprintf(fd, "%s%s", sep, this->columns[column].names[i]); + sep = " "; + } + fprintf(fd, "\n"); +} + +static void writeMeterModes(const Settings* this, FILE* fd, int column) { + const char* sep = ""; + for (int i = 0; i < this->columns[column].len; i++) { + fprintf(fd, "%s%d", sep, this->columns[column].modes[i]); + sep = " "; + } + fprintf(fd, "\n"); +} + +int Settings_write(const Settings* this, bool onCrash) { + FILE* fd; + if (onCrash) { + fd = stderr; + } else { + fd = fopen(this->filename, "w"); + if (fd == NULL) + return -errno; + } + + if (!onCrash) { + fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n"); + fprintf(fd, "# The parser is also very primitive, and not human-friendly.\n"); + } + writeFields(fd, this->fields, "fields"); + // This "-1" is for compatibility with the older enum format. + fprintf(fd, "sort_key=%d\n", (int) this->sortKey - 1); + fprintf(fd, "sort_direction=%d\n", (int) this->direction); + fprintf(fd, "tree_sort_key=%d\n", (int) this->treeSortKey - 1); + fprintf(fd, "tree_sort_direction=%d\n", (int) this->treeDirection); + fprintf(fd, "hide_kernel_threads=%d\n", (int) this->hideKernelThreads); + fprintf(fd, "hide_userland_threads=%d\n", (int) this->hideUserlandThreads); + fprintf(fd, "shadow_other_users=%d\n", (int) this->shadowOtherUsers); + fprintf(fd, "show_thread_names=%d\n", (int) this->showThreadNames); + fprintf(fd, "show_program_path=%d\n", (int) this->showProgramPath); + fprintf(fd, "highlight_base_name=%d\n", (int) this->highlightBaseName); + fprintf(fd, "highlight_deleted_exe=%d\n", (int) this->highlightDeletedExe); + fprintf(fd, "highlight_megabytes=%d\n", (int) this->highlightMegabytes); + fprintf(fd, "highlight_threads=%d\n", (int) this->highlightThreads); + fprintf(fd, "highlight_changes=%d\n", (int) this->highlightChanges); + fprintf(fd, "highlight_changes_delay_secs=%d\n", (int) this->highlightDelaySecs); + fprintf(fd, "find_comm_in_cmdline=%d\n", (int) this->findCommInCmdline); + fprintf(fd, "strip_exe_from_cmdline=%d\n", (int) this->stripExeFromCmdline); + fprintf(fd, "show_merged_command=%d\n", (int) this->showMergedCommand); + fprintf(fd, "tree_view=%d\n", (int) this->treeView); + fprintf(fd, "tree_view_always_by_pid=%d\n", (int) this->treeViewAlwaysByPID); + fprintf(fd, "all_branches_collapsed=%d\n", (int) this->allBranchesCollapsed); + fprintf(fd, "header_margin=%d\n", (int) this->headerMargin); + fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime); + fprintf(fd, "cpu_count_from_one=%d\n", (int) this->countCPUsFromOne); + fprintf(fd, "show_cpu_usage=%d\n", (int) this->showCPUUsage); + fprintf(fd, "show_cpu_frequency=%d\n", (int) this->showCPUFrequency); + #ifdef BUILD_WITH_CPU_TEMP + fprintf(fd, "show_cpu_temperature=%d\n", (int) this->showCPUTemperature); + fprintf(fd, "degree_fahrenheit=%d\n", (int) this->degreeFahrenheit); + #endif + fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames); + fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter); + fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme); + #ifdef HAVE_GETMOUSE + fprintf(fd, "enable_mouse=%d\n", (int) this->enableMouse); + #endif + fprintf(fd, "delay=%d\n", (int) this->delay); + fprintf(fd, "left_meters="); writeMeters(this, fd, 0); + fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0); + fprintf(fd, "right_meters="); writeMeters(this, fd, 1); + fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1); + fprintf(fd, "hide_function_bar=%d\n", (int) this->hideFunctionBar); + #ifdef HAVE_LIBHWLOC + fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity); + #endif + + if (onCrash) + return 0; + + int r = 0; + + if (ferror(fd) != 0) + r = (errno != 0) ? -errno : -EBADF; + + if (fclose(fd) != 0) + r = r ? r : -errno; + + return r; +} + +Settings* Settings_new(unsigned int initialCpuCount) { + Settings* this = xCalloc(1, sizeof(Settings)); + + this->sortKey = PERCENT_CPU; + this->treeSortKey = PID; + this->direction = -1; + this->treeDirection = 1; + this->shadowOtherUsers = false; + this->showThreadNames = false; + this->hideKernelThreads = false; + this->hideUserlandThreads = false; + this->treeView = false; + this->allBranchesCollapsed = false; + this->highlightBaseName = false; + this->highlightDeletedExe = true; + this->highlightMegabytes = false; + this->detailedCPUTime = false; + this->countCPUsFromOne = false; + this->showCPUUsage = true; + this->showCPUFrequency = false; + #ifdef BUILD_WITH_CPU_TEMP + this->showCPUTemperature = false; + this->degreeFahrenheit = false; + #endif + this->updateProcessNames = false; + this->showProgramPath = true; + this->highlightThreads = true; + this->highlightChanges = false; + this->highlightDelaySecs = DEFAULT_HIGHLIGHT_SECS; + this->findCommInCmdline = true; + this->stripExeFromCmdline = true; + this->showMergedCommand = false; + this->hideFunctionBar = 0; + #ifdef HAVE_LIBHWLOC + this->topologyAffinity = false; + #endif + this->fields = xCalloc(LAST_PROCESSFIELD + 1, sizeof(ProcessField)); + // TODO: turn 'fields' into a Vector, + // (and ProcessFields into proper objects). + this->flags = 0; + const ProcessField* defaults = Platform_defaultFields; + for (int i = 0; defaults[i]; i++) { + this->fields[i] = defaults[i]; + this->flags |= Process_fields[defaults[i]].flags; + } + + char* legacyDotfile = NULL; + const char* rcfile = getenv("HTOPRC"); + if (rcfile) { + this->filename = xStrdup(rcfile); + } else { + const char* home = getenv("HOME"); + if (!home) + home = ""; + + const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); + char* configDir = NULL; + char* htopDir = NULL; + if (xdgConfigHome) { + this->filename = String_cat(xdgConfigHome, "/htop/htoprc"); + configDir = xStrdup(xdgConfigHome); + htopDir = String_cat(xdgConfigHome, "/htop"); + } else { + this->filename = String_cat(home, "/.config/htop/htoprc"); + configDir = String_cat(home, "/.config"); + htopDir = String_cat(home, "/.config/htop"); + } + legacyDotfile = String_cat(home, "/.htoprc"); + (void) mkdir(configDir, 0700); + (void) mkdir(htopDir, 0700); + free(htopDir); + free(configDir); + struct stat st; + int err = lstat(legacyDotfile, &st); + if (err || S_ISLNK(st.st_mode)) { + free(legacyDotfile); + legacyDotfile = NULL; + } + } + this->colorScheme = 0; +#ifdef HAVE_GETMOUSE + this->enableMouse = true; +#endif + this->changed = false; + this->delay = DEFAULT_DELAY; + bool ok = false; + if (legacyDotfile) { + ok = Settings_read(this, legacyDotfile, initialCpuCount); + if (ok) { + // Transition to new location and delete old configuration file + if (Settings_write(this, false) == 0) { + unlink(legacyDotfile); + } + } + free(legacyDotfile); + } + if (!ok) { + ok = Settings_read(this, this->filename, initialCpuCount); + } + if (!ok) { + this->changed = true; + ok = Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount); + } + if (!ok) { + Settings_defaultMeters(this, initialCpuCount); + this->hideKernelThreads = true; + this->highlightMegabytes = true; + this->highlightThreads = true; + this->findCommInCmdline = true; + this->stripExeFromCmdline = true; + this->showMergedCommand = false; + this->headerMargin = true; + } + return this; +} + +void Settings_invertSortOrder(Settings* this) { + int* attr = (this->treeView) ? &(this->treeDirection) : &(this->direction); + *attr = (*attr == 1) ? -1 : 1; +} + +void Settings_setSortKey(Settings* this, ProcessField sortKey) { + if (this->treeViewAlwaysByPID || !this->treeView) { + this->sortKey = sortKey; + this->direction = (Process_fields[sortKey].defaultSortDesc) ? -1 : 1; + this->treeView = false; + } else { + this->treeSortKey = sortKey; + this->treeDirection = (Process_fields[sortKey].defaultSortDesc) ? -1 : 1; + } +} + +static bool readonly = false; + +void Settings_enableReadonly(void) { + readonly = true; +} + +bool Settings_isReadonly(void) { + return readonly; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Settings.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Settings.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Settings.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Settings.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,105 @@ +#ifndef HEADER_Settings +#define HEADER_Settings +/* +htop - Settings.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +#include "Process.h" + + +#define DEFAULT_DELAY 15 + +typedef struct { + int len; + char** names; + int* modes; +} MeterColumnSettings; + +typedef struct Settings_ { + char* filename; + MeterColumnSettings columns[2]; + + ProcessField* fields; + uint32_t flags; + int colorScheme; + int delay; + + int direction; + int treeDirection; + ProcessField sortKey; + ProcessField treeSortKey; + + bool countCPUsFromOne; + bool detailedCPUTime; + bool showCPUUsage; + bool showCPUFrequency; + #ifdef BUILD_WITH_CPU_TEMP + bool showCPUTemperature; + bool degreeFahrenheit; + #endif + bool treeView; + bool treeViewAlwaysByPID; + bool allBranchesCollapsed; + bool showProgramPath; + bool shadowOtherUsers; + bool showThreadNames; + bool hideKernelThreads; + bool hideUserlandThreads; + bool highlightBaseName; + bool highlightDeletedExe; + bool highlightMegabytes; + bool highlightThreads; + bool highlightChanges; + int highlightDelaySecs; + bool findCommInCmdline; + bool stripExeFromCmdline; + bool showMergedCommand; + bool updateProcessNames; + bool accountGuestInCPUMeter; + bool headerMargin; + #ifdef HAVE_GETMOUSE + bool enableMouse; + #endif + int hideFunctionBar; // 0 - off, 1 - on ESC until next input, 2 - permanently + #ifdef HAVE_LIBHWLOC + bool topologyAffinity; + #endif + + bool changed; +} Settings; + +#define Settings_cpuId(settings, cpu) ((settings)->countCPUsFromOne ? (cpu)+1 : (cpu)) + +static inline ProcessField Settings_getActiveSortKey(const Settings* this) { + return (this->treeView) + ? (this->treeViewAlwaysByPID ? PID : this->treeSortKey) + : this->sortKey; +} + +static inline int Settings_getActiveDirection(const Settings* this) { + return this->treeView ? this->treeDirection : this->direction; +} + +void Settings_delete(Settings* this); + +int Settings_write(const Settings* this, bool onCrash); + +Settings* Settings_new(unsigned int initialCpuCount); + +void Settings_invertSortOrder(Settings* this); + +void Settings_setSortKey(Settings* this, ProcessField sortKey); + +void Settings_enableReadonly(void); + +bool Settings_isReadonly(void); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/SignalsPanel.c pcp-5.3.2/vendor/github.com/htop-dev/htop/SignalsPanel.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/SignalsPanel.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/SignalsPanel.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,49 @@ +/* +htop - SignalsPanel.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "SignalsPanel.h" + +#include +#include + +#include "FunctionBar.h" +#include "ListItem.h" +#include "Object.h" +#include "Panel.h" +#include "Platform.h" +#include "XUtils.h" + + +Panel* SignalsPanel_new() { + Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Send ", "Cancel ")); + const int defaultSignal = SIGTERM; + int defaultPosition = 15; + unsigned int i; + for (i = 0; i < Platform_numberOfSignals; i++) { + Panel_set(this, i, (Object*) ListItem_new(Platform_signals[i].name, Platform_signals[i].number)); + // signal 15 is not always the 15th signal in the table + if (Platform_signals[i].number == defaultSignal) { + defaultPosition = i; + } + } + #if (defined(SIGRTMIN) && defined(SIGRTMAX)) + if (SIGRTMAX - SIGRTMIN <= 100) { + static char buf[16]; + for (int sig = SIGRTMIN; sig <= SIGRTMAX; i++, sig++) { + int n = sig - SIGRTMIN; + xSnprintf(buf, sizeof(buf), "%2d SIGRTMIN%-+3d", sig, n); + if (n == 0) { + buf[11] = '\0'; + } + Panel_set(this, i, (Object*) ListItem_new(buf, sig)); + } + } + #endif + Panel_setHeader(this, "Send signal:"); + Panel_setSelected(this, defaultPosition); + return this; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/SignalsPanel.h pcp-5.3.2/vendor/github.com/htop-dev/htop/SignalsPanel.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/SignalsPanel.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/SignalsPanel.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,20 @@ +#ifndef HEADER_SignalsPanel +#define HEADER_SignalsPanel +/* +htop - SignalsPanel.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Panel.h" + + +typedef struct SignalItem_ { + const char* name; + int number; +} SignalItem; + +Panel* SignalsPanel_new(void); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/Platform.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,315 @@ +/* +htop - solaris/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2015 David C. Hunt +(C) 2017,2018 Guy M. Broome +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "solaris/Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Macros.h" +#include "Meter.h" +#include "CPUMeter.h" +#include "MemoryMeter.h" +#include "SwapMeter.h" +#include "TasksMeter.h" +#include "LoadAverageMeter.h" +#include "ClockMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "HostnameMeter.h" +#include "SysArchMeter.h" +#include "UptimeMeter.h" +#include "zfs/ZfsArcMeter.h" +#include "zfs/ZfsCompressedArcMeter.h" +#include "SolarisProcess.h" +#include "SolarisProcessList.h" + + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT/IOT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGUSR1", .number = 16 }, + { .name = "17 SIGUSR2", .number = 17 }, + { .name = "18 SIGCHLD/CLD", .number = 18 }, + { .name = "19 SIGPWR", .number = 19 }, + { .name = "20 SIGWINCH", .number = 20 }, + { .name = "21 SIGURG", .number = 21 }, + { .name = "22 SIGPOLL/IO", .number = 22 }, + { .name = "23 SIGSTOP", .number = 23 }, + { .name = "24 SIGTSTP", .number = 24 }, + { .name = "25 SIGCONT", .number = 25 }, + { .name = "26 SIGTTIN", .number = 26 }, + { .name = "27 SIGTTOU", .number = 27 }, + { .name = "28 SIGVTALRM", .number = 28 }, + { .name = "29 SIGPROF", .number = 29 }, + { .name = "30 SIGXCPU", .number = 30 }, + { .name = "31 SIGXFSZ", .number = 31 }, + { .name = "32 SIGWAITING", .number = 32 }, + { .name = "33 SIGLWP", .number = 33 }, + { .name = "34 SIGFREEZE", .number = 34 }, + { .name = "35 SIGTHAW", .number = 35 }, + { .name = "36 SIGCANCEL", .number = 36 }, + { .name = "37 SIGLOST", .number = 37 }, + { .name = "38 SIGXRES", .number = 38 }, + { .name = "39 SIGJVM1", .number = 39 }, + { .name = "40 SIGJVM2", .number = 40 }, + { .name = "41 SIGINFO", .number = 41 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const ProcessField Platform_defaultFields[] = { PID, LWPID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &UptimeMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &ZfsArcMeter_class, + &ZfsCompressedArcMeter_class, + &BlankMeter_class, + NULL +}; + +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + int boot_time = 0; + int curr_time = time(NULL); + struct utmpx* ent; + + while (( ent = getutxent() )) { + if ( String_eq("system boot", ent->ut_line )) { + boot_time = ent->ut_tv.tv_sec; + } + } + + endutxent(); + + return (curr_time - boot_time); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + double plat_loadavg[3]; + if (getloadavg( plat_loadavg, 3 ) < 0) { + *one = NAN; + *five = NAN; + *fifteen = NAN; + return; + } + *one = plat_loadavg[LOADAVG_1MIN]; + *five = plat_loadavg[LOADAVG_5MIN]; + *fifteen = plat_loadavg[LOADAVG_15MIN]; +} + +int Platform_getMaxPid() { + int vproc = 32778; // Reasonable Solaris default + + kstat_ctl_t* kc = kstat_open(); + if (kc != NULL) { + kstat_t* kshandle = kstat_lookup_wrapper(kc, "unix", 0, "var"); + if (kshandle != NULL) { + kstat_read(kc, kshandle, NULL); + + kvar_t* ksvar = kshandle->ks_data; + if (ksvar && ksvar->v_proc > 0) { + vproc = ksvar->v_proc; + } + } + kstat_close(kc); + } + + return vproc; +} + +double Platform_setCPUValues(Meter* this, unsigned int cpu) { + const SolarisProcessList* spl = (const SolarisProcessList*) this->pl; + unsigned int cpus = this->pl->cpuCount; + const CPUData* cpuData = NULL; + + if (cpus == 1) { + // single CPU box has everything in spl->cpus[0] + cpuData = &(spl->cpus[0]); + } else { + cpuData = &(spl->cpus[cpu]); + } + + double percent; + double* v = this->values; + + v[CPU_METER_NICE] = cpuData->nicePercent; + v[CPU_METER_NORMAL] = cpuData->userPercent; + if (this->pl->settings->detailedCPUTime) { + v[CPU_METER_KERNEL] = cpuData->systemPercent; + v[CPU_METER_IRQ] = cpuData->irqPercent; + this->curItems = 4; + percent = v[0] + v[1] + v[2] + v[3]; + } else { + v[2] = cpuData->systemAllPercent; + this->curItems = 3; + percent = v[0] + v[1] + v[2]; + } + + percent = isnan(percent) ? 0.0 : CLAMP(percent, 0.0, 100.0); + + v[CPU_METER_FREQUENCY] = cpuData->frequency; + v[CPU_METER_TEMPERATURE] = NAN; + + return percent; +} + +void Platform_setMemoryValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalMem; + this->values[0] = pl->usedMem; + this->values[1] = pl->buffersMem; + // this->values[2] = "shared memory, like tmpfs and shm" + this->values[3] = pl->cachedMem; + // this->values[4] = "available memory" +} + +void Platform_setSwapValues(Meter* this) { + const ProcessList* pl = this->pl; + this->total = pl->totalSwap; + this->values[0] = pl->usedSwap; + this->values[1] = NAN; +} + +void Platform_setZfsArcValues(Meter* this) { + const SolarisProcessList* spl = (const SolarisProcessList*) this->pl; + + ZfsArcMeter_readStats(this, &(spl->zfs)); +} + +void Platform_setZfsCompressedArcValues(Meter* this) { + const SolarisProcessList* spl = (const SolarisProcessList*) this->pl; + + ZfsCompressedArcMeter_readStats(this, &(spl->zfs)); +} + +static int Platform_buildenv(void* accum, struct ps_prochandle* Phandle, uintptr_t addr, const char* str) { + envAccum* accump = accum; + (void) Phandle; + (void) addr; + size_t thissz = strlen(str); + if ((thissz + 2) > (accump->capacity - accump->size)) { + accump->env = xRealloc(accump->env, accump->capacity *= 2); + } + if ((thissz + 2) > (accump->capacity - accump->size)) { + return 1; + } + strlcpy( accump->env + accump->size, str, (accump->capacity - accump->size)); + strncpy( accump->env + accump->size + thissz + 1, "\n", 2); + accump->size = accump->size + thissz + 1; + return 0; +} + +char* Platform_getProcessEnv(pid_t pid) { + envAccum envBuilder; + pid_t realpid = pid / 1024; + int graberr; + struct ps_prochandle* Phandle; + + if ((Phandle = Pgrab(realpid, PGRAB_RDONLY, &graberr)) == NULL) { + return NULL; + } + + envBuilder.capacity = 4096; + envBuilder.size = 0; + envBuilder.env = xMalloc(envBuilder.capacity); + + (void) Penv_iter(Phandle, Platform_buildenv, &envBuilder); + + Prelease(Phandle, 0); + + strncpy( envBuilder.env + envBuilder.size, "\0", 1); + return envBuilder.env; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + // TODO + (void)data; + return false; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + // TODO + (void)data; + return false; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + *percent = NAN; + *isOnAC = AC_ERROR; +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/Platform.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,141 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - solaris/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2015 David C. Hunt +(C) 2017,2018 Guy M. Broome +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include + +/* On OmniOS /usr/include/sys/regset.h redefines ERR to 13 - \r, breaking the Enter key. + * Since ncruses macros use the ERR macro, we can not use another name. + */ +#undef ERR +#include +#undef ERR +#define ERR (-1) + +#include +#include + +#include +#include +#include + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "NetworkIOMeter.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "generic/hostname.h" +#include "generic/uname.h" + + +#define kill(pid, signal) kill(pid / 1024, signal) + +typedef struct var kvar_t; + +typedef struct envAccum_ { + size_t capacity; + size_t size; + size_t bytes; + char* env; +} envAccum; + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const ProcessField Platform_defaultFields[]; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, unsigned int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +void Platform_setZfsArcValues(Meter* this); + +void Platform_setZfsCompressedArcValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +static inline void Platform_getHostname(char* buffer, size_t size) { + Generic_hostname(buffer, size); +} + +static inline void Platform_getRelease(char** string) { + *string = Generic_uname(); +} + +#define PLATFORM_LONG_OPTIONS + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline void* kstat_data_lookup_wrapper(kstat_t* ksp, const char* name) { +IGNORE_WCASTQUAL_BEGIN + return kstat_data_lookup(ksp, (char*)name); +IGNORE_WCASTQUAL_END +} + +static inline kstat_t* kstat_lookup_wrapper(kstat_ctl_t* kc, const char* ks_module, int ks_instance, const char* ks_name) { +IGNORE_WCASTQUAL_BEGIN + return kstat_lookup(kc, (char*)ks_module, ks_instance, (char*)ks_name); +IGNORE_WCASTQUAL_END +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,24 @@ +#ifndef HEADER_SolarisProcessField +#define HEADER_SolarisProcessField +/* +htop - solaris/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + ZONEID = 100, \ + ZONE = 101, \ + PROJID = 102, \ + TASKID = 103, \ + POOLID = 104, \ + CONTID = 105, \ + LWPID = 106, \ + \ + DUMMY_BUMP_FIELD = CWD, \ + // End of list + + +#endif /* HEADER_SolarisProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,137 @@ +/* +htop - SolarisProcess.c +(C) 2015 Hisham H. Muhammad +(C) 2017,2018 Guy M. Broome +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "solaris/SolarisProcess.h" + +#include +#include +#include +#include + +#include "Process.h" +#include "ProcessList.h" +#include "CRT.h" + +#include "solaris/Platform.h" + + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, O onproc, Z zombie, T stopped, W waiting)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + //[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, + //[MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + //[MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, + [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process", .flags = 0, }, + [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process", .flags = 0, }, + [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, }, + [ZONEID] = { .name = "ZONEID", .title = "ZONEID", .description = "Zone ID", .flags = 0, .pidColumn = true, }, + [ZONE] = { .name = "ZONE", .title = "ZONE ", .description = "Zone name", .flags = 0, }, + [PROJID] = { .name = "PROJID", .title = "PRJID", .description = "Project ID", .flags = 0, .pidColumn = true, }, + [TASKID] = { .name = "TASKID", .title = "TSKID", .description = "Task ID", .flags = 0, .pidColumn = true, }, + [POOLID] = { .name = "POOLID", .title = "POLID", .description = "Pool ID", .flags = 0, .pidColumn = true, }, + [CONTID] = { .name = "CONTID", .title = "CNTID", .description = "Contract ID", .flags = 0, .pidColumn = true, }, + [LWPID] = { .name = "LWPID", .title = "LWPID", .description = "LWP ID", .flags = 0, .pidColumn = true, }, +}; + +Process* SolarisProcess_new(const Settings* settings) { + SolarisProcess* this = xCalloc(1, sizeof(SolarisProcess)); + Object_setClass(this, Class(SolarisProcess)); + Process_init(&this->super, settings); + return &this->super; +} + +void Process_delete(Object* cast) { + SolarisProcess* sp = (SolarisProcess*) cast; + Process_done((Process*)cast); + free(sp->zname); + free(sp); +} + +static void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const SolarisProcess* sp = (const SolarisProcess*) this; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + int n = sizeof(buffer) - 1; + switch (field) { + // add Solaris-specific fields here + case ZONEID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->zoneid); break; + case PROJID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->projid); break; + case TASKID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->taskid); break; + case POOLID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->poolid); break; + case CONTID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->contid); break; + case ZONE: Process_printLeftAlignedField(str, attr, sp->zname ? sp->zname : "global", ZONENAME_MAX/4); return; + case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realpid); break; + case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realppid); break; + case TGID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realtgid); break; + case LWPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->lwpid); break; + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int SolarisProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const SolarisProcess* p1 = (const SolarisProcess*)v1; + const SolarisProcess* p2 = (const SolarisProcess*)v2; + + switch (key) { + case ZONEID: + return SPACESHIP_NUMBER(p1->zoneid, p2->zoneid); + case PROJID: + return SPACESHIP_NUMBER(p1->projid, p2->projid); + case TASKID: + return SPACESHIP_NUMBER(p1->taskid, p2->taskid); + case POOLID: + return SPACESHIP_NUMBER(p1->poolid, p2->poolid); + case CONTID: + return SPACESHIP_NUMBER(p1->contid, p2->contid); + case ZONE: + return strcmp(p1->zname ? p1->zname : "global", p2->zname ? p2->zname : "global"); + case PID: + return SPACESHIP_NUMBER(p1->realpid, p2->realpid); + case PPID: + return SPACESHIP_NUMBER(p1->realppid, p2->realppid); + case LWPID: + return SPACESHIP_NUMBER(p1->lwpid, p2->lwpid); + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass SolarisProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = SolarisProcess_writeField, + .compareByKey = SolarisProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,49 @@ +#ifndef HEADER_SolarisProcess +#define HEADER_SolarisProcess +/* +htop - SolarisProcess.h +(C) 2015 Hisham H. Muhammad +(C) 2017,2018 Guy M. Broome +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include + +/* On OmniOS /usr/include/sys/regset.h redefines ERR to 13 - \r, breaking the Enter key. + * Since ncruses macros use the ERR macro, we can not use another name. + */ +#undef ERR +#include +#undef ERR +#define ERR (-1) + +#include "Settings.h" + + +typedef struct SolarisProcess_ { + Process super; + zoneid_t zoneid; + char* zname; + taskid_t taskid; + projid_t projid; + poolid_t poolid; + ctid_t contid; + pid_t realpid; + pid_t realppid; + pid_t realtgid; + pid_t lwpid; +} SolarisProcess; + +extern const ProcessClass SolarisProcess_class; + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* SolarisProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,493 @@ +/* +htop - SolarisProcessList.c +(C) 2014 Hisham H. Muhammad +(C) 2017,2018 Guy M. Broome +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#include "solaris/SolarisProcessList.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "solaris/Platform.h" +#include "solaris/SolarisProcess.h" + + +#define GZONE "global " +#define UZONE "unknown " + +static int pageSize; +static int pageSizeKB; + +static char* SolarisProcessList_readZoneName(kstat_ctl_t* kd, SolarisProcess* sproc) { + char* zname; + + if ( sproc->zoneid == 0 ) { + zname = xStrdup(GZONE); + } else if ( kd == NULL ) { + zname = xStrdup(UZONE); + } else { + kstat_t* ks = kstat_lookup_wrapper( kd, "zones", sproc->zoneid, NULL ); + zname = xStrdup(ks == NULL ? UZONE : ks->ks_name); + } + + return zname; +} + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + SolarisProcessList* spl = xCalloc(1, sizeof(SolarisProcessList)); + ProcessList* pl = (ProcessList*) spl; + ProcessList_init(pl, Class(SolarisProcess), usersTable, dynamicMeters, pidMatchList, userId); + + spl->kd = kstat_open(); + + pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + CRT_fatalError("Cannot get pagesize by sysconf(_SC_PAGESIZE)"); + pageSizeKB = pageSize / 1024; + + pl->cpuCount = sysconf(_SC_NPROCESSORS_ONLN); + if (pl->cpuCount == (unsigned int)-1) + CRT_fatalError("Cannot get CPU count by sysconf(_SC_NPROCESSORS_ONLN)"); + else if (pl->cpuCount == 1) + spl->cpus = xRealloc(spl->cpus, sizeof(CPUData)); + else + spl->cpus = xRealloc(spl->cpus, (pl->cpuCount + 1) * sizeof(CPUData)); + + return pl; +} + +static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) { + const SolarisProcessList* spl = (SolarisProcessList*) pl; + unsigned int cpus = pl->cpuCount; + kstat_t* cpuinfo = NULL; + kstat_named_t* idletime = NULL; + kstat_named_t* intrtime = NULL; + kstat_named_t* krnltime = NULL; + kstat_named_t* usertime = NULL; + kstat_named_t* cpu_freq = NULL; + double idlebuf = 0; + double intrbuf = 0; + double krnlbuf = 0; + double userbuf = 0; + int arrskip = 0; + + assert(cpus > 0); + + if (cpus > 1) { + // Store values for the stats loop one extra element up in the array + // to leave room for the average to be calculated afterwards + arrskip++; + } + + // Calculate per-CPU statistics first + for (unsigned int i = 0; i < cpus; i++) { + if (spl->kd != NULL) { + if ((cpuinfo = kstat_lookup_wrapper(spl->kd, "cpu", i, "sys")) != NULL) { + if (kstat_read(spl->kd, cpuinfo, NULL) != -1) { + idletime = kstat_data_lookup_wrapper(cpuinfo, "cpu_nsec_idle"); + intrtime = kstat_data_lookup_wrapper(cpuinfo, "cpu_nsec_intr"); + krnltime = kstat_data_lookup_wrapper(cpuinfo, "cpu_nsec_kernel"); + usertime = kstat_data_lookup_wrapper(cpuinfo, "cpu_nsec_user"); + } + } + } + + assert( (idletime != NULL) && (intrtime != NULL) + && (krnltime != NULL) && (usertime != NULL) ); + + if (pl->settings->showCPUFrequency) { + if (spl->kd != NULL) { + if ((cpuinfo = kstat_lookup_wrapper(spl->kd, "cpu_info", i, NULL)) != NULL) { + if (kstat_read(spl->kd, cpuinfo, NULL) != -1) { + cpu_freq = kstat_data_lookup_wrapper(cpuinfo, "current_clock_Hz"); + } + } + } + + assert( cpu_freq != NULL ); + } + + CPUData* cpuData = &(spl->cpus[i + arrskip]); + + uint64_t totaltime = (idletime->value.ui64 - cpuData->lidle) + + (intrtime->value.ui64 - cpuData->lintr) + + (krnltime->value.ui64 - cpuData->lkrnl) + + (usertime->value.ui64 - cpuData->luser); + + // Calculate percentages of deltas since last reading + cpuData->userPercent = ((usertime->value.ui64 - cpuData->luser) / (double)totaltime) * 100.0; + cpuData->nicePercent = (double)0.0; // Not implemented on Solaris + cpuData->systemPercent = ((krnltime->value.ui64 - cpuData->lkrnl) / (double)totaltime) * 100.0; + cpuData->irqPercent = ((intrtime->value.ui64 - cpuData->lintr) / (double)totaltime) * 100.0; + cpuData->systemAllPercent = cpuData->systemPercent + cpuData->irqPercent; + cpuData->idlePercent = ((idletime->value.ui64 - cpuData->lidle) / (double)totaltime) * 100.0; + // Store current values to use for the next round of deltas + cpuData->luser = usertime->value.ui64; + cpuData->lkrnl = krnltime->value.ui64; + cpuData->lintr = intrtime->value.ui64; + cpuData->lidle = idletime->value.ui64; + // Add frequency in MHz + cpuData->frequency = pl->settings->showCPUFrequency ? (double)cpu_freq->value.ui64 / 1E6 : NAN; + // Accumulate the current percentages into buffers for later average calculation + if (cpus > 1) { + userbuf += cpuData->userPercent; + krnlbuf += cpuData->systemPercent; + intrbuf += cpuData->irqPercent; + idlebuf += cpuData->idlePercent; + } + } + + if (cpus > 1) { + CPUData* cpuData = &(spl->cpus[0]); + cpuData->userPercent = userbuf / cpus; + cpuData->nicePercent = (double)0.0; // Not implemented on Solaris + cpuData->systemPercent = krnlbuf / cpus; + cpuData->irqPercent = intrbuf / cpus; + cpuData->systemAllPercent = cpuData->systemPercent + cpuData->irqPercent; + cpuData->idlePercent = idlebuf / cpus; + } +} + +static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { + SolarisProcessList* spl = (SolarisProcessList*) pl; + static kstat_t *meminfo = NULL; + int ksrphyserr = -1; + kstat_named_t *totalmem_pgs = NULL; + kstat_named_t *freemem_pgs = NULL; + kstat_named_t *pages = NULL; + struct swaptable *sl = NULL; + struct swapent *swapdev = NULL; + uint64_t totalswap = 0; + uint64_t totalfree = 0; + int nswap = 0; + char *spath = NULL; + char *spathbase = NULL; + + // Part 1 - physical memory + if (spl->kd != NULL && meminfo == NULL) { + // Look up the kstat chain just once, it never changes + meminfo = kstat_lookup_wrapper(spl->kd, "unix", 0, "system_pages"); + } + if (meminfo != NULL) { + ksrphyserr = kstat_read(spl->kd, meminfo, NULL); + } + if (ksrphyserr != -1) { + totalmem_pgs = kstat_data_lookup_wrapper(meminfo, "physmem"); + freemem_pgs = kstat_data_lookup_wrapper(meminfo, "freemem"); + pages = kstat_data_lookup_wrapper(meminfo, "pagestotal"); + + pl->totalMem = totalmem_pgs->value.ui64 * pageSizeKB; + if (pl->totalMem > freemem_pgs->value.ui64 * pageSizeKB) { + pl->usedMem = pl->totalMem - freemem_pgs->value.ui64 * pageSizeKB; + } else { + pl->usedMem = 0; // This can happen in non-global zone (in theory) + } + // Not sure how to implement this on Solaris - suggestions welcome! + pl->cachedMem = 0; + // Not really "buffers" but the best Solaris analogue that I can find to + // "memory in use but not by programs or the kernel itself" + pl->buffersMem = (totalmem_pgs->value.ui64 - pages->value.ui64) * pageSizeKB; + } else { + // Fall back to basic sysconf if kstat isn't working + pl->totalMem = sysconf(_SC_PHYS_PAGES) * pageSize; + pl->buffersMem = 0; + pl->cachedMem = 0; + pl->usedMem = pl->totalMem - (sysconf(_SC_AVPHYS_PAGES) * pageSize); + } + + // Part 2 - swap + nswap = swapctl(SC_GETNSWP, NULL); + if (nswap > 0) { + sl = xMalloc((nswap * sizeof(swapent_t)) + sizeof(int)); + } + if (sl != NULL) { + spathbase = xMalloc( nswap * MAXPATHLEN ); + } + if (spathbase != NULL) { + spath = spathbase; + swapdev = sl->swt_ent; + for (int i = 0; i < nswap; i++, swapdev++) { + swapdev->ste_path = spath; + spath += MAXPATHLEN; + } + sl->swt_n = nswap; + } + nswap = swapctl(SC_LIST, sl); + if (nswap > 0) { + swapdev = sl->swt_ent; + for (int i = 0; i < nswap; i++, swapdev++) { + totalswap += swapdev->ste_pages; + totalfree += swapdev->ste_free; + } + } + free(spathbase); + free(sl); + pl->totalSwap = totalswap * pageSizeKB; + pl->usedSwap = pl->totalSwap - (totalfree * pageSizeKB); +} + +static inline void SolarisProcessList_scanZfsArcstats(ProcessList* pl) { + SolarisProcessList* spl = (SolarisProcessList*) pl; + kstat_t *arcstats = NULL; + int ksrphyserr = -1; + kstat_named_t *cur_kstat = NULL; + + if (spl->kd != NULL) { + arcstats = kstat_lookup_wrapper(spl->kd, "zfs", 0, "arcstats"); + } + if (arcstats != NULL) { + ksrphyserr = kstat_read(spl->kd, arcstats, NULL); + } + if (ksrphyserr != -1) { + cur_kstat = kstat_data_lookup_wrapper( arcstats, "size" ); + spl->zfs.size = cur_kstat->value.ui64 / 1024; + spl->zfs.enabled = spl->zfs.size > 0 ? 1 : 0; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "c_max" ); + spl->zfs.max = cur_kstat->value.ui64 / 1024; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "mfu_size" ); + spl->zfs.MFU = cur_kstat != NULL ? cur_kstat->value.ui64 / 1024 : 0; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "mru_size" ); + spl->zfs.MRU = cur_kstat != NULL ? cur_kstat->value.ui64 / 1024 : 0; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "anon_size" ); + spl->zfs.anon = cur_kstat != NULL ? cur_kstat->value.ui64 / 1024 : 0; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "hdr_size" ); + spl->zfs.header = cur_kstat != NULL ? cur_kstat->value.ui64 / 1024 : 0; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "other_size" ); + spl->zfs.other = cur_kstat != NULL ? cur_kstat->value.ui64 / 1024 : 0; + + if ((cur_kstat = kstat_data_lookup_wrapper( arcstats, "compressed_size" )) != NULL) { + spl->zfs.compressed = cur_kstat->value.ui64 / 1024; + spl->zfs.isCompressed = 1; + + cur_kstat = kstat_data_lookup_wrapper( arcstats, "uncompressed_size" ); + spl->zfs.uncompressed = cur_kstat->value.ui64 / 1024; + } else { + spl->zfs.isCompressed = 0; + } + } +} + +void ProcessList_delete(ProcessList* pl) { + SolarisProcessList* spl = (SolarisProcessList*) pl; + ProcessList_done(pl); + free(spl->cpus); + if (spl->kd) { + kstat_close(spl->kd); + } + free(spl); +} + +static void SolarisProcessList_updateExe(pid_t pid, Process* proc) { + char path[32]; + xSnprintf(path, sizeof(path), "/proc/%d/path/a.out", pid); + + char target[PATH_MAX]; + ssize_t ret = readlink(path, target, sizeof(target) - 1); + if (ret <= 0) + return; + + target[ret] = '\0'; + Process_updateExe(proc, target); +} + +static void SolarisProcessList_updateCwd(pid_t pid, Process* proc) { + char path[32]; + xSnprintf(path, sizeof(path), "/proc/%d/cwd", pid); + + char target[PATH_MAX]; + ssize_t ret = readlink(path, target, sizeof(target) - 1); + if (ret <= 0) + return; + + target[ret] = '\0'; + free_and_xStrdup(&proc->procCwd, target); +} + +/* NOTE: the following is a callback function of type proc_walk_f + * and MUST conform to the appropriate definition in order + * to work. See libproc(3LIB) on a Solaris or Illumos + * system for more info. + */ + +static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, void* listptr) { + bool preExisting; + pid_t getpid; + + // Setup process list + ProcessList* pl = (ProcessList*) listptr; + SolarisProcessList* spl = (SolarisProcessList*) listptr; + + id_t lwpid_real = _lwpsinfo->pr_lwpid; + if (lwpid_real > 1023) { + return 0; + } + + pid_t lwpid = (_psinfo->pr_pid * 1024) + lwpid_real; + bool onMasterLWP = (_lwpsinfo->pr_lwpid == _psinfo->pr_lwp.pr_lwpid); + if (onMasterLWP) { + getpid = _psinfo->pr_pid * 1024; + } else { + getpid = lwpid; + } + + Process* proc = ProcessList_getProcess(pl, getpid, &preExisting, SolarisProcess_new); + SolarisProcess* sproc = (SolarisProcess*) proc; + + // Common code pass 1 + proc->show = false; + sproc->taskid = _psinfo->pr_taskid; + sproc->projid = _psinfo->pr_projid; + sproc->poolid = _psinfo->pr_poolid; + sproc->contid = _psinfo->pr_contract; + proc->priority = _lwpsinfo->pr_pri; + proc->nice = _lwpsinfo->pr_nice - NZERO; + proc->processor = _lwpsinfo->pr_onpro; + proc->state = _lwpsinfo->pr_sname; + // NOTE: This 'percentage' is a 16-bit BINARY FRACTIONS where 1.0 = 0x8000 + // Source: https://docs.oracle.com/cd/E19253-01/816-5174/proc-4/index.html + // (accessed on 18 November 2017) + proc->percent_mem = ((uint16_t)_psinfo->pr_pctmem / (double)32768) * (double)100.0; + proc->pgrp = _psinfo->pr_pgid; + proc->nlwp = _psinfo->pr_nlwp; + proc->session = _psinfo->pr_sid; + + proc->tty_nr = _psinfo->pr_ttydev; + const char* name = (_psinfo->pr_ttydev != PRNODEV) ? ttyname(_psinfo->pr_ttydev) : NULL; + if (!name) { + free(proc->tty_name); + proc->tty_name = NULL; + } else { + free_and_xStrdup(&proc->tty_name, name); + } + + proc->m_resident = _psinfo->pr_rssize; // KB + proc->m_virt = _psinfo->pr_size; // KB + + if (proc->st_uid != _psinfo->pr_euid) { + proc->st_uid = _psinfo->pr_euid; + proc->user = UsersTable_getRef(pl->usersTable, proc->st_uid); + } + + if (!preExisting) { + sproc->realpid = _psinfo->pr_pid; + sproc->lwpid = lwpid_real; + sproc->zoneid = _psinfo->pr_zoneid; + sproc->zname = SolarisProcessList_readZoneName(spl->kd, sproc); + SolarisProcessList_updateExe(_psinfo->pr_pid, proc); + + Process_updateComm(proc, _psinfo->pr_fname); + Process_updateCmdline(proc, _psinfo->pr_psargs, 0, 0); + + if (proc->settings->flags & PROCESS_FLAG_CWD) { + SolarisProcessList_updateCwd(_psinfo->pr_pid, proc); + } + } + + // End common code pass 1 + + if (onMasterLWP) { // Are we on the representative LWP? + proc->ppid = (_psinfo->pr_ppid * 1024); + proc->tgid = (_psinfo->pr_ppid * 1024); + sproc->realppid = _psinfo->pr_ppid; + sproc->realtgid = _psinfo->pr_ppid; + // See note above (in common section) about this BINARY FRACTION + proc->percent_cpu = ((uint16_t)_psinfo->pr_pctcpu / (double)32768) * (double)100.0; + proc->time = _psinfo->pr_time.tv_sec; + if (!preExisting) { // Tasks done only for NEW processes + proc->isUserlandThread = false; + proc->starttime_ctime = _psinfo->pr_start.tv_sec; + } + + // Update proc and thread counts based on settings + if (proc->isKernelThread && !pl->settings->hideKernelThreads) { + pl->kernelThreads += proc->nlwp; + pl->totalTasks += proc->nlwp + 1; + if (proc->state == 'O') { + pl->runningTasks++; + } + } else if (!proc->isKernelThread) { + if (proc->state == 'O') { + pl->runningTasks++; + } + if (pl->settings->hideUserlandThreads) { + pl->totalTasks++; + } else { + pl->userlandThreads += proc->nlwp; + pl->totalTasks += proc->nlwp + 1; + } + } + proc->show = !(pl->settings->hideKernelThreads && proc->isKernelThread); + } else { // We are not in the master LWP, so jump to the LWP handling code + proc->percent_cpu = ((uint16_t)_lwpsinfo->pr_pctcpu / (double)32768) * (double)100.0; + proc->time = _lwpsinfo->pr_time.tv_sec; + if (!preExisting) { // Tasks done only for NEW LWPs + proc->isUserlandThread = true; + proc->ppid = _psinfo->pr_pid * 1024; + proc->tgid = _psinfo->pr_pid * 1024; + sproc->realppid = _psinfo->pr_pid; + sproc->realtgid = _psinfo->pr_pid; + proc->starttime_ctime = _lwpsinfo->pr_start.tv_sec; + } + + // Top-level process only gets this for the representative LWP + if (proc->isKernelThread && !pl->settings->hideKernelThreads) { + proc->show = true; + } + if (!proc->isKernelThread && !pl->settings->hideUserlandThreads) { + proc->show = true; + } + } // Top-level LWP or subordinate LWP + + // Common code pass 2 + + if (!preExisting) { + if ((sproc->realppid <= 0) && !(sproc->realpid <= 1)) { + proc->isKernelThread = true; + } else { + proc->isKernelThread = false; + } + + Process_fillStarttimeBuffer(proc); + ProcessList_add(pl, proc); + } + + proc->updated = true; + + // End common code pass 2 + + return 0; +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + SolarisProcessList_scanCPUTime(super); + SolarisProcessList_scanMemoryInfo(super); + SolarisProcessList_scanZfsArcstats(super); + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + super->kernelThreads = 1; + proc_walk(&SolarisProcessList_walkproc, super, PR_WALK_LWP); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/solaris/SolarisProcessList.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,62 @@ +#ifndef HEADER_SolarisProcessList +#define HEADER_SolarisProcessList +/* +htop - SolarisProcessList.h +(C) 2014 Hisham H. Muhammad +(C) 2017,2018 Guy M. Broome +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" + +#include "solaris/SolarisProcess.h" + +#include "zfs/ZfsArcStats.h" + + +#define ZONE_ERRMSGLEN 1024 +extern char zone_errmsg[ZONE_ERRMSGLEN]; + +typedef struct CPUData_ { + double userPercent; + double nicePercent; + double systemPercent; + double irqPercent; + double idlePercent; + double systemAllPercent; + double frequency; + uint64_t luser; + uint64_t lkrnl; + uint64_t lintr; + uint64_t lidle; +} CPUData; + +typedef struct SolarisProcessList_ { + ProcessList super; + kstat_ctl_t* kd; + CPUData* cpus; + ZfsArcStats zfs; +} SolarisProcessList; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* pl); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/SwapMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/SwapMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/SwapMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/SwapMeter.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,73 @@ +/* +htop - SwapMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "SwapMeter.h" + +#include +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" + + +static const int SwapMeter_attributes[] = { + SWAP, + SWAP_CACHE +}; + +static void SwapMeter_updateValues(Meter* this) { + char* buffer = this->txtBuffer; + size_t size = sizeof(this->txtBuffer); + int written; + + this->values[1] = NAN; /* 'cached' not present on all platforms */ + Platform_setSwapValues(this); + + written = Meter_humanUnit(buffer, this->values[0], size); + METER_BUFFER_CHECK(buffer, size, written); + + METER_BUFFER_APPEND_CHR(buffer, size, '/'); + + Meter_humanUnit(buffer, this->total, size); +} + +static void SwapMeter_display(const Object* cast, RichString* out) { + char buffer[50]; + const Meter* this = (const Meter*)cast; + RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + + if (!isnan(this->values[1])) { + Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " cache:"); + RichString_appendAscii(out, CRT_colors[SWAP_CACHE], buffer); + } +} + +const MeterClass SwapMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = SwapMeter_display, + }, + .updateValues = SwapMeter_updateValues, + .defaultMode = BAR_METERMODE, + .maxItems = 2, + .total = 100.0, + .attributes = SwapMeter_attributes, + .name = "Swap", + .uiName = "Swap", + .caption = "Swp" +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/SwapMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/SwapMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/SwapMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/SwapMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_SwapMeter +#define HEADER_SwapMeter +/* +htop - SwapMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass SwapMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/SysArchMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/SysArchMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/SysArchMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/SysArchMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,44 @@ +/* +htop - SysArchMeter.c +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "SysArchMeter.h" + +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "XUtils.h" + + +static const int SysArchMeter_attributes[] = {HOSTNAME}; + +static void SysArchMeter_updateValues(Meter* this) { + static char* string; + + if (string == NULL) + Platform_getRelease(&string); + + String_safeStrncpy(this->txtBuffer, string, sizeof(this->txtBuffer)); +} + +const MeterClass SysArchMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = SysArchMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = SysArchMeter_attributes, + .name = "System", + .uiName = "System", + .caption = "System: ", +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/SysArchMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/SysArchMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/SysArchMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/SysArchMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,14 @@ +#ifndef HEADER_SysArchMeter +#define HEADER_SysArchMeter +/* +htop - SysArchMeter.h +(C) 2021 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +#include "Meter.h" + + +extern const MeterClass SysArchMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/TasksMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/TasksMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/TasksMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/TasksMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,76 @@ +/* +htop - TasksMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "TasksMeter.h" + +#include "CRT.h" +#include "Macros.h" +#include "Object.h" +#include "ProcessList.h" +#include "RichString.h" +#include "Settings.h" +#include "XUtils.h" + + +static const int TasksMeter_attributes[] = { + CPU_SYSTEM, + PROCESS_THREAD, + PROCESS, + TASKS_RUNNING +}; + +static void TasksMeter_updateValues(Meter* this) { + const ProcessList* pl = this->pl; + this->values[0] = pl->kernelThreads; + this->values[1] = pl->userlandThreads; + this->values[2] = pl->totalTasks - pl->kernelThreads - pl->userlandThreads; + this->values[3] = MINIMUM(pl->runningTasks, pl->cpuCount); + this->total = pl->totalTasks; + + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%d/%d", (int) this->values[3], (int) this->total); +} + +static void TasksMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + const Settings* settings = this->pl->settings; + char buffer[20]; + int len; + + len = xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[2]); + RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, len); + + RichString_appendAscii(out, settings->hideUserlandThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], ", "); + len = xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[1]); + RichString_appendnAscii(out, settings->hideUserlandThreads ? CRT_colors[METER_SHADOW] : CRT_colors[TASKS_RUNNING], buffer, len); + RichString_appendAscii(out, settings->hideUserlandThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], " thr"); + + RichString_appendAscii(out, settings->hideKernelThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], ", "); + len = xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[0]); + RichString_appendnAscii(out, settings->hideKernelThreads ? CRT_colors[METER_SHADOW] : CRT_colors[TASKS_RUNNING], buffer, len); + RichString_appendAscii(out, settings->hideKernelThreads ? CRT_colors[METER_SHADOW] : CRT_colors[METER_TEXT], " kthr"); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], "; "); + len = xSnprintf(buffer, sizeof(buffer), "%d", (int)this->values[3]); + RichString_appendnAscii(out, CRT_colors[TASKS_RUNNING], buffer, len); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " running"); +} + +const MeterClass TasksMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = TasksMeter_display, + }, + .updateValues = TasksMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 4, + .total = 100.0, + .attributes = TasksMeter_attributes, + .name = "Tasks", + .uiName = "Task counter", + .caption = "Tasks: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/TasksMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/TasksMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/TasksMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/TasksMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_TasksMeter +#define HEADER_TasksMeter +/* +htop - TasksMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass TasksMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/TESTPLAN pcp-5.3.2/vendor/github.com/htop-dev/htop/TESTPLAN --- pcp-5.3.1/vendor/github.com/htop-dev/htop/TESTPLAN 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/TESTPLAN 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,156 @@ + +Main screen: + + For all views, all modes: + + Mouse click header - nothing happens. + + Mouse click on ProcessList title bar - exit Tree view, update FunctionBar, title bar updates, sort by clicked field. +*** FAILING: wrong FB update depending on mode; does not change sort in wip branch + click on same entry - invert sort. + click on another entry - sort another field. + + Mouse click on a process - select that process. + + for each entry in FunctionBar: + Mouse click entry - perform action of associated key. + + In Normal mode, Sorted view: + + <+> or <-> - do nothing. + + - enter SortBy screen. + + In Normal mode, Tree view: + + select process - update F6 in FunctionBar if subtree is collapsed or expanded. + + , <+> or <-> - expand/collapse subtree. + + In Normal mode, either Sorted or Tree view: + + , - activate Search mode. + + , <\> - activate Filter mode. + + , <]> - as root only, decrease process NICE value. + + , <[> - increase process NICE value. + + - enter Affinity screen. + + - do nothing. + + - select process and all its children. + + , , , - do nothing. + + , , - enter Help screen. + + - on Linux, enter IOPriority screen. + + - do nothing. + + , - enter Kill screen. + + - enter LSOF screen. + + , , - do nothing. + +

- enter Sorted view, update function bar, sort by CPU%. + + , - do nothing. + + - enter Sorted view, update function bar, sort by TIME. + + - untag all processes. + + , , , , - do nothing. + + <<>, <>>, <,>, <.> - enter SortBy screen. + + space - tag current process, move down cursor. + + numbers - incremental PID search. + + In Search mode: + + TODO + + In Filter mode: + + TODO + +Setup screen: + + TODO + +SortBy screen: + + TODO + +User screen: + + TODO + +Kill screen: + + TODO + +Affinity screen: + + TODO + +Help screen: + + any key - back to Main screen. + +IOPriority screen: + + TODO + +STrace screen: + + TODO + +LSOF screen: + + TODO diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/test_spec.lua pcp-5.3.2/vendor/github.com/htop-dev/htop/test_spec.lua --- pcp-5.3.1/vendor/github.com/htop-dev/htop/test_spec.lua 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/test_spec.lua 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,687 @@ +#!/usr/bin/env lua + +local VISUALDELAY = os.getenv("VISUALDELAY") + +local visual = VISUALDELAY or false +local visual_delay = VISUALDELAY and (tonumber(VISUALDELAY)) or 0.1 +local short_delay = 0.3 +local long_delay = 1 + +local unistd = require("posix.unistd") +local time = require("posix.time") +local curses = require("posix.curses") +local rote = require("rote") + +local rt = rote.RoteTerm(24, 80) + +--[[ +local function os_execread(cmd) + local fd = io.popen(cmd, "r") + local out = fd:read("*a") + fd:close() + return (out:gsub("\n$", "")) +end +]] +--local branch = os_execread("git branch | grep '*'"):sub(3) +--print("Running in branch "..branch) + +os.execute("make coverage") +os.execute("rm -f *.gcda */*.gcda") +os.execute("rm -f coverage.info test.htoprc") +os.execute("rm -rf lcov") +os.execute("killall htop") +os.execute("ps aux | grep '[s]leep 12345' | awk '{print $2}' | xargs kill 2> /dev/null") + +os.execute("cp ./default.htoprc ./test.htoprc") +rt:forkPty("LC_ALL=C HTOPRC=./test.htoprc ./htop 2> htop-valgrind.txt") + +local stdscr, term_win +-- Curses initialization needed even when not in visual mode +-- because luaposix only initializes KEY_* constants after initscr(). +stdscr = curses.initscr() +if visual then + curses.echo(false) + curses.start_color() + curses.raw(true) + curses.halfdelay(1) + stdscr:keypad(true) + term_win = curses.newwin(24, 80, 0, 0) + local function makePair(foreground, background) + return background * 8 + 7 - foreground + end + -- initialize the color pairs the way rt:draw() expects it + for foreground = 0, 7 do + for background = 0, 7 do + if foreground ~= 7 or background ~= 0 then + local pair = makePair(foreground, background) + curses.init_pair(pair, foreground, background) + end + end + end +else + curses.endwin() +end + +local function show(key) + rt:update() + if visual then + rt:draw(term_win, 0, 0) + if key then + term_win:mvaddstr(0, 0, tostring(key)) + end + term_win:refresh() + + delay(visual_delay) + end +end + +local function send(key, times, quick) + if times == 0 then return end + for _ = 1, times or 1 do + delay(0.003) -- 30ms delay to avoid clobbering Esc sequences + if type(key) == "string" then + for c in key:gmatch('.') do + rt:keyPress(string.byte(c)) + end + else + rt:keyPress(key) + end + if not quick then + show(key) + end + end + if quick then + show(key) + end +end + +local function string_at(x, y, len) + rt:update() + local out = {} + for i = 1, len do + out[#out+1] = rt:cellChar(y-1, x+i-2) + end + return table.concat(out) +end + +local function is_string_at(x, y, str) + return string_at(x, y, #str) == str +end + +local function check_string_at(x, y, str) + return { str, string_at(x, y, #str) } +end + +local ESC = "\27\27" + +function delay(t) + time.nanosleep({ tv_sec = math.floor(t), tv_nsec = (t - math.floor(t)) * 1000000000 }) +end + +delay(2) -- give some time for htop to initialize. +rt:update() + +local y_panelhdr = (function() + for y = 1, 24 do + if is_string_at(3, y, "PID") then + return y + end + end +end)() or 1 + +assert.not_equal(y_panelhdr, 1) + +local x_metercol2 = 41 + +show() + +os.execute("sleep 12345 &") + +local function terminated() + return not os.execute("ps aux | grep -q '\\./[h]top'") +end + +local function running_it(desc, fn) + it(desc, function() + assert(not terminated()) + show() + fn() + assert(not terminated()) + end) +end + +local function check(t) + return t[1], t[2] +end + +local attrs = { + black_on_cyan = 6, + red_on_cyan = 22, + white_on_black = 176, + yellow_on_black = 112, +} + +local function find_selected_y(from) + rt:update() + for y = from or (y_panelhdr + 1), rt:rows() - 1 do + local attr = rt:cellAttr(y-1, 1) + if attr == attrs.black_on_cyan then + return y + end + end + return y_panelhdr + 1 +end + +local function find_command_x() + for x = 1, 80 do + if is_string_at(x, y_panelhdr, "Command") then + return x + end + end + return 64 +end + +local function set_display_option(n) + send("S") + send(curses.KEY_DOWN) + send(curses.KEY_RIGHT) + send(curses.KEY_DOWN, n, "quick") + send("\n") + send(curses.KEY_F10) +end + +describe("htop test suite", function() + + running_it("performs incremental filter", function() + send("\\") + send("x\127bux\127sted") -- test backspace + send("\n") + delay(short_delay) + rt:update() + local pid = (" "..tostring(unistd.getpid())):sub(-5) + local ourpid = check_string_at(1, y_panelhdr + 1, pid) + send("\\") + send(ESC) + send(curses.KEY_F5) + send(curses.KEY_HOME) + delay(short_delay) + rt:update() + local initpid = check_string_at(1, y_panelhdr + 1, " 1") + delay(short_delay) + rt:update() + send(curses.KEY_F5) + assert.equal(check(ourpid)) + assert.equal(check(initpid)) + end) + + running_it("performs incremental search", function() + send(curses.KEY_HOME) + send("/") + send("busted") + local attr = rt:cellAttr(rt:rows() - 1, 30) + delay(short_delay) + local line = find_selected_y() + local pid = (" "..tostring(unistd.getpid())):sub(-5) + assert.equal(attr, attrs.black_on_cyan) + local ourpid = check_string_at(1, line, pid) + send("\n") + send(curses.KEY_HOME) + assert.equal(check(ourpid)) + end) + + running_it("performs pid search", function() + send(curses.KEY_F5) + send(curses.KEY_END) + send("1") + delay(short_delay) + local line = find_selected_y() + local initpid = check_string_at(1, line, " 1") + send(curses.KEY_F5) + assert.equal(check(initpid)) + end) + + + running_it("horizontal scroll", function() + local h_scroll = 20 + send(curses.KEY_F5) + delay(short_delay) + local str1 = string_at(1+h_scroll, y_panelhdr+1, 5) + send(curses.KEY_RIGHT) + delay(short_delay) + local str2 = string_at(1, y_panelhdr+1, 5) + send(curses.KEY_LEFT) + delay(short_delay) + local str3 = string_at(1+h_scroll, y_panelhdr+1, 5) + send(curses.KEY_LEFT) + delay(short_delay) + local str4 = string_at(1+h_scroll, y_panelhdr+1, 5) + send(curses.KEY_F5) + assert.equal(str1, str2) + assert.equal(str2, str3) + assert.equal(str3, str4) + end) + + running_it("kills a process", function() + send(curses.KEY_HOME) + send("\\") + send("sleep 12345") + local attr = rt:cellAttr(rt:rows() - 1, 30) + assert.equal(attr, attrs.black_on_cyan) + send("\n") + delay(short_delay) + rt:update() + local col = find_command_x() + local procname = check_string_at(col, y_panelhdr + 1, "sleep 12345") + send("k") + send("\n") + send("\\") + send(ESC) + delay(short_delay) + assert.equal(check(procname)) + assert.not_equal((os.execute("ps aux | grep -q '[s]leep 12345'")), true) + end) + + running_it("runs strace", function() + send(curses.KEY_HOME) + send("/") + send("busted") + send("\n") + send("s") + delay(long_delay) + send(ESC) + end) + + running_it("runs lsof", function() + send(curses.KEY_HOME) + send("/") + send("busted") + send("\n") + send("l") + delay(long_delay) + send(ESC) + end) + + running_it("performs filtering in lsof", function() + send(curses.KEY_HOME) + send("/") + send("htop") + send("\n") + send("l") + send(curses.KEY_F4) + send("pipe") + delay(long_delay) + local pipefd = check_string_at(1, 3, " 3") + send(ESC) + assert.equal(check(pipefd)) + end) + + running_it("performs search in lsof", function() + send(curses.KEY_HOME) + send("/") + send("htop") + send("\n") + send("l") + send(curses.KEY_F3) + send("pipe") + delay(long_delay) + local line = find_selected_y(3) + local pipefd = check_string_at(1, line, " 3") + send(ESC) + assert.equal(check(pipefd)) + end) + + + running_it("cycles through meter modes in the default meters", function() + send("S") + for _ = 1, 2 do + send(curses.KEY_RIGHT) + for _ = 1, 3 do + send("\n", 4) + send(curses.KEY_DOWN) + end + end + send(ESC) + end) + + running_it("show process of a user", function() + send(curses.KEY_F5) + send("u") + send(curses.KEY_DOWN) + delay(short_delay) + rt:update() + local chosen = string_at(1, y_panelhdr + 2, 9) + send("\n") + send(curses.KEY_HOME) + delay(short_delay) + rt:update() + local shown = string_at(7, y_panelhdr + 1, 9) + send("u") + send("\n") + send(curses.KEY_HOME) + delay(short_delay) + rt:update() + local inituser = string_at(7, y_panelhdr + 1, 9) + send(curses.KEY_F5) + assert.equal(shown, chosen) + assert.equal(inituser, "root ") + end) + + running_it("performs failing search", function() + send(curses.KEY_HOME) + send("/") + send("xxxxxxxxxx") + delay(short_delay) + rt:update() + local attr = rt:cellAttr(rt:rows() - 1, 30) + assert.equal(attr, attrs.red_on_cyan) + send("\n") + end) + + running_it("cycles through search", function() + send(curses.KEY_HOME) + send("/") + send("sh") + local lastpid + local pidpairs = {} + for _ = 1, 3 do + send(curses.KEY_F3) + local line = find_selected_y() + local pid = string_at(1, line, 5) + if lastpid then + pidpairs[#pidpairs + 1] = { lastpid, pid } + lastpid = pid + end + end + send(curses.KEY_HOME) + for _, pair in pairs(pidpairs) do + assert.not_equal(pair[1], pair[2]) + end + end) + + running_it("visits each setup screen", function() + send("S") + send(curses.KEY_DOWN, 3) + send(curses.KEY_F10) + end) + + running_it("adds and removes PPID column", function() + send("S") + send(curses.KEY_DOWN, 3) + send(curses.KEY_RIGHT, 2) + send(curses.KEY_DOWN, 2) + send("\n") + send(curses.KEY_F10) + delay(short_delay) + local ppid = check_string_at(2, y_panelhdr, "PPID") + send("S") + send(curses.KEY_DOWN, 3) + send(curses.KEY_RIGHT, 1) + send(curses.KEY_DC) + send(curses.KEY_F10) + delay(short_delay) + local not_ppid = check_string_at(2, y_panelhdr, "PPID") + assert.equal(check(ppid)) + assert.not_equal(check(not_ppid)) + end) + + running_it("changes CPU affinity for a process", function() + send("a") + send(" \n") + send(ESC) + end) + + running_it("renices for a process", function() + send("/") + send("busted") + send("\n") + local line = find_selected_y() + local before = check_string_at(22, line, " 0") + send(curses.KEY_F8) + delay(short_delay) + local after = check_string_at(22, line, " 1") + assert.equal(check(before)) + assert.equal(check(after)) + end) + + running_it("tries to lower nice for a process", function() + send("/") + send("busted") + send("\n") + local line = find_selected_y() + local before = string_at(22, line, 2) + send(curses.KEY_F7) + delay(short_delay) + local after = string_at(22, line, 2) + assert.equal(before, after) -- no permissions + end) + + running_it("invert sort order", function() + local cpu_col = 45 + send("P") + send("I") + send(curses.KEY_HOME) + delay(short_delay) + local zerocpu = check_string_at(cpu_col, y_panelhdr + 1, " 0.0") + send("I") + delay(short_delay) + local nonzerocpu = check_string_at(cpu_col, y_panelhdr + 1, " 0.0") + assert.equal(check(zerocpu)) + assert.not_equal(check(nonzerocpu)) + end) + + running_it("changes IO priority for a process", function() + send("/") + send("htop") + send("\n") + send("i") + send(curses.KEY_END) + send("\n") + send(ESC) + end) + + running_it("shows help", function() + send(curses.KEY_F1) + send("\n") + set_display_option(9) + send(curses.KEY_F1) + send("\n") + set_display_option(9) + end) + + running_it("moves meters around", function() + send("S") + send(curses.KEY_RIGHT) + send(curses.KEY_UP) + send("\n") + send(curses.KEY_DOWN) + send(curses.KEY_UP) + send(curses.KEY_RIGHT) + send(curses.KEY_RIGHT) + send(curses.KEY_LEFT) + send(curses.KEY_LEFT) + send("\n") + send(curses.KEY_F10) + end) + + local meters = { + { name = "clock", down = 0, string = "Time" }, + { name = "load", down = 2, string = "Load" }, + { name = "battery", down = 7, string = "Battery" }, + { name = "hostname", down = 8, string = "Hostname" }, + { name = "memory", down = 3, string = "Mem" }, + { name = "CPU average", down = 16, string = "Avg" }, + } + + running_it("checks various CPU meters", function() + send("S") + send(curses.KEY_RIGHT, 3) + send(curses.KEY_DOWN, 9, "quick") + for _ = 9, 14 do + send("\n") + send("\n") + send(curses.KEY_DC) + send(curses.KEY_RIGHT) + send(curses.KEY_DOWN) + end + end) + + for _, item in ipairs(meters) do + running_it("adds and removes a "..item.name.." widget", function() + send("S") + send(curses.KEY_RIGHT, 3) + send(curses.KEY_DOWN, item.down) + send("\n") + send(curses.KEY_UP, 4) + send("\n") + send(curses.KEY_F4, 4) -- cycle through meter modes + delay(short_delay) + rt:update() + local with = check_string_at(x_metercol2, 2, item.string) + send(curses.KEY_DC) + delay(short_delay) + local without = check_string_at(x_metercol2, 2, item.string) + send(curses.KEY_F10) + assert.equal(check(with)) + assert.not_equal(check(without)) + end) + end + + running_it("goes through themes", function() + send(curses.KEY_F2) + send(curses.KEY_DOWN, 2) + send(curses.KEY_RIGHT) + for _ = 1, 6 do + send("\n") + send(curses.KEY_DOWN) + end + send(curses.KEY_UP, 6) + send("\n") + send(curses.KEY_F10) + end) + + local display_options = { + { name = "tree view", down = 0 }, + { name = "shadow other user's process", down = 1 }, + { name = "hide kernel threads", down = 2 }, + { name = "hide userland threads", down = 3 }, + { name = "display threads in different color", down = 4 }, + { name = "show custom thread names", down = 5 }, + { name = "highlight basename", down = 6 }, + { name = "highlight large numbers", down = 7 }, + { name = "leave margin around header", down = 8 }, + { name = "use detailed CPU time", down = 9 }, + { name = "count from zero", down = 10 }, + { name = "update process names", down = 11 }, + { name = "guest time in CPU%", down = 12 }, + } + + for _, item in ipairs(display_options) do + running_it("checks display option to "..item.name, function() + for _ = 1, 2 do + set_display_option(item.down) + delay(short_delay) + end + end) + end + + running_it("shows detailed CPU with guest time", function() + for _ = 1, 2 do + send("S") + send(curses.KEY_DOWN) + send(curses.KEY_RIGHT) + send(curses.KEY_DOWN, 9) + send("\n") + send(curses.KEY_DOWN, 3) + send("\n") + send(curses.KEY_LEFT) + send(curses.KEY_UP) + send(curses.KEY_RIGHT) + send(curses.KEY_F4, 4) -- cycle through CPU meter modes + send(curses.KEY_F10) + delay(short_delay) + end + end) + + running_it("expands and collapses tree", function() + send(curses.KEY_F5) -- tree view + send(curses.KEY_HOME) + send(curses.KEY_DOWN) -- second process in the tree + send("-") + send("+") + send(curses.KEY_F5) + end) + + running_it("sets sort key", function() + send(".") + send("\n") + end) + + running_it("tags all children", function() + send(curses.KEY_F5) -- tree view + send(curses.KEY_HOME) -- ensure we're at init + send("c") + local taggedattrs = {} + rt:update() + for y = y_panelhdr + 2, 23 do + table.insert(taggedattrs, rt:cellAttr(y-1, 4)) + end + delay(short_delay) + send("U") + local untaggedattrs = {} + rt:update() + for y = y_panelhdr + 2, 23 do + table.insert(untaggedattrs, rt:cellAttr(y-1, 4)) + end + send(curses.KEY_F5) + + for _, taggedattr in ipairs(taggedattrs) do + assert.equal(attrs.yellow_on_black, taggedattr) + end + for _, untaggedattr in ipairs(untaggedattrs) do + assert.equal(attrs.white_on_black, untaggedattr) + end + end) + + for i = 1, 62 do + running_it("show column "..i, function() + send("S") + send(curses.KEY_END) + send(curses.KEY_RIGHT, 1) + if i > 1 then + send(curses.KEY_DC) + end + send(curses.KEY_RIGHT, 1) + local down = i + while down > 13 do + send(curses.KEY_NPAGE) + down = down - 13 + end + send(curses.KEY_DOWN, down, "quick") + send("\n") + send(curses.KEY_F10) + if i == 62 then + send("S") + send(curses.KEY_END) + send(curses.KEY_RIGHT, 1) + if i > 1 then + send(curses.KEY_DC) + end + send(curses.KEY_F10) + end + end) + end + + it("finally quits", function() + assert(not terminated()) + send("q") + while not terminated() do + unistd.sleep(1) + send("q") + end + assert(terminated()) + if visual then + curses.endwin() + end + os.execute("make lcov && xdg-open lcov/index.html") + end) +end) diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/TraceScreen.c pcp-5.3.2/vendor/github.com/htop-dev/htop/TraceScreen.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/TraceScreen.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/TraceScreen.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,189 @@ +/* +htop - TraceScreen.c +(C) 2005-2006 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "TraceScreen.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" +#include "FunctionBar.h" +#include "Panel.h" +#include "ProvideCurses.h" +#include "XUtils.h" + + +static const char* const TraceScreenFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing ", "Done ", NULL}; + +static const char* const TraceScreenKeys[] = {"F3", "F4", "F8", "F9", "Esc"}; + +static const int TraceScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27}; + +TraceScreen* TraceScreen_new(const Process* process) { + // This initializes all TraceScreen variables to "false" so only default = true ones need to be set below + TraceScreen* this = xCalloc(1, sizeof(TraceScreen)); + Object_setClass(this, Class(TraceScreen)); + this->tracing = true; + FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents); + CRT_disableDelay(); + return (TraceScreen*) InfoScreen_init(&this->super, process, fuBar, LINES - 2, " "); +} + +void TraceScreen_delete(Object* cast) { + TraceScreen* this = (TraceScreen*) cast; + if (this->child > 0) { + kill(this->child, SIGTERM); + waitpid(this->child, NULL, 0); + } + + if (this->strace) { + fclose(this->strace); + } + + CRT_enableDelay(); + free(InfoScreen_done((InfoScreen*)this)); +} + +static void TraceScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Trace of process %d - %s", this->process->pid, Process_getCommand(this->process)); +} + +bool TraceScreen_forkTracer(TraceScreen* this) { + int fdpair[2] = {0, 0}; + + if (pipe(fdpair) == -1) + return false; + + if (fcntl(fdpair[0], F_SETFL, O_NONBLOCK) < 0) + goto err; + + if (fcntl(fdpair[1], F_SETFL, O_NONBLOCK) < 0) + goto err; + + pid_t child = fork(); + if (child == -1) + goto err; + + if (child == 0) { + close(fdpair[0]); + + dup2(fdpair[1], STDOUT_FILENO); + dup2(fdpair[1], STDERR_FILENO); + close(fdpair[1]); + + char buffer[32] = {0}; + xSnprintf(buffer, sizeof(buffer), "%d", this->super.process->pid); + execlp("strace", "strace", "-T", "-tt", "-s", "512", "-p", buffer, NULL); + + // Should never reach here, unless execlp fails ... + const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; + (void)! write(STDERR_FILENO, message, strlen(message)); + + exit(127); + } + + FILE* fd = fdopen(fdpair[0], "r"); + if (!fd) + goto err; + + close(fdpair[1]); + + this->child = child; + this->strace = fd; + return true; + +err: + close(fdpair[1]); + close(fdpair[0]); + return false; +} + +static void TraceScreen_updateTrace(InfoScreen* super) { + TraceScreen* this = (TraceScreen*) super; + char buffer[1025]; + + int fd_strace = fileno(this->strace); + assert(fd_strace != -1); + + fd_set fds; + FD_ZERO(&fds); +// FD_SET(STDIN_FILENO, &fds); + FD_SET(fd_strace, &fds); + + struct timeval tv = { .tv_sec = 0, .tv_usec = 500 }; + int ready = select(fd_strace + 1, &fds, NULL, NULL, &tv); + + size_t nread = 0; + if (ready > 0 && FD_ISSET(fd_strace, &fds)) + nread = fread(buffer, 1, sizeof(buffer) - 1, this->strace); + + if (nread && this->tracing) { + const char* line = buffer; + buffer[nread] = '\0'; + for (size_t i = 0; i < nread; i++) { + if (buffer[i] == '\n') { + buffer[i] = '\0'; + if (this->contLine) { + InfoScreen_appendLine(&this->super, line); + this->contLine = false; + } else { + InfoScreen_addLine(&this->super, line); + } + line = buffer + i + 1; + } + } + if (line < buffer + nread) { + InfoScreen_addLine(&this->super, line); + buffer[nread] = '\0'; + this->contLine = true; + } + if (this->follow) { + Panel_setSelected(this->super.display, Panel_size(this->super.display) - 1); + } + } +} + +static bool TraceScreen_onKey(InfoScreen* super, int ch) { + TraceScreen* this = (TraceScreen*) super; + switch(ch) { + case 'f': + case KEY_F(8): + this->follow = !(this->follow); + if (this->follow) + Panel_setSelected(super->display, Panel_size(super->display)-1); + return true; + case 't': + case KEY_F(9): + this->tracing = !this->tracing; + FunctionBar_setLabel(super->display->defaultBar, KEY_F(9), this->tracing?"Stop Tracing ":"Resume Tracing "); + InfoScreen_draw(this); + return true; + } + this->follow = false; + return false; +} + +const InfoScreenClass TraceScreen_class = { + .super = { + .extends = Class(Object), + .delete = TraceScreen_delete + }, + .draw = TraceScreen_draw, + .onErr = TraceScreen_updateTrace, + .onKey = TraceScreen_onKey, +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/TraceScreen.h pcp-5.3.2/vendor/github.com/htop-dev/htop/TraceScreen.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/TraceScreen.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/TraceScreen.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,37 @@ +#ifndef HEADER_TraceScreen +#define HEADER_TraceScreen +/* +htop - TraceScreen.h +(C) 2005-2006 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include +#include +#include + +#include "InfoScreen.h" +#include "Object.h" +#include "Process.h" + + +typedef struct TraceScreen_ { + InfoScreen super; + bool tracing; + pid_t child; + FILE* strace; + bool contLine; + bool follow; +} TraceScreen; + + +extern const InfoScreenClass TraceScreen_class; + +TraceScreen* TraceScreen_new(const Process* process); + +void TraceScreen_delete(Object* cast); + +bool TraceScreen_forkTracer(TraceScreen* this); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/.travis.yml pcp-5.3.2/vendor/github.com/htop-dev/htop/.travis.yml --- pcp-5.3.1/vendor/github.com/htop-dev/htop/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/.travis.yml 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +language: c + +compiler: + - clang + - gcc + +os: + - freebsd + +script: + - ./autogen.sh + # clang might warn about C11 generic selections in isnan() + - CFLAGS=-Wno-c11-extensions ./configure --enable-werror + - make -k + - CFLAGS=-Wno-c11-extensions make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/Platform.c pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/Platform.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/Platform.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/Platform.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,158 @@ +/* +htop - unsupported/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2015 David C. Hunt +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "unsupported/Platform.h" + +#include + +#include "CPUMeter.h" +#include "ClockMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" +#include "MemoryMeter.h" +#include "SwapMeter.h" +#include "SysArchMeter.h" +#include "TasksMeter.h" +#include "UptimeMeter.h" + + +const SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, +}; + +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); + +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +const MeterClass* const Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &SysArchMeter_class, + &UptimeMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, + &BlankMeter_class, + NULL +}; + +static const char Platform_unsupported[] = "unsupported"; + +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + +int Platform_getUptime() { + return 0; +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + *one = 0; + *five = 0; + *fifteen = 0; +} + +int Platform_getMaxPid() { + return 1; +} + +double Platform_setCPUValues(Meter* this, unsigned int cpu) { + (void) cpu; + + double* v = this->values; + v[CPU_METER_FREQUENCY] = NAN; + v[CPU_METER_TEMPERATURE] = NAN; + + this->curItems = 1; + + return 0.0; +} + +void Platform_setMemoryValues(Meter* this) { + (void) this; +} + +void Platform_setSwapValues(Meter* this) { + (void) this; +} + +bool Process_isThread(const Process* this) { + (void) this; + return false; +} + +char* Platform_getProcessEnv(pid_t pid) { + (void) pid; + return NULL; +} + +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + (void)data; + return false; +} + +bool Platform_getNetworkIO(NetworkIOData* data) { + (void)data; + return false; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + *percent = NAN; + *isOnAC = AC_ERROR; +} + +void Platform_getHostname(char* buffer, size_t size) { + String_safeStrncpy(buffer, Platform_unsupported, size); +} + +void Platform_getRelease(char** string) { + *string = xStrdup(Platform_unsupported); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/Platform.h pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/Platform.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/Platform.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/Platform.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,91 @@ +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - unsupported/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2015 David C. Hunt +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Action.h" +#include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "NetworkIOMeter.h" +#include "ProcessLocksScreen.h" +#include "SignalsPanel.h" +#include "generic/gettime.h" +#include "unsupported/UnsupportedProcess.h" + + +extern const SignalItem Platform_signals[]; + +extern const unsigned int Platform_numberOfSignals; + +extern const ProcessField Platform_defaultFields[]; + +extern const MeterClass* const Platform_meterTypes[]; + +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); + +int Platform_getUptime(void); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(void); + +double Platform_setCPUValues(Meter* this, unsigned int cpu); + +void Platform_setMemoryValues(Meter* this); + +void Platform_setSwapValues(Meter* this); + +bool Process_isThread(const Process* this); + +char* Platform_getProcessEnv(pid_t pid); + +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(NetworkIOData* data); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + +void Platform_getHostname(char* buffer, size_t size); + +void Platform_getRelease(char** string); + +#define PLATFORM_LONG_OPTIONS + +static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { } + +static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) { + return false; +} + +static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) { + Generic_gettime_realtime(tv, msec); +} + +static inline void Platform_gettime_monotonic(uint64_t* msec) { + Generic_gettime_monotonic(msec); +} + +static inline Hashtable* Platform_dynamicMeters(void) { + return NULL; +} + +static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { } + +static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { } + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/ProcessField.h pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/ProcessField.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/ProcessField.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/ProcessField.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_UnsupportedProcessField +#define HEADER_UnsupportedProcessField +/* +htop - unsupported/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + // End of list + + +#endif /* HEADER_UnsupportedProcessField */ diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.c pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,105 @@ +/* +htop - UnsupportedProcess.c +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "unsupported/UnsupportedProcess.h" + +#include + +#include "CRT.h" +#include "Process.h" + + +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { + [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, + [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, + [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging)", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, + [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, + [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true,}, + [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, }, + [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, + [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, + [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, + [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, }, + [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, + [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, }, + [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, + [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, + [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, + [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, + [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, +}; + +Process* UnsupportedProcess_new(const Settings* settings) { + Process* this = xCalloc(1, sizeof(UnsupportedProcess)); + Object_setClass(this, Class(UnsupportedProcess)); + Process_init(this, settings); + return this; +} + +void Process_delete(Object* cast) { + Process* super = (Process*) cast; + Process_done(super); + // free platform-specific fields here + free(cast); +} + +static void UnsupportedProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const UnsupportedProcess* up = (const UnsupportedProcess*) this; + bool coloring = this->settings->highlightMegabytes; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + size_t n = sizeof(buffer) - 1; + + (void) up; + (void) coloring; + (void) n; + + switch (field) { + /* Add platform specific fields */ + default: + Process_writeField(this, str, field); + return; + } + RichString_appendWide(str, attr, buffer); +} + +static int UnsupportedProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const UnsupportedProcess* p1 = (const UnsupportedProcess*)v1; + const UnsupportedProcess* p2 = (const UnsupportedProcess*)v2; + + (void) p1; + (void) p2; + + switch (key) { + /* Add platform specific fields */ + default: + return Process_compareByKey_Base(v1, v2, key); + } +} + +const ProcessClass UnsupportedProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = Process_compare + }, + .writeField = UnsupportedProcess_writeField, + .getCommandStr = NULL, + .compareByKey = UnsupportedProcess_compareByKey +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.h pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcess.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,28 @@ +#ifndef HEADER_UnsupportedProcess +#define HEADER_UnsupportedProcess +/* +htop - UnsupportedProcess.h +(C) 2015 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Settings.h" + + +typedef struct UnsupportedProcess_ { + Process super; + + /* Add platform specific fields */ +} UnsupportedProcess; + + +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; + +Process* UnsupportedProcess_new(const Settings* settings); + +void Process_delete(Object* cast); + +extern const ProcessClass UnsupportedProcess_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.c pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.c 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,90 @@ +/* +htop - UnsupportedProcessList.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "UnsupportedProcessList.h" + +#include +#include + +#include "ProcessList.h" +#include "UnsupportedProcess.h" + + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + ProcessList* this = xCalloc(1, sizeof(ProcessList)); + ProcessList_init(this, Class(Process), usersTable, dynamicMeters, pidMatchList, userId); + + this->cpuCount = 1; + + return this; +} + +void ProcessList_delete(ProcessList* this) { + ProcessList_done(this); + free(this); +} + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { + + // in pause mode only gather global data for meters (CPU/memory/...) + if (pauseProcessUpdate) { + return; + } + + bool preExisting = true; + Process* proc; + + proc = ProcessList_getProcess(super, 1, &preExisting, UnsupportedProcess_new); + + /* Empty values */ + proc->time = proc->time + 10; + proc->pid = 1; + proc->ppid = 1; + proc->tgid = 0; + + Process_updateComm(proc, "commof16char"); + Process_updateCmdline(proc, "", 0, 0); + Process_updateExe(proc, "/path/to/executable"); + + if (proc->settings->flags & PROCESS_FLAG_CWD) { + proc->procCwd = "/current/working/directory"; + } + + proc->updated = true; + + proc->state = 'R'; + proc->isKernelThread = false; + proc->isUserlandThread = false; + proc->show = true; /* Reflected in proc->settings-> "hideXXX" really */ + proc->pgrp = 0; + proc->session = 0; + proc->tty_nr = 0; + proc->tty_name = NULL; + proc->tpgid = 0; + proc->processor = 0; + + proc->percent_cpu = 2.5; + proc->percent_mem = 2.5; + + proc->st_uid = 0; + proc->user = "nobody"; /* Update whenever proc->st_uid is changed */ + + proc->priority = 0; + proc->nice = 0; + proc->nlwp = 1; + proc->starttime_ctime = 1433116800; // Jun 01, 2015 + Process_fillStarttimeBuffer(proc); + + proc->m_virt = 100; + proc->m_resident = 100; + + proc->minflt = 20; + proc->majflt = 20; + + if (!preExisting) + ProcessList_add(super, proc); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.h pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/unsupported/UnsupportedProcessList.h 2021-07-30 04:05:09.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_UnsupportedProcessList +#define HEADER_UnsupportedProcessList +/* +htop - UnsupportedProcessList.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "ProcessList.h" + + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/UptimeMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/UptimeMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/UptimeMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/UptimeMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,60 @@ +/* +htop - UptimeMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "UptimeMeter.h" + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "XUtils.h" + + +static const int UptimeMeter_attributes[] = { + UPTIME +}; + +static void UptimeMeter_updateValues(Meter* this) { + int totalseconds = Platform_getUptime(); + if (totalseconds == -1) { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "(unknown)"); + return; + } + int seconds = totalseconds % 60; + int minutes = (totalseconds / 60) % 60; + int hours = (totalseconds / 3600) % 24; + int days = (totalseconds / 86400); + this->values[0] = days; + if (days > this->total) { + this->total = days; + } + char daysbuf[32]; + if (days > 100) { + xSnprintf(daysbuf, sizeof(daysbuf), "%d days(!), ", days); + } else if (days > 1) { + xSnprintf(daysbuf, sizeof(daysbuf), "%d days, ", days); + } else if (days == 1) { + xSnprintf(daysbuf, sizeof(daysbuf), "1 day, "); + } else { + daysbuf[0] = '\0'; + } + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%02d:%02d:%02d", daysbuf, hours, minutes, seconds); +} + +const MeterClass UptimeMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete + }, + .updateValues = UptimeMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 100.0, + .attributes = UptimeMeter_attributes, + .name = "Uptime", + .uiName = "Uptime", + .caption = "Uptime: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/UptimeMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/UptimeMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/UptimeMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/UptimeMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,15 @@ +#ifndef HEADER_UptimeMeter +#define HEADER_UptimeMeter +/* +htop - UptimeMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Meter.h" + + +extern const MeterClass UptimeMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/UsersTable.c pcp-5.3.2/vendor/github.com/htop-dev/htop/UsersTable.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/UsersTable.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/UsersTable.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,46 @@ +/* +htop - UsersTable.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "UsersTable.h" + +#include +#include +#include +#include + +#include "XUtils.h" + + +UsersTable* UsersTable_new() { + UsersTable* this; + this = xMalloc(sizeof(UsersTable)); + this->users = Hashtable_new(10, true); + return this; +} + +void UsersTable_delete(UsersTable* this) { + Hashtable_delete(this->users); + free(this); +} + +char* UsersTable_getRef(UsersTable* this, unsigned int uid) { + char* name = Hashtable_get(this->users, uid); + if (name == NULL) { + const struct passwd* userData = getpwuid(uid); + if (userData != NULL) { + name = xStrdup(userData->pw_name); + Hashtable_put(this->users, uid, name); + } + } + return name; +} + +inline void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData) { + Hashtable_foreach(this->users, f, userData); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/UsersTable.h pcp-5.3.2/vendor/github.com/htop-dev/htop/UsersTable.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/UsersTable.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/UsersTable.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,25 @@ +#ifndef HEADER_UsersTable +#define HEADER_UsersTable +/* +htop - UsersTable.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Hashtable.h" + + +typedef struct UsersTable_ { + Hashtable* users; +} UsersTable; + +UsersTable* UsersTable_new(void); + +void UsersTable_delete(UsersTable* this); + +char* UsersTable_getRef(UsersTable* this, unsigned int uid); + +void UsersTable_foreach(UsersTable* this, Hashtable_PairFunction f, void* userData); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Vector.c pcp-5.3.2/vendor/github.com/htop-dev/htop/Vector.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Vector.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Vector.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,340 @@ +/* +htop - Vector.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Vector.h" + +#include +#include +#include + +#include "XUtils.h" + + +Vector* Vector_new(const ObjectClass* type, bool owner, int size) { + Vector* this; + + if (size == DEFAULT_SIZE) { + size = 10; + } + + assert(size > 0); + this = xMalloc(sizeof(Vector)); + this->growthRate = size; + this->array = (Object**) xCalloc(size, sizeof(Object*)); + this->arraySize = size; + this->items = 0; + this->type = type; + this->owner = owner; + return this; +} + +void Vector_delete(Vector* this) { + if (this->owner) { + for (int i = 0; i < this->items; i++) { + if (this->array[i]) { + Object_delete(this->array[i]); + } + } + } + free(this->array); + free(this); +} + +#ifndef NDEBUG + +static bool Vector_isConsistent(const Vector* this) { + assert(this->items <= this->arraySize); + + if (this->owner) { + for (int i = 0; i < this->items; i++) { + if (!this->array[i]) { + return false; + } + } + } + + return true; +} + +unsigned int Vector_count(const Vector* this) { + unsigned int items = 0; + for (int i = 0; i < this->items; i++) { + if (this->array[i]) { + items++; + } + } + assert(items == (unsigned int)this->items); + return items; +} + +Object* Vector_get(const Vector* this, int idx) { + assert(idx >= 0 && idx < this->items); + assert(this->array[idx]); + assert(Object_isA(this->array[idx], this->type)); + return this->array[idx]; +} + +int Vector_size(const Vector* this) { + assert(Vector_isConsistent(this)); + return this->items; +} + +#endif /* NDEBUG */ + +void Vector_prune(Vector* this) { + assert(Vector_isConsistent(this)); + if (this->owner) { + for (int i = 0; i < this->items; i++) + if (this->array[i]) { + Object_delete(this->array[i]); + //this->array[i] = NULL; + } + } + this->items = 0; +} + +//static int comparisons = 0; + +static void swap(Object** array, int indexA, int indexB) { + assert(indexA >= 0); + assert(indexB >= 0); + Object* tmp = array[indexA]; + array[indexA] = array[indexB]; + array[indexB] = tmp; +} + +static int partition(Object** array, int left, int right, int pivotIndex, Object_Compare compare) { + const Object* pivotValue = array[pivotIndex]; + swap(array, pivotIndex, right); + int storeIndex = left; + for (int i = left; i < right; i++) { + //comparisons++; + if (compare(array[i], pivotValue) <= 0) { + swap(array, i, storeIndex); + storeIndex++; + } + } + swap(array, storeIndex, right); + return storeIndex; +} + +static void quickSort(Object** array, int left, int right, Object_Compare compare) { + if (left >= right) + return; + + int pivotIndex = (left + right) / 2; + int pivotNewIndex = partition(array, left, right, pivotIndex, compare); + quickSort(array, left, pivotNewIndex - 1, compare); + quickSort(array, pivotNewIndex + 1, right, compare); +} + +// If I were to use only one sorting algorithm for both cases, it would probably be this one: +/* + +static void combSort(Object** array, int left, int right, Object_Compare compare) { + int gap = right - left; + bool swapped = true; + while ((gap > 1) || swapped) { + if (gap > 1) { + gap = (int)((double)gap / 1.247330950103979); + } + swapped = false; + for (int i = left; gap + i <= right; i++) { + comparisons++; + if (compare(array[i], array[i+gap]) > 0) { + swap(array, i, i+gap); + swapped = true; + } + } + } +} + +*/ + +static void insertionSort(Object** array, int left, int right, Object_Compare compare) { + for (int i = left + 1; i <= right; i++) { + Object* t = array[i]; + int j = i - 1; + while (j >= left) { + //comparisons++; + if (compare(array[j], t) <= 0) + break; + + array[j + 1] = array[j]; + j--; + } + array[j + 1] = t; + } +} + +void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare) { + assert(compare); + assert(Vector_isConsistent(this)); + quickSort(this->array, 0, this->items - 1, compare); + assert(Vector_isConsistent(this)); +} + +void Vector_insertionSort(Vector* this) { + assert(this->type->compare); + assert(Vector_isConsistent(this)); + insertionSort(this->array, 0, this->items - 1, this->type->compare); + assert(Vector_isConsistent(this)); +} + +static void Vector_checkArraySize(Vector* this) { + assert(Vector_isConsistent(this)); + if (this->items >= this->arraySize) { + //int i; + //i = this->arraySize; + this->arraySize = this->items + this->growthRate; + this->array = (Object**) xRealloc(this->array, sizeof(Object*) * this->arraySize); + //for (; i < this->arraySize; i++) + // this->array[i] = NULL; + } + assert(Vector_isConsistent(this)); +} + +void Vector_insert(Vector* this, int idx, void* data_) { + Object* data = data_; + assert(idx >= 0); + assert(Object_isA(data, this->type)); + assert(Vector_isConsistent(this)); + + if (idx > this->items) { + idx = this->items; + } + + Vector_checkArraySize(this); + //assert(this->array[this->items] == NULL); + if (idx < this->items) { + memmove(&this->array[idx + 1], &this->array[idx], (this->items - idx) * sizeof(this->array[0])); + } + this->array[idx] = data; + this->items++; + assert(Vector_isConsistent(this)); +} + +Object* Vector_take(Vector* this, int idx) { + assert(idx >= 0 && idx < this->items); + assert(Vector_isConsistent(this)); + Object* removed = this->array[idx]; + assert(removed); + this->items--; + if (idx < this->items) { + memmove(&this->array[idx], &this->array[idx + 1], (this->items - idx) * sizeof(this->array[0])); + } + //this->array[this->items] = NULL; + assert(Vector_isConsistent(this)); + return removed; +} + +Object* Vector_remove(Vector* this, int idx) { + Object* removed = Vector_take(this, idx); + if (this->owner) { + Object_delete(removed); + return NULL; + } else { + return removed; + } +} + +void Vector_moveUp(Vector* this, int idx) { + assert(idx >= 0 && idx < this->items); + assert(Vector_isConsistent(this)); + + if (idx == 0) + return; + + Object* temp = this->array[idx]; + this->array[idx] = this->array[idx - 1]; + this->array[idx - 1] = temp; +} + +void Vector_moveDown(Vector* this, int idx) { + assert(idx >= 0 && idx < this->items); + assert(Vector_isConsistent(this)); + + if (idx == this->items - 1) + return; + + Object* temp = this->array[idx]; + this->array[idx] = this->array[idx + 1]; + this->array[idx + 1] = temp; +} + +void Vector_set(Vector* this, int idx, void* data_) { + Object* data = data_; + assert(idx >= 0); + assert(Object_isA(data, this->type)); + assert(Vector_isConsistent(this)); + + Vector_checkArraySize(this); + if (idx >= this->items) { + this->items = idx + 1; + } else { + if (this->owner) { + Object* removed = this->array[idx]; + assert (removed != NULL); + Object_delete(removed); + } + } + this->array[idx] = data; + assert(Vector_isConsistent(this)); +} + +/* + +static void Vector_merge(Vector* this, Vector* v2) { + int i; + assert(Vector_isConsistent(this)); + + for (i = 0; i < v2->items; i++) + Vector_add(this, v2->array[i]); + v2->items = 0; + Vector_delete(v2); + assert(Vector_isConsistent(this)); +} + +*/ + +void Vector_add(Vector* this, void* data_) { + Object* data = data_; + assert(Object_isA(data, this->type)); + assert(Vector_isConsistent(this)); + int i = this->items; + Vector_set(this, this->items, data); + assert(this->items == i + 1); (void)(i); + assert(Vector_isConsistent(this)); +} + +int Vector_indexOf(const Vector* this, const void* search_, Object_Compare compare) { + const Object* search = search_; + assert(Object_isA(search, this->type)); + assert(compare); + assert(Vector_isConsistent(this)); + for (int i = 0; i < this->items; i++) { + const Object* o = this->array[i]; + assert(o); + if (compare(search, o) == 0) { + return i; + } + } + return -1; +} + +void Vector_splice(Vector* this, Vector* from) { + assert(Vector_isConsistent(this)); + assert(Vector_isConsistent(from)); + assert(!(this->owner && from->owner)); + + int olditems = this->items; + this->items += from->items; + Vector_checkArraySize(this); + for (int j = 0; j < from->items; j++) { + this->array[olditems + j] = from->array[j]; + } +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/Vector.h pcp-5.3.2/vendor/github.com/htop-dev/htop/Vector.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/Vector.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/Vector.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,81 @@ +#ifndef HEADER_Vector +#define HEADER_Vector +/* +htop - Vector.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Object.h" + +#include + + +#ifndef DEFAULT_SIZE +#define DEFAULT_SIZE (-1) +#endif + +typedef struct Vector_ { + Object** array; + const ObjectClass* type; + int arraySize; + int growthRate; + int items; + bool owner; +} Vector; + +Vector* Vector_new(const ObjectClass* type, bool owner, int size); + +void Vector_delete(Vector* this); + +void Vector_prune(Vector* this); + +void Vector_quickSortCustomCompare(Vector* this, Object_Compare compare); +static inline void Vector_quickSort(Vector* this) { + Vector_quickSortCustomCompare(this, this->type->compare); +} + +void Vector_insertionSort(Vector* this); + +void Vector_insert(Vector* this, int idx, void* data_); + +Object* Vector_take(Vector* this, int idx); + +Object* Vector_remove(Vector* this, int idx); + +void Vector_moveUp(Vector* this, int idx); + +void Vector_moveDown(Vector* this, int idx); + +void Vector_set(Vector* this, int idx, void* data_); + +#ifndef NDEBUG + +Object* Vector_get(const Vector* this, int idx); +int Vector_size(const Vector* this); +unsigned int Vector_count(const Vector* this); + +#else /* NDEBUG */ + +static inline Object* Vector_get(const Vector* this, int idx) { + return this->array[idx]; +} + +static inline int Vector_size(const Vector* this) { + return this->items; +} + +#endif /* NDEBUG */ + +static inline const ObjectClass* Vector_type(const Vector* this) { + return this->type; +} + +void Vector_add(Vector* this, void* data_); + +int Vector_indexOf(const Vector* this, const void* search_, Object_Compare compare); + +void Vector_splice(Vector* this, Vector* from); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/XUtils.c pcp-5.3.2/vendor/github.com/htop-dev/htop/XUtils.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/XUtils.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/XUtils.c 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,305 @@ +/* +htop - StringUtils.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include "XUtils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CRT.h" + + +void fail() { + CRT_done(); + abort(); + + _exit(1); // Should never reach here +} + +void* xMalloc(size_t size) { + assert(size > 0); + void* data = malloc(size); + if (!data) { + fail(); + } + return data; +} + +void* xMallocArray(size_t nmemb, size_t size) { + assert(nmemb > 0); + assert(size > 0); + if (SIZE_MAX / nmemb < size) { + fail(); + } + return xMalloc(nmemb * size); +} + +void* xCalloc(size_t nmemb, size_t size) { + assert(nmemb > 0); + assert(size > 0); + if (SIZE_MAX / nmemb < size) { + fail(); + } + void* data = calloc(nmemb, size); + if (!data) { + fail(); + } + return data; +} + +void* xRealloc(void* ptr, size_t size) { + assert(size > 0); + void* data = realloc(ptr, size); // deepcode ignore MemoryLeakOnRealloc: this goes to fail() + if (!data) { + free(ptr); + fail(); + } + return data; +} + +void* xReallocArray(void* ptr, size_t nmemb, size_t size) { + assert(nmemb > 0); + assert(size > 0); + if (SIZE_MAX / nmemb < size) { + fail(); + } + return xRealloc(ptr, nmemb * size); +} + +char* String_cat(const char* s1, const char* s2) { + const size_t l1 = strlen(s1); + const size_t l2 = strlen(s2); + char* out = xMalloc(l1 + l2 + 1); + memcpy(out, s1, l1); + memcpy(out + l1, s2, l2); + out[l1 + l2] = '\0'; + return out; +} + +char* String_trim(const char* in) { + while (in[0] == ' ' || in[0] == '\t' || in[0] == '\n') { + in++; + } + + size_t len = strlen(in); + while (len > 0 && (in[len - 1] == ' ' || in[len - 1] == '\t' || in[len - 1] == '\n')) { + len--; + } + + return xStrndup(in, len); +} + +char** String_split(const char* s, char sep, size_t* n) { + const unsigned int rate = 10; + char** out = xCalloc(rate, sizeof(char*)); + size_t ctr = 0; + unsigned int blocks = rate; + const char* where; + while ((where = strchr(s, sep)) != NULL) { + size_t size = (size_t)(where - s); + out[ctr] = xStrndup(s, size); + ctr++; + if (ctr == blocks) { + blocks += rate; + out = (char**) xRealloc(out, sizeof(char*) * blocks); + } + s += size + 1; + } + if (s[0] != '\0') { + out[ctr] = xStrdup(s); + ctr++; + } + out = xRealloc(out, sizeof(char*) * (ctr + 1)); + out[ctr] = NULL; + + if (n) + *n = ctr; + + return out; +} + +void String_freeArray(char** s) { + if (!s) { + return; + } + for (size_t i = 0; s[i] != NULL; i++) { + free(s[i]); + } + free(s); +} + +char* String_getToken(const char* line, const unsigned short int numMatch) { + const size_t len = strlen(line); + char inWord = 0; + unsigned short int count = 0; + char match[50]; + + size_t foundCount = 0; + + for (size_t i = 0; i < len; i++) { + char lastState = inWord; + inWord = line[i] == ' ' ? 0 : 1; + + if (lastState == 0 && inWord == 1) + count++; + + if (inWord == 1) { + if (count == numMatch && line[i] != ' ' && line[i] != '\0' && line[i] != '\n' && line[i] != (char)EOF) { + match[foundCount] = line[i]; + foundCount++; + } + } + } + + match[foundCount] = '\0'; + return xStrdup(match); +} + +char* String_readLine(FILE* fd) { + const unsigned int step = 1024; + unsigned int bufSize = step; + char* buffer = xMalloc(step + 1); + char* at = buffer; + for (;;) { + const char* ok = fgets(at, step + 1, fd); + if (!ok) { + free(buffer); + return NULL; + } + char* newLine = strrchr(at, '\n'); + if (newLine) { + *newLine = '\0'; + return buffer; + } else { + if (feof(fd)) { + return buffer; + } + } + bufSize += step; + buffer = xRealloc(buffer, bufSize + 1); + at = buffer + bufSize - step; + } +} + +size_t String_safeStrncpy(char* restrict dest, const char* restrict src, size_t size) { + assert(size > 0); + + size_t i = 0; + for (; i < size - 1 && src[i]; i++) + dest[i] = src[i]; + + dest[i] = '\0'; + + return i; +} + +int xAsprintf(char** strp, const char* fmt, ...) { + va_list vl; + va_start(vl, fmt); + int r = vasprintf(strp, fmt, vl); + va_end(vl); + + if (r < 0 || !*strp) { + fail(); + } + + return r; +} + +int xSnprintf(char* buf, size_t len, const char* fmt, ...) { + va_list vl; + va_start(vl, fmt); + int n = vsnprintf(buf, len, fmt, vl); + va_end(vl); + + if (n < 0 || (size_t)n >= len) { + fail(); + } + + return n; +} + +char* xStrdup(const char* str) { + char* data = strdup(str); + if (!data) { + fail(); + } + return data; +} + +void free_and_xStrdup(char** ptr, const char* str) { + if (*ptr && String_eq(*ptr, str)) + return; + + free(*ptr); + *ptr = xStrdup(str); +} + +char* xStrndup(const char* str, size_t len) { + char* data = strndup(str, len); + if (!data) { + fail(); + } + return data; +} + +static ssize_t readfd_internal(int fd, void* buffer, size_t count) { + if (!count) { + close(fd); + return -EINVAL; + } + + ssize_t alreadyRead = 0; + count--; // reserve one for null-terminator + + for (;;) { + ssize_t res = read(fd, buffer, count); + if (res == -1) { + if (errno == EINTR) + continue; + + close(fd); + return -errno; + } + + if (res > 0) { + buffer = ((char*)buffer) + res; + count -= (size_t)res; + alreadyRead += res; + } + + if (count == 0 || res == 0) { + close(fd); + *((char*)buffer) = '\0'; + return alreadyRead; + } + } +} + +ssize_t xReadfile(const char* pathname, void* buffer, size_t count) { + int fd = open(pathname, O_RDONLY); + if (fd < 0) + return -errno; + + return readfd_internal(fd, buffer, count); +} + +ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count) { + int fd = Compat_openat(dirfd, pathname, O_RDONLY); + if (fd < 0) + return -errno; + + return readfd_internal(fd, buffer, count); +} diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/XUtils.h pcp-5.3.2/vendor/github.com/htop-dev/htop/XUtils.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/XUtils.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/XUtils.h 2021-07-30 04:05:07.000000000 +0000 @@ -0,0 +1,79 @@ +#ifndef HEADER_XUtils +#define HEADER_XUtils +/* +htop - StringUtils.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "config.h" // IWYU pragma: keep + +#include +#include +#include // IWYU pragma: keep +#include // IWYU pragma: keep +#include + +#include "Compat.h" +#include "Macros.h" + + +void fail(void) ATTR_NORETURN; + +void* xMalloc(size_t size) ATTR_ALLOC_SIZE1(1) ATTR_MALLOC; + +void* xMallocArray(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC; + +void* xCalloc(size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(1, 2) ATTR_MALLOC; + +void* xRealloc(void* ptr, size_t size) ATTR_ALLOC_SIZE1(2); + +void* xReallocArray(void* ptr, size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(2, 3); + +/* + * String_startsWith gives better performance if strlen(match) can be computed + * at compile time (e.g. when they are immutable string literals). :) + */ +static inline bool String_startsWith(const char* s, const char* match) { + return strncmp(s, match, strlen(match)) == 0; +} + +static inline bool String_contains_i(const char* s1, const char* s2) { + return strcasestr(s1, s2) != NULL; +} + +static inline bool String_eq(const char* s1, const char* s2) { + return strcmp(s1, s2) == 0; +} + +char* String_cat(const char* s1, const char* s2) ATTR_MALLOC; + +char* String_trim(const char* in) ATTR_MALLOC; + +char** String_split(const char* s, char sep, size_t* n); + +void String_freeArray(char** s); + +char* String_getToken(const char* line, unsigned short int numMatch) ATTR_MALLOC; + +char* String_readLine(FILE* fd) ATTR_MALLOC; + +/* Always null-terminates dest. Caller must pass a strictly positive size. */ +size_t String_safeStrncpy(char* restrict dest, const char* restrict src, size_t size); + +ATTR_FORMAT(printf, 2, 3) +int xAsprintf(char** strp, const char* fmt, ...); + +ATTR_FORMAT(printf, 3, 4) +int xSnprintf(char* buf, size_t len, const char* fmt, ...); + +char* xStrdup(const char* str) ATTR_NONNULL ATTR_MALLOC; +void free_and_xStrdup(char** ptr, const char* str); + +char* xStrndup(const char* str, size_t len) ATTR_NONNULL ATTR_MALLOC; + +ssize_t xReadfile(const char* pathname, void* buffer, size_t count); +ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count); + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,98 @@ +/* +htop - ZfsArcMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "zfs/ZfsArcMeter.h" + +#include + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" + +#include "zfs/ZfsArcStats.h" + + +static const int ZfsArcMeter_attributes[] = { + ZFS_MFU, ZFS_MRU, ZFS_ANON, ZFS_HEADER, ZFS_OTHER +}; + +void ZfsArcMeter_readStats(Meter* this, const ZfsArcStats* stats) { + this->total = stats->max; + this->values[0] = stats->MFU; + this->values[1] = stats->MRU; + this->values[2] = stats->anon; + this->values[3] = stats->header; + this->values[4] = stats->other; + + // "Hide" the last value so it can + // only be accessed by index and is not + // displayed by the Bar or Graph style + this->curItems = 5; + this->values[5] = stats->size; +} + +static void ZfsArcMeter_updateValues(Meter* this) { + char* buffer = this->txtBuffer; + size_t size = sizeof(this->txtBuffer); + int written; + Platform_setZfsArcValues(this); + + written = Meter_humanUnit(buffer, this->values[5], size); + METER_BUFFER_CHECK(buffer, size, written); + + METER_BUFFER_APPEND_CHR(buffer, size, '/'); + + Meter_humanUnit(buffer, this->total, size); +} + +static void ZfsArcMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + + if (this->values[5] > 0) { + char buffer[50]; + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + Meter_humanUnit(buffer, this->values[5], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Used:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " MFU:"); + RichString_appendAscii(out, CRT_colors[ZFS_MFU], buffer); + Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " MRU:"); + RichString_appendAscii(out, CRT_colors[ZFS_MRU], buffer); + Meter_humanUnit(buffer, this->values[2], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Anon:"); + RichString_appendAscii(out, CRT_colors[ZFS_ANON], buffer); + Meter_humanUnit(buffer, this->values[3], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Hdr:"); + RichString_appendAscii(out, CRT_colors[ZFS_HEADER], buffer); + Meter_humanUnit(buffer, this->values[4], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Oth:"); + RichString_appendAscii(out, CRT_colors[ZFS_OTHER], buffer); + } else { + RichString_writeAscii(out, CRT_colors[METER_TEXT], " "); + RichString_appendAscii(out, CRT_colors[FAILED_READ], "Unavailable"); + } +} + +const MeterClass ZfsArcMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = ZfsArcMeter_display, + }, + .updateValues = ZfsArcMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 6, + .total = 100.0, + .attributes = ZfsArcMeter_attributes, + .name = "ZFSARC", + .uiName = "ZFS ARC", + .caption = "ARC: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsArcMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_ZfsArcMeter +#define HEADER_ZfsArcMeter +/* +htop - ZfsArcMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "zfs/ZfsArcStats.h" + +#include "Meter.h" + + +void ZfsArcMeter_readStats(Meter* this, const ZfsArcStats* stats); + +extern const MeterClass ZfsArcMeter_class; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsArcStats.h pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsArcStats.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsArcStats.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsArcStats.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,24 @@ +#ifndef HEADER_ZfsArcStats +#define HEADER_ZfsArcStats +/* +htop - ZfsArcStats.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +typedef struct ZfsArcStats_ { + int enabled; + int isCompressed; + unsigned long long int max; + unsigned long long int size; + unsigned long long int MFU; + unsigned long long int MRU; + unsigned long long int anon; + unsigned long long int header; + unsigned long long int other; + unsigned long long int compressed; + unsigned long long int uncompressed; +} ZfsArcStats; + +#endif diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.c pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.c --- pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.c 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.c 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,87 @@ +/* +htop - ZfsCompressedArcMeter.c +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "zfs/ZfsCompressedArcMeter.h" + +#include + +#include "CRT.h" +#include "Meter.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" +#include "XUtils.h" +#include "zfs/ZfsArcStats.h" + + +static const int ZfsCompressedArcMeter_attributes[] = { + ZFS_COMPRESSED +}; + +void ZfsCompressedArcMeter_readStats(Meter* this, const ZfsArcStats* stats) { + if ( stats->isCompressed ) { + this->total = stats->uncompressed; + this->values[0] = stats->compressed; + } else { + // For uncompressed ARC, report 1:1 ratio + this->total = stats->size; + this->values[0] = stats->size; + } +} + +static int ZfsCompressedArcMeter_printRatioString(const Meter* this, char* buffer, size_t size) { + if (this->values[0] > 0) { + return xSnprintf(buffer, size, "%.2f:1", this->total / this->values[0]); + } + + return xSnprintf(buffer, size, "N/A"); +} + +static void ZfsCompressedArcMeter_updateValues(Meter* this) { + Platform_setZfsCompressedArcValues(this); + + ZfsCompressedArcMeter_printRatioString(this, this->txtBuffer, sizeof(this->txtBuffer)); +} + +static void ZfsCompressedArcMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + + if (this->values[0] > 0) { + char buffer[50]; + int len; + + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Uncompressed, "); + Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Compressed, "); + len = ZfsCompressedArcMeter_printRatioString(this, buffer, sizeof(buffer)); + RichString_appendnAscii(out, CRT_colors[ZFS_RATIO], buffer, len); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " Ratio"); + } else { + RichString_writeAscii(out, CRT_colors[METER_TEXT], " "); + RichString_appendAscii(out, CRT_colors[FAILED_READ], "Compression Unavailable"); + } +} + +const MeterClass ZfsCompressedArcMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = ZfsCompressedArcMeter_display, + }, + .updateValues = ZfsCompressedArcMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 1, + .total = 100.0, + .attributes = ZfsCompressedArcMeter_attributes, + .name = "ZFSCARC", + .uiName = "ZFS CARC", + .description = "ZFS CARC: Compressed ARC statistics", + .caption = "ARC: " +}; diff -Nru pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.h pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.h --- pcp-5.3.1/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.h 1970-01-01 00:00:00.000000000 +0000 +++ pcp-5.3.2/vendor/github.com/htop-dev/htop/zfs/ZfsCompressedArcMeter.h 2021-06-15 01:03:49.000000000 +0000 @@ -0,0 +1,19 @@ +#ifndef HEADER_ZfsCompressedArcMeter +#define HEADER_ZfsCompressedArcMeter +/* +htop - ZfsCompressedArcMeter.h +(C) 2004-2011 Hisham H. Muhammad +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + +#include "zfs/ZfsArcStats.h" + +#include "Meter.h" + + +void ZfsCompressedArcMeter_readStats(Meter* this, const ZfsArcStats* stats); + +extern const MeterClass ZfsCompressedArcMeter_class; + +#endif diff -Nru pcp-5.3.1/VERSION.pcp pcp-5.3.2/VERSION.pcp --- pcp-5.3.1/VERSION.pcp 2021-06-15 00:58:16.000000000 +0000 +++ pcp-5.3.2/VERSION.pcp 2021-06-15 01:03:49.000000000 +0000 @@ -3,5 +3,5 @@ # PACKAGE_MAJOR=5 PACKAGE_MINOR=3 -PACKAGE_REVISION=1 +PACKAGE_REVISION=2 PACKAGE_BUILD=1

- hide/show program path. + + , - quit program. + + - do nothing. + + - enter STrace screen. + + , - toggle between Tree and Sorted view, update F5 in FunctionBar, follow process + + - enter User screen. + + , , , , - do nothing. + + , - do nothing. + + , , - enter Setup screen. + + , - do nothing. + + - follow process. + + - do nothing. + + - toggle show/hide userland threads. + + - invert sort order. + + - do nothing. + + - toggle show/hide kernel threads. + + - do nothing. + + - enter Sorted view, update function bar, sort by MEM%. + + , - do nothing. + +