From bc192e2e6daec33795d7928db428b228d97a2906 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 28 Apr 2020 04:50:08 -0400 Subject: [PATCH] import pcp-5.0.2-5.el8 --- .gitignore | 1 + .pcp.metadata | 1 + SOURCES/activemq-modules.patch | 53 + SOURCES/archive-discovery.patch | 3175 ++++++++++++++++++++++++++ SOURCES/multilib-pcp-devel.patch | 22 + SOURCES/s390x-interrupts.patch | 108 + SPECS/pcp.spec | 3672 ++++++++++++++++++++++++++++++ 7 files changed, 7032 insertions(+) create mode 100644 .gitignore create mode 100644 .pcp.metadata create mode 100644 SOURCES/activemq-modules.patch create mode 100644 SOURCES/archive-discovery.patch create mode 100644 SOURCES/multilib-pcp-devel.patch create mode 100644 SOURCES/s390x-interrupts.patch create mode 100644 SPECS/pcp.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02817f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/pcp-5.0.2.src.tar.gz diff --git a/.pcp.metadata b/.pcp.metadata new file mode 100644 index 0000000..017406d --- /dev/null +++ b/.pcp.metadata @@ -0,0 +1 @@ +95c6975c1af0c910a0e26ad5677a40bd8cd52ed2 SOURCES/pcp-5.0.2.src.tar.gz diff --git a/SOURCES/activemq-modules.patch b/SOURCES/activemq-modules.patch new file mode 100644 index 0000000..f43068d --- /dev/null +++ b/SOURCES/activemq-modules.patch @@ -0,0 +1,53 @@ +commit 4356ac909fa1cc30e5804d9ff6e4c9204977b091 +Author: Nathan Scott +Date: Fri Jan 31 14:34:25 2020 +1100 + + pmdactivemq: module name and path resolution fixes for latest perl + + Picked up by test qa/760 with recent versions of perl. + + Resolves Red Hat BZ #1788881 + +diff --git a/src/pmdas/activemq/GNUmakefile b/src/pmdas/activemq/GNUmakefile +index 8289670ca..1ad330220 100644 +--- a/src/pmdas/activemq/GNUmakefile ++++ b/src/pmdas/activemq/GNUmakefile +@@ -41,7 +41,9 @@ build-me: check_domain + install install_pcp: default + $(INSTALL) -m 755 -d $(PMDADIR) + $(INSTALL) -m 755 Install Remove $(PMDADIR) +- $(INSTALL) -m 644 pmda$(IAM).pl $(MODULES) $(PMDADIR) ++ $(INSTALL) -m 644 pmda$(IAM).pl $(PMDADIR)/pmda$(IAM).pl ++ $(INSTALL) -m 755 -d $(PMDADIR)/PCP ++ $(INSTALL) -m 644 $(MODULES) $(PMDADIR)/PCP + @$(INSTALL_MAN) + else + build-me: +diff --git a/src/pmdas/activemq/pmdaactivemq.pl b/src/pmdas/activemq/pmdaactivemq.pl +index 7f835aac5..4b5451688 100755 +--- a/src/pmdas/activemq/pmdaactivemq.pl ++++ b/src/pmdas/activemq/pmdaactivemq.pl +@@ -49,16 +49,16 @@ my $jvm_garbage_collection_cluster = 5; + for my $file (pmda_config('PCP_PMDAS_DIR') . '/activemq/activemq.conf', 'activemq.conf') { + eval `cat $file` unless ! -f $file; + } +-my $timesource = TimeSource->new; +-my $cache = Cache->new($timesource, $cache_time); ++my $timesource = PCP::TimeSource->new; ++my $cache = PCP::Cache->new($timesource, $cache_time); + my $http_client = LWP::UserAgent->new; + $http_client->agent('pmdaactivemq'); + $http_client->timeout($rest_timeout); +-my $rest_client = RESTClient->new($http_client, $cache, $rest_hostname, $rest_port, $rest_username, $rest_password, $rest_realm); +-my $activemq = ActiveMQ->new($rest_client); +-my $jvm_memory = JVMMemory->new($rest_client); +-my $jvm_memory_pool = JVMMemoryPool->new($rest_client); +-my $jvm_garbage_collection = JVMGarbageCollection->new($rest_client); ++my $rest_client = PCP::RESTClient->new($http_client, $cache, $rest_hostname, $rest_port, $rest_username, $rest_password, $rest_realm); ++my $activemq = PCP::ActiveMQ->new($rest_client); ++my $jvm_memory = PCP::JVMMemory->new($rest_client); ++my $jvm_memory_pool = PCP::JVMMemoryPool->new($rest_client); ++my $jvm_garbage_collection = PCP::JVMGarbageCollection->new($rest_client); + + my %queue_instances; + diff --git a/SOURCES/archive-discovery.patch b/SOURCES/archive-discovery.patch new file mode 100644 index 0000000..cf7a3d3 --- /dev/null +++ b/SOURCES/archive-discovery.patch @@ -0,0 +1,3175 @@ +diff -Naurp pcp-5.0.2.orig/qa/1211.out pcp-5.0.2/qa/1211.out +--- pcp-5.0.2.orig/qa/1211.out 2019-12-06 15:18:26.000000000 +1100 ++++ pcp-5.0.2/qa/1211.out 2020-02-03 13:23:15.258762963 +1100 +@@ -144,6 +144,9 @@ kernel.uname.nodename + kernel.uname.release + kernel.uname.sysname + kernel.uname.version ++pmcd.pmlogger.archive ++pmcd.pmlogger.host ++pmcd.pmlogger.port + proc.fd.count + proc.id.egid + proc.id.egid_nm +@@ -267,6 +270,7 @@ List all instance names ... + 030016 pmlogger -P -c config.default 20110930.17.20 + 1 minute + 15 minute ++2950 + 5 minute + cpu0 + cpu1 +@@ -398,10 +402,10 @@ fecd5a4b4c6e1273eaa001287a6dd57b7bbd19f7 + Values fetch for a single-valued query ... + + d51624d12da45900bfee2fd73f1e23f3ccabb784 +- [Mon Oct 3 09:10:22.959242000 2011] 172598244 +- [Mon Oct 3 09:10:23.300460000 2011] 172598364 +- [Mon Oct 3 09:10:23.802930000 2011] 172598481 + [Mon Oct 3 09:10:24.305845000 2011] 172598559 ++ [Mon Oct 3 09:10:23.802930000 2011] 172598481 ++ [Mon Oct 3 09:10:23.300460000 2011] 172598364 ++ [Mon Oct 3 09:10:22.959242000 2011] 172598244 + + Values fetch with a one-second interval ... + +@@ -420,15 +424,18 @@ d51624d12da45900bfee2fd73f1e23f3ccabb784 + Values fetch for a multi-valued query ... + + fecd5a4b4c6e1273eaa001287a6dd57b7bbd19f7 +- [Mon Oct 3 09:10:23.300460000 2011] 0.000000e+00 59181b1de54ff2b383cfd1cdd8636f86c880b69b +- [Mon Oct 3 09:10:23.300460000 2011] 2.000000e-02 ab010c7d45145aa33c8f8fa681a68c9d4102ae19 +- [Mon Oct 3 09:10:23.300460000 2011] 5.000000e-02 9d418095c9f971ff4fd44d6828ead27f9d021dc3 +- [Mon Oct 3 09:10:23.802930000 2011] 0.000000e+00 59181b1de54ff2b383cfd1cdd8636f86c880b69b +- [Mon Oct 3 09:10:23.802930000 2011] 2.000000e-02 ab010c7d45145aa33c8f8fa681a68c9d4102ae19 +- [Mon Oct 3 09:10:23.802930000 2011] 5.000000e-02 9d418095c9f971ff4fd44d6828ead27f9d021dc3 + [Mon Oct 3 09:10:24.305845000 2011] 0.000000e+00 59181b1de54ff2b383cfd1cdd8636f86c880b69b + [Mon Oct 3 09:10:24.305845000 2011] 2.000000e-02 ab010c7d45145aa33c8f8fa681a68c9d4102ae19 + [Mon Oct 3 09:10:24.305845000 2011] 5.000000e-02 9d418095c9f971ff4fd44d6828ead27f9d021dc3 ++ [Mon Oct 3 09:10:23.802930000 2011] 0.000000e+00 59181b1de54ff2b383cfd1cdd8636f86c880b69b ++ [Mon Oct 3 09:10:23.802930000 2011] 2.000000e-02 ab010c7d45145aa33c8f8fa681a68c9d4102ae19 ++ [Mon Oct 3 09:10:23.802930000 2011] 5.000000e-02 9d418095c9f971ff4fd44d6828ead27f9d021dc3 ++ [Mon Oct 3 09:10:23.300460000 2011] 0.000000e+00 59181b1de54ff2b383cfd1cdd8636f86c880b69b ++ [Mon Oct 3 09:10:23.300460000 2011] 2.000000e-02 ab010c7d45145aa33c8f8fa681a68c9d4102ae19 ++ [Mon Oct 3 09:10:23.300460000 2011] 5.000000e-02 9d418095c9f971ff4fd44d6828ead27f9d021dc3 ++ [Mon Oct 3 09:10:22.959242000 2011] 0.000000e+00 59181b1de54ff2b383cfd1cdd8636f86c880b69b ++ [Mon Oct 3 09:10:22.959242000 2011] 2.000000e-02 ab010c7d45145aa33c8f8fa681a68c9d4102ae19 ++ [Mon Oct 3 09:10:22.959242000 2011] 5.000000e-02 9d418095c9f971ff4fd44d6828ead27f9d021dc3 + + Multi-series lookups from a multi-series query ... + 2db1da4d276d81c42c578c2829e99188ae7cc898 +diff -Naurp pcp-5.0.2.orig/qa/1573 pcp-5.0.2/qa/1573 +--- pcp-5.0.2.orig/qa/1573 1970-01-01 10:00:00.000000000 +1000 ++++ pcp-5.0.2/qa/1573 2020-02-03 13:36:17.288581801 +1100 +@@ -0,0 +1,103 @@ ++#!/bin/sh ++# PCP QA Test No. 1573 ++# Exercise libpcp_web memory leak without a redis-server. ++# ++# Copyright (c) 2020 Red Hat. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++_check_series ++ ++_cleanup() ++{ ++ cd $here ++ if $need_restore ++ then ++ need_restore=false ++ _service pmlogger stop >/dev/null ++ $sudo rm -rf $PCP_LOG_DIR/pmlogger ++ $sudo mv $PCP_LOG_DIR/pmlogger.$seq $PCP_LOG_DIR/pmlogger ++ _restore_config $PCP_ETC_DIR/pcp/pmlogger ++ _service pcp restart 2>&1 | _filter_pcp_stop | _filter_pcp_start ++ _wait_for_pmcd ++ _wait_for_pmlogger ++ echo === restarting pmproxy ++ _restore_config $PCP_SYSCONF_DIR/pmproxy ++ _service pmproxy restart 2>&1 | _filter_pcp_start ++ _wait_for_pmproxy ++ fi ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=1 # failure is the default! ++need_restore=false ++$sudo rm -rf $tmp $tmp.* $seq.full ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# real QA test starts here ++_save_config $PCP_SYSCONF_DIR/pmproxy ++need_restore=true ++ ++# only want the primary logger running ++_save_config $PCP_ETC_DIR/pcp/pmlogger ++_restore_pmlogger_control ++ ++#$sudo rm -f $PCP_SYSCONF_DIR/pmproxy/* ++echo "[pmproxy]" > $tmp.conf ++echo "pcp.enabled = true" >> $tmp.conf ++echo "http.enabled = true" >> $tmp.conf ++echo "redis.enabled = true" >> $tmp.conf ++echo "[discover]" >> $tmp.conf ++echo "enabled = true" >> $tmp.conf ++echo "[pmseries]" >> $tmp.conf ++echo "enabled = false" >> $tmp.conf ++$sudo cp $tmp.conf $PCP_SYSCONF_DIR/pmproxy/pmproxy.conf ++ ++_service pmlogger stop >/dev/null ++ ++# move aside existing logs so we can measure base memory footprint ++[ -d $PCP_LOG_DIR/pmlogger.$seq ] && $sudo mv $PCP_LOG_DIR/pmlogger.$seq $PCP_LOG_DIR/pmlogger.$seq.saved ++$sudo mv $PCP_LOG_DIR/pmlogger $PCP_LOG_DIR/pmlogger.$seq ++$sudo mkdir -p $PCP_LOG_DIR/pmlogger ++$sudo chmod 775 $PCP_LOG_DIR/pmlogger ++$sudo chown $PCP_USER:$PCP_USER $PCP_LOG_DIR/pmlogger ++ ++_service pmproxy restart 2>&1 | _filter_pcp_stop | _filter_pcp_start ++_wait_for_pmproxy ++ ++pmproxy_pid=`_get_pids_by_name -a pmproxy` ++[ -z "$pmproxy_pid" ] && echo === pmproxy not running && status=1 && exit 1 ++echo === extract initial rss ++pmproxy_rss1=`pminfo -f proc.memory.rss | ++ $PCP_AWK_PROG '{ if ($2 == "['$pmproxy_pid'") { print $NF} }'` ++ ++echo === restarting pmlogger # primary only ++_service pmlogger restart 2>&1 | _filter_pcp_start ++_wait_for_pmlogger ++ ++echo === wait for pmproxy to process filesystem events ++pmsleep 4.2 ++ ++echo === extract updated rss ++pmproxy_rss2=`pminfo -f proc.memory.rss | ++ $PCP_AWK_PROG '{ if ($2 == "['$pmproxy_pid'") { print $NF} }'` ++ ++echo === checking rss within tolerance ++_within_tolerance "rss" $pmproxy_rss1 $pmproxy_rss2 10% ++[ $pmproxy_rss2 -gt 10000 ] && echo "Unexpected pmproxy RSS: $pmproxy_rss2, was initially $pmproxy_rss1" ++ ++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 ++echo === see $seq.full for pmproxy rss and logs ++ ++# success, all done ++status=0 ++exit +diff -Naurp pcp-5.0.2.orig/qa/1573.out pcp-5.0.2/qa/1573.out +--- pcp-5.0.2.orig/qa/1573.out 1970-01-01 10:00:00.000000000 +1000 ++++ pcp-5.0.2/qa/1573.out 2020-02-03 13:23:15.259762953 +1100 +@@ -0,0 +1,8 @@ ++QA output created by 1573 ++=== extract initial rss ++=== restarting pmlogger ++=== wait for pmproxy to process filesystem events ++=== extract updated rss ++=== checking rss within tolerance ++=== see 1573.full for pmproxy rss and logs ++=== restarting pmproxy +diff -Naurp pcp-5.0.2.orig/qa/1600 pcp-5.0.2/qa/1600 +--- pcp-5.0.2.orig/qa/1600 2019-12-10 17:49:05.000000000 +1100 ++++ pcp-5.0.2/qa/1600 2020-02-03 13:23:15.260762942 +1100 +@@ -82,7 +82,11 @@ _filter_values() + _filter_label_values() + { + sed \ ++ -e "s/^domainname: \"${domainname}\"/domainname: \"DOMAIN\"/g" \ ++ -e "s/^machineid: \"${machineid}\"/machineid: \"MACHINE\"/g" \ + -e "s/^hostname: \"${hostname}\"/hostname: \"HOSTNAME\"/g" \ ++ -e "s/^groupid: $groupid/groupid: GID/g" \ ++ -e "s/^userid: $userid/userid: UID/g" \ + -e "s/changed: false, true/changed: false/g" \ + -e "/metric_label: null/d" \ + #end +diff -Naurp pcp-5.0.2.orig/qa/1600.out pcp-5.0.2/qa/1600.out +--- pcp-5.0.2.orig/qa/1600.out 2019-12-10 10:46:20.000000000 +1100 ++++ pcp-5.0.2/qa/1600.out 2020-02-03 13:23:15.260762942 +1100 +@@ -27,15 +27,15 @@ TIMESERIES + == verify metric labels + + TIMESERIES +- inst [100 or "bin-100"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [200 or "bin-200"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [300 or "bin-300"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [400 or "bin-400"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [500 or "bin-500"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [600 or "bin-600"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [700 or "bin-700"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [800 or "bin-800"] labels {"agent":"sample","hostname":"HOST","role":"testing"} +- inst [900 or "bin-900"] labels {"agent":"sample","hostname":"HOST","role":"testing"} ++ inst [100 or "bin-100"] labels {"agent":"sample","bin":100,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [200 or "bin-200"] labels {"agent":"sample","bin":200,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [300 or "bin-300"] labels {"agent":"sample","bin":300,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [400 or "bin-400"] labels {"agent":"sample","bin":400,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [500 or "bin-500"] labels {"agent":"sample","bin":500,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [600 or "bin-600"] labels {"agent":"sample","bin":600,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [700 or "bin-700"] labels {"agent":"sample","bin":700,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [800 or "bin-800"] labels {"agent":"sample","bin":800,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} ++ inst [900 or "bin-900"] labels {"agent":"sample","bin":900,"domainname":"DOMAIN","groupid":GID,"hostname":"HOST","latitude":-25.28496,"longitude":152.87886,"machineid":"MACHINE","role":"testing","userid":UID} + == verify metric values + + TIMESERIES +@@ -43,15 +43,24 @@ TIMESERIES + [TIMESTAMP] VALUE + == verify label names and values + agent: "mmv", "sample", "pmcd" ++bin: 100, 200, 300, 400, 500, 600, 700, 800, 900 + changed: false + clan: "mcdonell" + cluster: "zero" ++domainname: "DOMAIN" ++groupid: GID + hostname: "HOSTNAME" + indom_label: 42.001 ++latitude: -25.28496 ++longitude: 152.87886 ++machineid: "MACHINE" + measure: "speed" + model: "RGB" ++registry_label: "string" + role: "testing" ++transient: false, true + units: "metres per second" + unitsystem: "SI" ++userid: UID + == verify archive removal + == all done +diff -Naurp pcp-5.0.2.orig/qa/1601.out pcp-5.0.2/qa/1601.out +--- pcp-5.0.2.orig/qa/1601.out 2019-11-27 16:01:34.000000000 +1100 ++++ pcp-5.0.2/qa/1601.out 2020-02-03 13:23:15.261762932 +1100 +@@ -131,7 +131,7 @@ Using series 01d8bc7fa75aaff98a08aa0b1c0 + { + "series": "605fc77742cd0317597291329561ac4e50c0dd12", + "instance": "c3795d8b757506a2901c6b08b489ba56cae7f0d4", +- "timestamp": 1317633023300.460, ++ "timestamp": 1317633024305.845, + "value": "71661" + }, + { +@@ -147,7 +147,7 @@ Using series 01d8bc7fa75aaff98a08aa0b1c0 + { + "series": "605fc77742cd0317597291329561ac4e50c0dd12", + "instance": "c3795d8b757506a2901c6b08b489ba56cae7f0d4", +- "timestamp": 1317633023300.460, ++ "timestamp": 1317633024305.845, + "value": "71661" + }, + { +@@ -163,7 +163,7 @@ Using series 01d8bc7fa75aaff98a08aa0b1c0 + { + "series": "605fc77742cd0317597291329561ac4e50c0dd12", + "instance": "c3795d8b757506a2901c6b08b489ba56cae7f0d4", +- "timestamp": 1317633023300.460, ++ "timestamp": 1317633024305.845, + "value": "71661" + }, + { +@@ -179,7 +179,7 @@ Using series 01d8bc7fa75aaff98a08aa0b1c0 + { + "series": "605fc77742cd0317597291329561ac4e50c0dd12", + "instance": "c3795d8b757506a2901c6b08b489ba56cae7f0d4", +- "timestamp": 1317633023300.460, ++ "timestamp": 1317633024305.845, + "value": "71661" + }, + { +diff -Naurp pcp-5.0.2.orig/qa/1661 pcp-5.0.2/qa/1661 +--- pcp-5.0.2.orig/qa/1661 2019-12-10 17:04:20.000000000 +1100 ++++ pcp-5.0.2/qa/1661 2020-02-03 13:23:15.261762932 +1100 +@@ -41,8 +41,7 @@ _restore_pmlogger_control + echo;echo === restarting pmproxy service to ensure sane starting condition + _service pmlogger stop 2>&1 | _filter_pcp_stop + _service pmproxy restart 2>&1 | _filter_pcp_stop | _filter_pcp_start +-# give pmproxy a chance to startup +-pmsleep 2; _wait_for_pmproxy ++_wait_for_pmproxy + + pmproxy_pid=`_get_pids_by_name -a pmproxy` + [ -z "$pmproxy_pid" ] && echo === pmproxy not running && status=1 && exit 1 +diff -Naurp pcp-5.0.2.orig/qa/group pcp-5.0.2/qa/group +--- pcp-5.0.2.orig/qa/group 2019-12-11 14:06:06.000000000 +1100 ++++ pcp-5.0.2/qa/group 2020-02-03 13:23:15.261762932 +1100 +@@ -1688,6 +1688,7 @@ BAD + 1545 pcp2xml python pcp2xxx local + 1546 pmrep python local + 1547 pmrep python local ++1573 pmproxy libpcp_web pmlogger local + 1588 python pmiostat local + 1598 pmda.statsd local + 1599 pmda.statsd local +diff -Naurp pcp-5.0.2.orig/src/include/pcp/libpcp.h pcp-5.0.2/src/include/pcp/libpcp.h +--- pcp-5.0.2.orig/src/include/pcp/libpcp.h 2019-09-24 17:23:36.000000000 +1000 ++++ pcp-5.0.2/src/include/pcp/libpcp.h 2020-02-03 13:23:15.261762932 +1100 +@@ -7,7 +7,7 @@ + * remain fixed across releases, and they may not work, or may + * provide different semantics at some point in the future. + * +- * Copyright (c) 2012-2019 Red Hat. ++ * Copyright (c) 2012-2020 Red Hat. + * Copyright (c) 2008-2009 Aconex. All Rights Reserved. + * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. + * +@@ -846,6 +846,13 @@ PCP_CALL extern int __pmLogPutText(__pmA + PCP_CALL extern int __pmLogWriteLabel(__pmFILE *, const __pmLogLabel *); + PCP_CALL extern int __pmLogLoadLabel(__pmArchCtl *, const char *); + PCP_CALL extern int __pmLogLoadMeta(__pmArchCtl *); ++PCP_CALL extern int __pmLogAddDesc(__pmArchCtl *, const pmDesc *); ++PCP_CALL extern int __pmLogAddInDom(__pmArchCtl *, const pmTimespec *, const pmInResult *, int *, int); ++PCP_CALL extern int __pmLogAddPMNSNode(__pmArchCtl *, pmID, const char *); ++PCP_CALL extern int __pmLogAddLabelSets(__pmArchCtl *, const pmTimespec *, unsigned int, unsigned int, int, pmLabelSet *); ++PCP_CALL extern int __pmLogAddText(__pmArchCtl *, unsigned int, unsigned int, const char *); ++PCP_CALL extern int __pmLogAddVolume(__pmArchCtl *, unsigned int); ++ + #define PMLOGREAD_NEXT 0 + #define PMLOGREAD_TO_EOF 1 + PCP_CALL extern int __pmLogRead(__pmArchCtl *, int, __pmFILE *, pmResult **, int); +@@ -862,7 +869,9 @@ PCP_CALL extern int __pmLogLookupText(__ + PCP_CALL extern int __pmLogNameInDom(__pmArchCtl *, pmInDom, pmTimeval *, int, char **); + PCP_CALL extern const char *__pmLogLocalSocketDefault(int, char *buf, size_t bufSize); + PCP_CALL extern const char *__pmLogLocalSocketUser(int, char *buf, size_t bufSize); ++PCP_CALL extern int __pmLogCompressedSuffix(const char *); + PCP_CALL extern char *__pmLogBaseName(char *); ++PCP_CALL extern char *__pmLogBaseNameVol(char *, int *); + PCP_DATA extern int __pmLogReads; + + /* Convert opaque context handle to __pmContext pointer */ +diff -Naurp pcp-5.0.2.orig/src/libpcp/src/exports.master pcp-5.0.2/src/libpcp/src/exports.master +--- pcp-5.0.2.orig/src/libpcp/src/exports.master 2019-10-02 14:40:30.000000000 +1000 ++++ pcp-5.0.2/src/libpcp/src/exports.master 2020-02-03 13:23:15.262762921 +1100 +@@ -683,3 +683,15 @@ PCP_3.26 { + global: + __pmDupLabelSets; + } PCP_3.25; ++ ++PCP_3.26_1 { ++ global: ++ __pmLogAddDesc; ++ __pmLogAddInDom; ++ __pmLogAddPMNSNode; ++ __pmLogAddLabelSets; ++ __pmLogAddText; ++ __pmLogAddVolume; ++ __pmLogCompressedSuffix; ++ __pmLogBaseNameVol; ++} PCP_3.26; +diff -Naurp pcp-5.0.2.orig/src/libpcp/src/io.c pcp-5.0.2/src/libpcp/src/io.c +--- pcp-5.0.2.orig/src/libpcp/src/io.c 2018-06-09 11:43:34.000000000 +1000 ++++ pcp-5.0.2/src/libpcp/src/io.c 2020-02-03 13:23:15.262762921 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018 Red Hat. ++ * Copyright (c) 2017-2018,2020 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 +@@ -47,7 +47,7 @@ extern __pm_fops __pm_xz; + #endif + + static const struct { +- const char *suff; ++ const char *suffix; + const int appl; + __pm_fops *handler; + } compress_ctl[] = { +@@ -61,40 +61,43 @@ static const struct { + }; + static const int ncompress = sizeof(compress_ctl) / sizeof(compress_ctl[0]); + ++int ++__pmLogCompressedSuffix(const char *suffix) ++{ ++ int i; ++ ++ for (i = 0; i < ncompress; i++) ++ if (strcmp(suffix, compress_ctl[i].suffix) == 0) ++ return 1; ++ return 0; ++} ++ + /* +- * If name contains '.' and the suffix is "index", "meta" or a string of +- * digits, all optionally followed by one of the compression suffixes, +- * strip the suffix. +- * +- * Modifications are performed on the argument string in-place. If modifications +- * are made, a pointer to the start of the modified string is returned. +- * Otherwise, NULL is returned. ++ * Variant of __pmLogBaseName() - see below that also returns log ++ * the volume number if the file name is an archive log volume. ++ * If the vol argument is NULL it will be ignored. + */ + char * +-__pmLogBaseName(char *name) ++__pmLogBaseNameVol(char *name, int *vol) + { +- char *q; +- int strip; +- int i; ++ char *q, *q2; ++ int strip = 0; + +- strip = 0; ++ if (vol) ++ *vol = -1; + if ((q = strrchr(name, '.')) != NULL) { +- for (i = 0; i < ncompress; i++) { +- if (strcmp(q, compress_ctl[i].suff) == 0) { +- char *q2; +- /* +- * The name ends with one of the supported compressed file +- * suffixes. Strip it before checking for other known suffixes. +- */ +- *q = '\0'; +- if ((q2 = strrchr(name, '.')) == NULL) { +- /* no . to the left of the suffix */ +- *q = '.'; +- goto done; +- } +- q = q2; +- break; ++ if (__pmLogCompressedSuffix(q)) { ++ /* ++ * The name ends with one of the supported compressed file ++ * suffixes. Strip it before checking for other known suffixes. ++ */ ++ *q = '\0'; ++ if ((q2 = strrchr(name, '.')) == NULL) { ++ /* no . to the left of the suffix */ ++ *q = '.'; ++ goto done; + } ++ q = q2; + } + if (strcmp(q, ".index") == 0) { + strip = 1; +@@ -109,16 +112,10 @@ __pmLogBaseName(char *name) + */ + if (q[1] != '\0') { + char *end; +- /* +- * Below we don't care about the value from strtol(), +- * we're interested in updating the pointer "end". +- * The messiness is thanks to gcc and glibc ... strtol() +- * is marked __attribute__((warn_unused_result)) ... +- * to avoid warnings on all platforms, assign to a +- * dummy variable that is explicitly marked unused. +- */ +- long tmpl __attribute__((unused)); ++ long tmpl; + tmpl = strtol(q+1, &end, 10); ++ if (vol) ++ *vol = tmpl; + if (*end == '\0') strip = 1; + } + } +@@ -131,6 +128,21 @@ done: + return NULL; /* not the name of an archive file. */ + } + ++/* ++ * If name contains '.' and the suffix is "index", "meta" or a string of ++ * digits, all optionally followed by one of the compression suffixes, ++ * strip the suffix. ++ * ++ * Modifications are performed on the argument string in-place. If modifications ++ * are made, a pointer to the start of the modified string is returned. ++ * Otherwise, NULL is returned. ++ */ ++char * ++__pmLogBaseName(char *name) ++{ ++ return __pmLogBaseNameVol(name, NULL); ++} ++ + static int + popen_uncompress(const char *cmd, const char *arg, const char *fname, int fd) + { +@@ -319,7 +331,7 @@ __pmCompressedFileIndex(char *fname, siz + char tmpname[MAXPATHLEN]; + + for (i = 0; i < ncompress; i++) { +- suffix = compress_ctl[i].suff; ++ suffix = compress_ctl[i].suffix; + pmsprintf(tmpname, sizeof(tmpname), "%s%s", fname, suffix); + sts = access(tmpname, R_OK); + if (sts == 0 || (errno != ENOENT && errno != ENOTDIR)) { +@@ -358,7 +370,7 @@ index_compress(char *fname, size_t flen) + suffix = strrchr(fname, '.'); + if (suffix != NULL) { + for (i = 0; i < ncompress; i++) { +- if (strcmp(suffix, compress_ctl[i].suff) == 0) ++ if (strcmp(suffix, compress_ctl[i].suffix) == 0) + return i; + } + } +@@ -731,7 +743,7 @@ compress_suffix_list(void) + const char *q; + + for (i = 0; i < ncompress; i++) { +- q = compress_ctl[i].suff; ++ q = compress_ctl[i].suffix; + if (i > 0) + *p++ = ' '; + while (*q) { +diff -Naurp pcp-5.0.2.orig/src/libpcp/src/logmeta.c pcp-5.0.2/src/libpcp/src/logmeta.c +--- pcp-5.0.2.orig/src/libpcp/src/logmeta.c 2018-09-14 10:22:56.000000000 +1000 ++++ pcp-5.0.2/src/libpcp/src/logmeta.c 2020-02-03 13:23:15.262762921 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2018 Red Hat. ++ * Copyright (c) 2013-2018, 2020 Red Hat. + * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it +@@ -490,7 +490,7 @@ check_dup_labels(const __pmArchCtl *acp) + } + + static int +-addtext(__pmArchCtl *acp, unsigned int ident, unsigned int type, char *buffer) ++addtext(__pmArchCtl *acp, unsigned int ident, unsigned int type, const char *buffer) + { + __pmLogCtl *lcp = acp->ac_log; + __pmHashNode *hp; +@@ -553,6 +553,92 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":15", + return sts; + } + ++int ++__pmLogAddDesc(__pmArchCtl *acp, const pmDesc *newdp) ++{ ++ __pmHashNode *hp; ++ __pmLogCtl *lcp = acp->ac_log; ++ pmDesc *dp, *olddp; ++ ++ if ((hp = __pmHashSearch((int)newdp->pmid, &lcp->l_hashpmid)) != NULL) { ++ /* PMID is already in the hash table - check for conflicts. */ ++ olddp = (pmDesc *)hp->data; ++ if (newdp->type != olddp->type) ++ return PM_ERR_LOGCHANGETYPE; ++ if (newdp->sem != olddp->sem) ++ return PM_ERR_LOGCHANGESEM; ++ if (newdp->indom != olddp->indom) ++ return PM_ERR_LOGCHANGEINDOM; ++ if (newdp->units.dimSpace != olddp->units.dimSpace || ++ newdp->units.dimTime != olddp->units.dimTime || ++ newdp->units.dimCount != olddp->units.dimCount || ++ newdp->units.scaleSpace != olddp->units.scaleSpace || ++ newdp->units.scaleTime != olddp->units.scaleTime || ++ newdp->units.scaleCount != olddp->units.scaleCount) ++ return PM_ERR_LOGCHANGEUNITS; ++ ++ /* PMID is already known and checks out - we're done here. */ ++ return 0; ++ } ++ ++ /* Add a copy of the descriptor into the PMID:desc hash table. */ ++PM_FAULT_POINT("libpcp/" __FILE__ ":2", PM_FAULT_ALLOC); ++ if ((dp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL) ++ return -oserror(); ++ *dp = *newdp; ++ ++ return __pmHashAdd((int)dp->pmid, (void *)dp, &lcp->l_hashpmid); ++} ++ ++int ++__pmLogAddPMNSNode(__pmArchCtl *acp, pmID pmid, const char *name) ++{ ++ __pmLogCtl *lcp = acp->ac_log; ++ int sts; ++ ++ /* ++ * If we see a duplicate name with a different PMID, its a ++ * recoverable error. ++ * We wont be able to see all of the data in the log, but ++ * its better to provide access to some rather than none, ++ * esp. when only one or two metric IDs may be corrupted ++ * in this way (which we may not be interested in anyway). ++ */ ++ sts = __pmAddPMNSNode(lcp->l_pmns, pmid, name); ++ if (sts == PM_ERR_PMID) ++ sts = 0; ++ return sts; ++} ++ ++int ++__pmLogAddInDom(__pmArchCtl *acp, const pmTimespec *when, const pmInResult *in, ++ int *tbuf, int allinbuf) ++{ ++ pmTimeval tv; ++ ++ tv.tv_sec = when->tv_sec; ++ tv.tv_usec = when->tv_nsec / 1000; ++ return addindom(acp->ac_log, in->indom, &tv, ++ in->numinst, in->instlist, in->namelist, tbuf, allinbuf); ++} ++ ++int ++__pmLogAddLabelSets(__pmArchCtl *acp, const pmTimespec *when, unsigned int type, ++ unsigned int ident, int nsets, pmLabelSet *labelsets) ++{ ++ pmTimeval tv; ++ ++ tv.tv_sec = when->tv_sec; ++ tv.tv_usec = when->tv_nsec / 1000; ++ return addlabel(acp, type, ident, nsets, labelsets, &tv); ++} ++ ++int ++__pmLogAddText(__pmArchCtl *acp, unsigned int ident, unsigned int type, const char *buffer) ++{ ++ return addtext(acp, ident, type, buffer); ++} ++ + /* + * Load _all_ of the hashed pmDesc and __pmLogInDom structures from the metadata + * log file -- used at the initialization (NewContext) of an archive. +@@ -563,11 +649,8 @@ int + __pmLogLoadMeta(__pmArchCtl *acp) + { + __pmLogCtl *lcp = acp->ac_log; +- __pmHashNode *hp; + int rlen; + int check; +- pmDesc *dp; +- pmDesc *olddp; + int sts = 0; + __pmLogHdr h; + __pmFILE *f = lcp->l_mdfp; +@@ -615,13 +698,10 @@ __pmLogLoadMeta(__pmArchCtl *acp) + } + rlen = h.len - (int)sizeof(__pmLogHdr) - (int)sizeof(int); + if (h.type == TYPE_DESC) { ++ pmDesc desc; ++ + numpmid++; +-PM_FAULT_POINT("libpcp/" __FILE__ ":2", PM_FAULT_ALLOC); +- if ((dp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL) { +- sts = -oserror(); +- goto end; +- } +- if ((n = (int)__pmFread(dp, 1, sizeof(pmDesc), f)) != sizeof(pmDesc)) { ++ if ((n = (int)__pmFread(&desc, 1, sizeof(pmDesc), f)) != sizeof(pmDesc)) { + if (pmDebugOptions.logmeta) { + fprintf(stderr, "__pmLogLoadMeta: pmDesc read -> %d: expected: %d\n", + n, (int)sizeof(pmDesc)); +@@ -632,67 +712,25 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":2", + } + else + sts = PM_ERR_LOGREC; +- free(dp); + goto end; + } +- else { +- /* swab desc */ +- dp->type = ntohl(dp->type); +- dp->sem = ntohl(dp->sem); +- dp->indom = __ntohpmInDom(dp->indom); +- dp->units = __ntohpmUnits(dp->units); +- dp->pmid = __ntohpmID(dp->pmid); +- } + +- /* Add it to the hash pmid hash table. */ +- if ((hp = __pmHashSearch((int)dp->pmid, &lcp->l_hashpmid)) != NULL) { +- /* +- * This pmid is already in the hash table. Check for conflicts. +- */ +- olddp = (pmDesc *)hp->data; +- if (dp->type != olddp->type) { +- sts = PM_ERR_LOGCHANGETYPE; +- free(dp); +- goto end; +- } +- if (dp->sem != olddp->sem) { +- sts = PM_ERR_LOGCHANGESEM; +- free(dp); +- goto end; +- } +- if (dp->indom != olddp->indom) { +- sts = PM_ERR_LOGCHANGEINDOM; +- free(dp); +- goto end; +- } +- if (dp->units.dimSpace != olddp->units.dimSpace || +- dp->units.dimTime != olddp->units.dimTime || +- dp->units.dimCount != olddp->units.dimCount || +- dp->units.scaleSpace != olddp->units.scaleSpace || +- dp->units.scaleTime != olddp->units.scaleTime || +- dp->units.scaleCount != olddp->units.scaleCount) { +- sts = PM_ERR_LOGCHANGEUNITS; +- free(dp); +- goto end; +- } +- /* +- * This pmid is already known, and matches. We can free the newly +- * read copy and use the one in the hash table. +- */ +- free(dp); +- dp = olddp; +- } +- else if ((sts = __pmHashAdd((int)dp->pmid, (void *)dp, &lcp->l_hashpmid)) < 0) { +- free(dp); ++ /* swab desc */ ++ desc.type = ntohl(desc.type); ++ desc.sem = ntohl(desc.sem); ++ desc.indom = __ntohpmInDom(desc.indom); ++ desc.units = __ntohpmUnits(desc.units); ++ desc.pmid = __ntohpmID(desc.pmid); ++ ++ if ((sts = __pmLogAddDesc(acp, &desc)) < 0) + goto end; +- } + + /* read in the names & store in PMNS tree ... */ + if ((n = (int)__pmFread(&numnames, 1, sizeof(numnames), f)) != + sizeof(numnames)) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: numnames read -> %d: expected: %d\n", +- n, (int)sizeof(numnames)); ++ fprintf(stderr, "%s: numnames read -> %d: expected: %d\n", ++ "__pmLogLoadMeta", n, (int)sizeof(numnames)); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -711,8 +749,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":2", + if ((n = (int)__pmFread(&len, 1, sizeof(len), f)) != + sizeof(len)) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: len name[%d] read -> %d: expected: %d\n", +- i, n, (int)sizeof(len)); ++ fprintf(stderr, "%s: len name[%d] read -> %d: expected: %d\n", ++ "__pmLogLoadMeta", i, n, (int)sizeof(len)); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -729,8 +767,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":2", + + if ((n = (int)__pmFread(name, 1, len, f)) != len) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: name[%d] read -> %d: expected: %d\n", +- i, n, len); ++ fprintf(stderr, "%s: name[%d] read -> %d: expected: %d\n", ++ "__pmLogLoadMeta", i, n, len); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -743,36 +781,23 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":2", + name[len] = '\0'; + if (pmDebugOptions.logmeta) { + char strbuf[20]; +- fprintf(stderr, "__pmLogLoadMeta: PMID: %s name: %s\n", +- pmIDStr_r(dp->pmid, strbuf, sizeof(strbuf)), name); ++ fprintf(stderr, "%s: PMID: %s name: %s\n", ++ "__pmLogLoadMeta", ++ pmIDStr_r(desc.pmid, strbuf, sizeof(strbuf)), name); + } +- /* Add the new PMNS node */ +- if ((sts = __pmAddPMNSNode(lcp->l_pmns, dp->pmid, name)) < 0) { +- /* +- * If we see a duplicate name with a different PMID, its a +- * recoverable error. +- * We wont be able to see all of the data in the log, but +- * its better to provide access to some rather than none, +- * esp. when only one or two metric IDs may be corrupted +- * in this way (which we may not be interested in anyway). +- */ +- if (sts != PM_ERR_PMID) +- goto end; +- } ++ ++ /* Add the new PMNS node into this context */ ++ if ((sts = __pmLogAddPMNSNode(acp, desc.pmid, name)) < 0) ++ goto end; + }/*for*/ + } + else if (h.type == TYPE_INDOM) { +- int *tbuf; +- pmInDom indom; +- pmTimeval *when; +- int numinst; +- int *instlist; +- char **namelist; ++ pmTimeval *tv; ++ pmTimespec when; ++ pmInResult in; + char *namebase; +- int *stridx; +- int i; +- int k; +- int allinbuf = 0; ++ int *tbuf, *stridx; ++ int i, k, allinbuf = 0; + + PM_FAULT_POINT("libpcp/" __FILE__ ":3", PM_FAULT_ALLOC); + if ((tbuf = (int *)malloc(rlen)) == NULL) { +@@ -781,8 +806,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":3", + } + if ((n = (int)__pmFread(tbuf, 1, rlen, f)) != rlen) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: indom read -> %d: expected: %d\n", +- n, rlen); ++ fprintf(stderr, "%s: indom read -> %d: expected: %d\n", ++ "__pmLogLoadMeta", n, rlen); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -795,44 +820,44 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":3", + } + + k = 0; +- when = (pmTimeval *)&tbuf[k]; +- when->tv_sec = ntohl(when->tv_sec); +- when->tv_usec = ntohl(when->tv_usec); +- k += sizeof(*when)/sizeof(int); +- indom = __ntohpmInDom((unsigned int)tbuf[k++]); +- numinst = ntohl(tbuf[k++]); +- if (numinst > 0) { +- instlist = &tbuf[k]; +- k += numinst; ++ 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++]); ++ if (in.numinst > 0) { ++ in.instlist = &tbuf[k]; ++ k += in.numinst; + stridx = &tbuf[k]; + #if defined(HAVE_32BIT_PTR) +- namelist = (char **)stridx; ++ 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 */ + PM_FAULT_POINT("libpcp/" __FILE__ ":4", PM_FAULT_ALLOC); +- namelist = (char **)malloc(numinst*sizeof(char*)); +- if (namelist == NULL) { ++ in.namelist = (char **)malloc(in.numinst * sizeof(char*)); ++ if (in.namelist == NULL) { + sts = -oserror(); + free(tbuf); + goto end; + } + #endif +- k += numinst; ++ k += in.numinst; + namebase = (char *)&tbuf[k]; +- for (i = 0; i < numinst; i++) { +- instlist[i] = ntohl(instlist[i]); +- namelist[i] = &namebase[ntohl(stridx[i])]; ++ for (i = 0; i < in.numinst; i++) { ++ in.instlist[i] = ntohl(in.instlist[i]); ++ in.namelist[i] = &namebase[ntohl(stridx[i])]; + } +- if ((sts = addindom(lcp, indom, when, numinst, instlist, namelist, tbuf, allinbuf)) < 0) ++ if ((sts = __pmLogAddInDom(acp, &when, &in, tbuf, allinbuf)) < 0) + goto end; + /* If this indom was a duplicate, then we need to free tbuf and + namelist, as appropriate. */ + if (sts == PMLOGPUTINDOM_DUP) { + free(tbuf); +- if (namelist != NULL && !allinbuf) +- free(namelist); ++ if (in.namelist != NULL && !allinbuf) ++ free(in.namelist); + } + } + else { +@@ -860,8 +885,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":11", + } + if ((n = (int)__pmFread(tbuf, 1, rlen, f)) != rlen) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: label read -> %d: expected: %d\n", +- n, rlen); ++ fprintf(stderr, "%s: label read -> %d: expected: %d\n", ++ "__pmLogLoadMeta", n, rlen); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -908,7 +933,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":11", + + if (jsonlen < 0 || jsonlen > PM_MAXLABELJSONLEN) { + if (pmDebugOptions.logmeta) +- fprintf(stderr, "__pmLogLoadMeta: corrupted json in labelset. jsonlen=%d\n", jsonlen); ++ fprintf(stderr, "%s: corrupted json in labelset. jsonlen=%d\n", ++ "__pmLogLoadMeta", jsonlen); + sts = PM_ERR_LOGREC; + free(labelsets); + free(tbuf); +@@ -935,7 +961,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":11", + if (nlabels > PM_MAXLABELS || k + nlabels * sizeof(pmLabel) > rlen) { + /* corrupt archive metadata detected. GH #475 */ + if (pmDebugOptions.logmeta) +- fprintf(stderr, "__pmLogLoadMeta: corrupted labelset. nlabels=%d\n", nlabels); ++ fprintf(stderr, "%s: corrupted labelset. nlabels=%d\n", ++ "__pmLogLoadMeta", nlabels); + sts = PM_ERR_LOGREC; + free(labelsets); + free(tbuf); +@@ -975,8 +1002,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":16", + } + if ((n = (int)__pmFread(tbuf, 1, rlen, f)) != rlen) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: text read -> %d: expected: %d\n", +- n, rlen); ++ fprintf(stderr, "%s: text read -> %d: expected: %d\n", ++ "__pmLogLoadMeta", n, rlen); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -1005,8 +1032,8 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":16", + ident = __ntohpmID(*((unsigned int *)&tbuf[k])); + else { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: bad text ident -> %x\n", +- type); ++ fprintf(stderr, "%s: bad text ident -> %x\n", ++ "__pmLogLoadMeta", type); + } + free(tbuf); + continue; +@@ -1024,8 +1051,9 @@ PM_FAULT_POINT("libpcp/" __FILE__ ":16", + check = ntohl(check); + if (n != sizeof(check) || h.len != check) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: trailer read -> %d or len=%d: expected %d @ offset=%d\n", +- n, check, h.len, (int)(__pmFtell(f) - sizeof(check))); ++ fprintf(stderr, "%s: trailer read -> %d or len=%d: " ++ "expected %d @ offset=%d\n", "__pmLogLoadMeta", ++ n, check, h.len, (int)(__pmFtell(f) - sizeof(check))); + } + if (__pmFerror(f)) { + __pmClearerr(f); +@@ -1046,7 +1074,7 @@ end: + if (sts == 0) { + if (numpmid == 0) { + if (pmDebugOptions.logmeta) { +- fprintf(stderr, "__pmLogLoadMeta: no metrics found?\n"); ++ fprintf(stderr, "%s: no metrics found?\n", "__pmLogLoadMeta"); + } + sts = PM_ERR_LOGREC; + } +diff -Naurp pcp-5.0.2.orig/src/libpcp/src/logutil.c pcp-5.0.2/src/libpcp/src/logutil.c +--- pcp-5.0.2.orig/src/libpcp/src/logutil.c 2018-07-08 10:58:08.000000000 +1000 ++++ pcp-5.0.2/src/libpcp/src/logutil.c 2020-02-03 13:23:15.263762911 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2017 Red Hat. ++ * Copyright (c) 2012-2017,2020 Red Hat. + * Copyright (c) 1995-2002,2004 Silicon Graphics, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or modify it +@@ -764,6 +764,22 @@ __pmLogClose(__pmArchCtl *acp) + } + + int ++__pmLogAddVolume(__pmArchCtl *acp, unsigned int vol) ++{ ++ __pmLogCtl *lcp = acp->ac_log; ++ ++ if (lcp->l_minvol == -1) { ++ lcp->l_minvol = vol; ++ lcp->l_maxvol = vol; ++ } else if (vol < lcp->l_minvol) { ++ lcp->l_minvol = vol; ++ } else if (vol > lcp->l_maxvol) { ++ lcp->l_maxvol = vol; ++ } ++ return 0; ++} ++ ++int + __pmLogLoadLabel(__pmArchCtl *acp, const char *name) + { + __pmLogCtl *lcp = acp->ac_log; +@@ -876,21 +892,14 @@ __pmLogLoadLabel(__pmArchCtl *acp, const + } + } + else { +- char *q; +- int vol; +- vol = (int)strtol(tp, &q, 10); ++ char *q; ++ unsigned int vol; ++ ++ vol = (unsigned int)strtoul(tp, &q, 10); + if (*q == '\0') { + exists = 1; +- if (lcp->l_minvol == -1) { +- lcp->l_minvol = vol; +- lcp->l_maxvol = vol; +- } +- else { +- if (vol < lcp->l_minvol) +- lcp->l_minvol = vol; +- if (vol > lcp->l_maxvol) +- lcp->l_maxvol = vol; +- } ++ if ((sts = __pmLogAddVolume(acp, vol)) < 0) ++ goto cleanup; + } + } + } +@@ -2282,7 +2291,7 @@ __pmLogSetTime(__pmContext *ctxp) + int match = 0; + int vol; + int numti = lcp->l_numti; +- __pmFILE *f; ++ __pmFILE *f; + __pmLogTI *tip = lcp->l_ti; + double t_lo; + struct stat sbuf; +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/discover.c pcp-5.0.2/src/libpcp_web/src/discover.c +--- pcp-5.0.2.orig/src/libpcp_web/src/discover.c 2019-12-10 17:04:20.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/discover.c 2020-02-03 13:36:11.958637560 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018-2019 Red Hat. ++ * Copyright (c) 2018-2020 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 +@@ -14,6 +14,8 @@ + #include "discover.h" + #include "slots.h" + #include "util.h" ++#include ++#include + + /* Decode various archive metafile records (desc, indom, labels, helptext) */ + static int pmDiscoverDecodeMetaDesc(uint32_t *, int, pmDesc *, int *, char ***); +@@ -24,11 +26,15 @@ static int pmDiscoverDecodeMetaLabelSet( + /* array of registered callbacks, see pmDiscoverSetup() */ + static int discoverCallBackTableSize; + static pmDiscoverCallBacks **discoverCallBackTable; ++static char *pmDiscoverFlagsStr(pmDiscover *); + + /* internal hash table of discovered paths */ +-#define PM_DISCOVER_HASHTAB_SIZE 64 ++#define PM_DISCOVER_HASHTAB_SIZE 16 + static pmDiscover *discover_hashtable[PM_DISCOVER_HASHTAB_SIZE]; + ++/* pmlogger_daily log-roll lock count */ ++static int lockcnt = 0; ++ + /* FNV string hash algorithm. Return unsigned in range 0 .. limit-1 */ + static unsigned int + strhash(const char *s, unsigned int limit) +@@ -43,18 +49,38 @@ strhash(const char *s, unsigned int limi + return h % limit; + } + ++/* ctime string - note static buf is returned */ ++static char * ++stamp(void) ++{ ++ time_t now = time(NULL); ++ char *p, *c = ctime(&now); ++ ++ if ((p = strrchr(c, '\n')) != NULL) ++ *p = '\0'; ++ return c; ++} ++ + /* +- * Lookup or Add a discovered file path (directory or PCP archive file) ++ * Lookup or Add a discovered file path (directory or PCP archive file). ++ * Note: the fullpath suffix (.meta, .[0-9]+) should already be stripped. + * Return path table entry (new or existing). + */ + static pmDiscover * +-pmDiscoverLookupAdd(const char *path, pmDiscoverModule *module, void *arg) ++pmDiscoverLookupAdd(const char *fullpath, pmDiscoverModule *module, void *arg) + { + pmDiscover *p, *h; +- unsigned int k = strhash(path, PM_DISCOVER_HASHTAB_SIZE); ++ unsigned int k; ++ sds name; ++ ++ name = sdsnew(fullpath); ++ k = strhash(name, PM_DISCOVER_HASHTAB_SIZE); ++ ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverLookupAdd: name=%s\n", name); + + for (p = NULL, h = discover_hashtable[k]; h != NULL; p = h, h = h->next) { +- if (strcmp(h->context.name, path) == 0) ++ if (sdscmp(h->context.name, name) == 0) + break; + } + +@@ -65,14 +91,24 @@ pmDiscoverLookupAdd(const char *path, pm + h->ctx = -1; /* no PMAPI context initially */ + h->flags = PM_DISCOVER_FLAGS_NEW; + h->context.type = PM_CONTEXT_ARCHIVE; +- h->context.name = sdsnew(path); ++ h->context.name = name; + h->module = module; + h->data = arg; + if (p == NULL) + discover_hashtable[k] = h; + else + p->next = h; ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverLookupAdd: --> new entry %s\n", name); ++ ++ } ++ else { ++ /* already in hash table, so free the buffer */ ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverLookupAdd: --> existing entry %s\n", name); ++ sdsfree(name); + } ++ + return h; + } + +@@ -82,12 +118,6 @@ pmDiscoverLookup(const char *path) + return pmDiscoverLookupAdd(path, NULL, NULL); + } + +-static pmDiscover * +-pmDiscoverAdd(const char *path, pmDiscoverModule *module, void *arg) +-{ +- return pmDiscoverLookupAdd(path, module, arg); +-} +- + static void + pmDiscoverFree(pmDiscover *p) + { +@@ -101,39 +131,42 @@ pmDiscoverFree(pmDiscover *p) + sdsfree(p->context.source); + if (p->context.labelset) + pmFreeLabelSets(p->context.labelset, 1); ++ if (p->event_handle) { ++ uv_fs_event_stop(p->event_handle); ++ free(p->event_handle); ++ p->event_handle = NULL; ++ } ++ + memset(p, 0, sizeof(*p)); + free(p); + } + + /* +- * Delete tracking of a previously discovered path. Frees resources and +- * destroy PCP context (if any). ++ * Traverse and invoke callback for all paths matching any bit ++ * in the flags bitmap. Callback can be NULL to just get a count. ++ * Return count of matching paths, may be 0. + */ +-static void +-pmDiscoverDelete(sds path) ++static int ++pmDiscoverTraverse(unsigned int flags, void (*callback)(pmDiscover *)) + { +- pmDiscover *p, *h; +- unsigned int k = strhash(path, PM_DISCOVER_HASHTAB_SIZE); ++ int count = 0, i; ++ pmDiscover *p; + +- for (p = NULL, h = discover_hashtable[k]; h != NULL; p = h, h = h->next) { +- if (sdscmp(h->context.name, path) == 0) { +- if (p == NULL) +- discover_hashtable[k] = NULL; +- else +- p->next = h->next; +- pmDiscoverFree(h); +- break; ++ for (i = 0; i < PM_DISCOVER_HASHTAB_SIZE; i++) { ++ for (p = discover_hashtable[i]; p; p = p->next) { ++ if (p->flags & flags) { ++ if (callback) ++ callback(p); ++ count++; ++ } + } + } ++ return count; + } + +-/* +- * Traverse and invoke callback for all paths matching any bit +- * in the flags bitmap. Callback can be NULL to just get a count. +- * Return count of matching paths, may be 0. +- */ ++/* as above, but with an extra (void *)arg passed to the cb */ + static int +-pmDiscoverTraverse(unsigned int flags, void (*callback)(pmDiscover *)) ++pmDiscoverTraverseArg(unsigned int flags, void (*callback)(pmDiscover *, void *), void *arg) + { + int count = 0, i; + pmDiscover *p; +@@ -142,7 +175,7 @@ pmDiscoverTraverse(unsigned int flags, v + for (p = discover_hashtable[i]; p; p = p->next) { + if (p->flags & flags) { + if (callback) +- callback(p); ++ callback(p, arg); + count++; + } + } +@@ -150,6 +183,7 @@ pmDiscoverTraverse(unsigned int flags, v + return count; + } + ++ + /* + * Traverse and purge deleted entries + * Return count of purged entries. +@@ -173,6 +207,9 @@ pmDiscoverPurgeDeleted(void) + prev->next = next; + else + discover_hashtable[i] = next; ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverPurgeDeleted: deleted %s %s\n", ++ p->context.name, pmDiscoverFlagsStr(p)); + pmDiscoverFree(p); + count++; + } +@@ -180,14 +217,32 @@ pmDiscoverPurgeDeleted(void) + } + } + +- if (pmDebugOptions.discovery) +- fprintf(stderr, "%s: purged %d entries\n", +- "pmDiscoverPurgeDeleted", count); +- + return count; + } + + /* ++ * if string ends with given suffix then return pointer ++ * to start of suffix in string, else NULL ++ */ ++static char * ++strsuffix(char *s, const char *suffix) ++{ ++ int slen, suflen; ++ char *ret = NULL; ++ ++ if (s && suffix) { ++ slen = strlen(s); ++ suflen = strlen(suffix); ++ if (slen >= suflen) { ++ ret = s + (slen - suflen); ++ if (strncmp(ret, suffix, suflen) != 0) ++ ret = NULL; ++ } ++ } ++ return ret; ++} ++ ++/* + * Discover dirs and archives - add new entries or refresh existing. + * Call this for each top-level directory. Discovered paths are not + * automatically monitored. After discovery, need to traverse and +@@ -196,44 +251,88 @@ pmDiscoverPurgeDeleted(void) + static int + pmDiscoverArchives(const char *dir, pmDiscoverModule *module, void *arg) + { +- uv_fs_t sreq, req; +- uv_dirent_t dent; +- uv_stat_t *s; ++ DIR *dirp; ++ struct dirent *dent; ++ struct stat *s; ++ struct stat statbuf; + pmDiscover *a; ++ char *suffix; + char path[MAXNAMELEN]; +- char basepath[MAXNAMELEN]; + int sep = pmPathSeparator(); ++ int vol; ++ ++ /* ++ * note: pmDiscoverLookupAdd sets PM_DISCOVER_FLAGS_NEW ++ * if this is a newly discovered archive or directory ++ */ ++ a = pmDiscoverLookupAdd(dir, module, arg); ++ a->flags |= PM_DISCOVER_FLAGS_DIRECTORY; + +- if (uv_fs_scandir(NULL, &req, dir, 0, NULL) < 0) ++ if ((dirp = opendir(dir)) == NULL) { ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverArchives: opendir %s failed %s: err %d\n", dir, path, errno); + return -ESRCH; ++ } + +- a = pmDiscoverAdd(dir, module, arg); +- a->flags |= PM_DISCOVER_FLAGS_DIRECTORY; ++ while ((dent = readdir(dirp)) != NULL) { ++ if (dent->d_name[0] == '.') ++ continue; ++ pmsprintf(path, sizeof(path), "%s%c%s", dir, sep, dent->d_name); ++ ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverArchives: readdir found %s\n", path); + +- while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { +- pmsprintf(path, sizeof(path), "%s%c%s", dir, sep, dent.name); +- if (uv_fs_stat(NULL, &sreq, path, NULL) < 0) ++ if (stat(path, &statbuf) < 0) { ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverArchives: stat failed %s, err %d\n", path, errno); + continue; +- s = &sreq.statbuf; +- strncpy(basepath, path, sizeof(basepath)); /* __pmLogBaseName modifies it's argument */ +- if (S_ISREG(s->st_mode) && __pmLogBaseName(basepath) != NULL) { +- /* +- * An archive file (index, meta or data vol). If compressed, then +- * it is read-only and we don't have to monitor it for growth. +- */ +- a = pmDiscoverAdd(path, module, arg); +- a->flags &= ~PM_DISCOVER_FLAGS_DELETED; ++ } + +- if (strstr(path, ".meta")) +- a->flags |= PM_DISCOVER_FLAGS_META; +- else if (strstr(path, ".index")) +- a->flags |= PM_DISCOVER_FLAGS_INDEX; +- else +- a->flags |= PM_DISCOVER_FLAGS_DATAVOL; +- +- /* compare to libpcp io.c for suffix list */ +- if (strstr(path, ".xz") || strstr(path, ".gz")) +- a->flags |= PM_DISCOVER_FLAGS_COMPRESSED; ++ s = &statbuf; ++ if (S_ISREG(s->st_mode)) { ++ if ((suffix = strsuffix(path, ".meta")) != NULL) { ++ /* ++ * An uncompressed PCP archive meta file. Track the meta ++ * file - the matching logvol filename varies because logvols ++ * are periodically rolled by pmlogger. Importantly, process all ++ * available metadata to EOF before processing any logvol data. ++ */ ++ *suffix = '\0'; /* strip suffix from path giving archive name */ ++ a = pmDiscoverLookupAdd(path, module, arg); ++ ++ /* ++ * note: pmDiscoverLookupAdd sets PM_DISCOVER_FLAGS_NEW ++ * if this is a newly discovered archive, otherwise we're ++ * already tracking this archive. ++ */ ++ a->flags |= PM_DISCOVER_FLAGS_META; ++ } ++ else if ((suffix = __pmLogBaseNameVol(path, &vol)) != NULL && vol >= 0) { ++ /* ++ * An archive logvol. This logvol may have been created since ++ * the context was first opened. Update the context maxvol ++ * to be sure pmFetchArchive can switch to it in due course. ++ */ ++ if ((a = pmDiscoverLookup(path)) != NULL) { ++ a->flags |= PM_DISCOVER_FLAGS_DATAVOL; ++ /* ensure archive context knows about this volume */ ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverArchives: found logvol %s %s vol=%d\n", ++ a->context.name, pmDiscoverFlagsStr(a), vol); ++ if (a->ctx >= 0 && vol >= 0) { ++ __pmContext *ctxp = __pmHandleToPtr(a->ctx); ++ __pmArchCtl *acp = ctxp->c_archctl; ++ ++ __pmLogAddVolume(acp, vol); ++ PM_UNLOCK(ctxp->c_lock); ++ } ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "pmDiscoverArchives: added logvol %s %s vol=%d\n", ++ a->context.name, pmDiscoverFlagsStr(a), vol); ++ } ++ } else if (pmDebugOptions.discovery) { ++ fprintf(stderr, "pmDiscoverArchives: ignored regular file %s\n", path); ++ } + } + else if (S_ISDIR(s->st_mode)) { + /* +@@ -241,29 +340,117 @@ pmDiscoverArchives(const char *dir, pmDi + */ + pmDiscoverArchives(path, module, arg); + } +- uv_fs_req_cleanup(&sreq); + } +- uv_fs_req_cleanup(&req); ++ if (dirp) ++ closedir(dirp); + + /* success */ + return 0; + } + ++/* ++ * Return 1 if monitored path has been deleted. ++ * For archives, we only check the meta file because ++ * a logvol can be deleted (e.g. via compression when ++ * the logvol is rolled to a new volume) without ++ * actually deleting the archive. ++ */ ++static int ++is_deleted(pmDiscover *p, struct stat *sbuf) ++{ ++ int ret = 0; ++ ++ if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { ++ if (stat(p->context.name, sbuf) < 0) ++ ret = 1; /* directory has been deleted */ ++ } ++ ++ if (p->flags & (PM_DISCOVER_FLAGS_META|PM_DISCOVER_FLAGS_DATAVOL)) { ++ sds meta = sdsnew(p->context.name); ++ meta = sdscat(meta, ".meta"); ++ if (stat(meta, sbuf) < 0) { ++ /* ++ * Archive metadata file has been deleted (or compressed) ++ * hence consider the archive to be deleted because there ++ * is no more data to logtail. ++ */ ++ ret = 1; ++ } ++ sdsfree(meta); ++ } ++ ++ if (pmDebugOptions.discovery) { ++ fprintf(stderr, "is_deleted: checking %s (%s) -> %s\n", ++ p->context.name, pmDiscoverFlagsStr(p), ret ? "DELETED" : "no"); ++ } ++ ++ return ret; ++} ++ ++static void ++logdir_is_locked_callBack(pmDiscover *p, void *arg) ++{ ++ int *cntp = (int *)arg; ++ char sep = pmPathSeparator(); ++ char path[MAXNAMELEN]; ++ ++ pmsprintf(path, sizeof(path), "%s%c%s", p->context.name, sep, "lock"); ++ if (access(path, F_OK) == 0) ++ (*cntp)++; ++} ++ ++static void ++check_deleted(pmDiscover *p) ++{ ++ struct stat sbuf; ++ if (!(p->flags & PM_DISCOVER_FLAGS_DELETED) && is_deleted(p, &sbuf)) ++ p->flags |= PM_DISCOVER_FLAGS_DELETED; ++} ++ + static void + fs_change_callBack(uv_fs_event_t *handle, const char *filename, int events, int status) + { + char buffer[MAXNAMELEN]; + size_t bytes = sizeof(buffer) - 1; + pmDiscover *p; +- uv_fs_t sreq; ++ char *s; + sds path; +- int path_changed = 0; ++ int count = 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. ++ */ ++ pmDiscoverTraverseArg(PM_DISCOVER_FLAGS_DIRECTORY, ++ logdir_is_locked_callBack, (void *)&count); ++ ++ if (lockcnt == 0 && count > 0) { ++ /* log-rolling has started */ ++ fprintf(stderr, "%s discovery callback ignored: log-rolling is now in progress\n", stamp()); ++ lockcnt = count; ++ return; ++ } ++ ++ if (lockcnt > 0 && count > 0) { ++ /* log-rolling is still in progress */ ++ lockcnt = count; ++ return; ++ } ++ ++ if (lockcnt > 0 && count == 0) { ++ /* log-rolling is finished: check what got deleted, and then purge */ ++ fprintf(stderr, "%s discovery callback: finished log-rolling\n", stamp()); ++ pmDiscoverTraverse(PM_DISCOVER_FLAGS_META|PM_DISCOVER_FLAGS_DATAVOL, check_deleted); ++ } ++ lockcnt = count; + + uv_fs_event_getpath(handle, buffer, &bytes); + path = sdsnewlen(buffer, bytes); + + if (pmDebugOptions.discovery) { +- fprintf(stderr, "%s: event on %s -", "fs_change_callBack", path); ++ fprintf(stderr, "fs_change_callBack: event on %s -", path); + if (events & UV_RENAME) + fprintf(stderr, " renamed"); + if (events & UV_CHANGE) +@@ -271,38 +458,40 @@ fs_change_callBack(uv_fs_event_t *handle + fputc('\n', stderr); + } + ++ + /* +- * Lookup the path, stat and update it's flags accordingly. If the +- * path has been deleted, stop it's event monitor and free the req buffer. +- * Then call the pmDiscovery callback. ++ * Strip ".meta" suffix (if any) and lookup the path. stat and update it's ++ * flags accordingly. If the path has been deleted, stop it's event monitor ++ * and free the req buffer, else call the pmDiscovery callback. + */ +- if ((p = pmDiscoverLookup(path)) == NULL) { ++ if ((s = strsuffix(path, ".meta")) != NULL) ++ *s = '\0'; ++ ++ p = pmDiscoverLookup(path); ++ if (p && pmDebugOptions.discovery) { ++ fprintf(stderr, "fs_change_callBack: ---> found entry %s (%s)\n", ++ p->context.name, pmDiscoverFlagsStr(p)); ++ } ++ ++ if (p == NULL) { + if (pmDebugOptions.discovery) +- fprintf(stderr, "%s: filename %s lookup failed\n", +- "fs_change_callBack", filename); ++ fprintf(stderr, "fs_change_callBack: %s lookup failed\n", filename); + } +- else if (uv_fs_stat(NULL, &sreq, p->context.name, NULL) < 0) { +- p->flags |= PM_DISCOVER_FLAGS_DELETED; +- if (p->event_handle) { +- uv_fs_event_stop(p->event_handle); +- free(p->event_handle); +- p->event_handle = NULL; +- } ++ else if (is_deleted(p, &statbuf)) { + /* path has been deleted. statbuf is invalid */ ++ p->flags |= PM_DISCOVER_FLAGS_DELETED; + memset(&p->statbuf, 0, sizeof(p->statbuf)); +- path_changed = 1; +- } +- else { +- /* avoid spurious events. only call the callBack if it really changed */ +- if (p->statbuf.st_mtim.tv_sec != sreq.statbuf.st_mtim.tv_sec || +- p->statbuf.st_mtim.tv_nsec != sreq.statbuf.st_mtim.tv_nsec) +- path_changed = 1; +- p->statbuf = sreq.statbuf; /* struct copy */ +- uv_fs_req_cleanup(&sreq); ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "fs_change_callBack: %s (%s) has been deleted", ++ p->context.name, pmDiscoverFlagsStr(p)); + } + +- if (p && p->changed && path_changed && !(p->flags & PM_DISCOVER_FLAGS_DELETED)) +- p->changed(p); ++ /* ++ * Something in the directory changed - new or deleted archive, or ++ * a tracked archive meta data file or logvolume grew ++ */ ++ if (p) ++ p->changed(p); /* returns immediately if PM_DISCOVER_FLAGS_DELETED */ + + sdsfree(path); + } +@@ -316,9 +505,14 @@ pmDiscoverMonitor(sds path, void (*callb + { + discoverModuleData *data; + pmDiscover *p; ++ sds eventfilename; + +- if ((p = pmDiscoverLookup(path)) == NULL) ++ if ((p = pmDiscoverLookup(path)) == NULL) { ++ if (pmDebugOptions.discovery) { ++ fprintf(stderr, "pmDiscoverMonitor: lookup failed for %s\n", path); ++ } + return -ESRCH; ++ } + data = getDiscoverModuleData(p->module); + + /* save the discovery callback to be invoked */ +@@ -330,9 +524,29 @@ pmDiscoverMonitor(sds path, void (*callb + * Start monitoring, using given uv loop. Up to the caller to create + * a PCP PMAPI context and to fetch/logtail in the changed callback. + */ ++ eventfilename = sdsnew(p->context.name); + uv_fs_event_init(data->events, p->event_handle); +- uv_fs_event_start(p->event_handle, fs_change_callBack, p->context.name, ++ ++ if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { ++ uv_fs_event_start(p->event_handle, fs_change_callBack, eventfilename, ++ UV_FS_EVENT_WATCH_ENTRY); ++ } ++ else { ++ /* ++ * Monitor an archive file. This tracks the archive meta file ++ * but the change callback processes both meta and logvol on ++ * every callback (meta before logvol). ++ */ ++ eventfilename = sdscat(eventfilename, ".meta"); ++ uv_fs_event_start(p->event_handle, fs_change_callBack, eventfilename, + UV_FS_EVENT_WATCH_ENTRY); ++ } ++ ++ if (pmDebugOptions.discovery) { ++ fprintf(stderr, "pmDiscoverMonitor: added event for %s (%s)\n", ++ eventfilename, pmDiscoverFlagsStr(p)); ++ } ++ sdsfree(eventfilename); + } + + return 0; +@@ -411,41 +625,23 @@ static void changed_callback(pmDiscover + static void + created_callback(pmDiscover *p) + { ++ if (p->flags & (PM_DISCOVER_FLAGS_COMPRESSED|PM_DISCOVER_FLAGS_INDEX)) ++ return; /* compressed archives don't grow and we ignore archive index files */ ++ + if (pmDebugOptions.discovery) + fprintf(stderr, "CREATED %s, %s\n", p->context.name, pmDiscoverFlagsStr(p)); + +- p->flags &= ~PM_DISCOVER_FLAGS_NEW; +- +- if (p->flags & PM_DISCOVER_FLAGS_COMPRESSED) +- return; /* compressed archives don't grow */ +- + if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { + if (pmDebugOptions.discovery) + fprintf(stderr, "MONITOR directory %s\n", p->context.name); + pmDiscoverMonitor(p->context.name, changed_callback); + } +- +- if (p->flags & PM_DISCOVER_FLAGS_DATAVOL) { ++ else if (p->flags & (PM_DISCOVER_FLAGS_META|PM_DISCOVER_FLAGS_DATAVOL)) { + if (pmDebugOptions.discovery) +- fprintf(stderr, "MONITOR logvol %s\n", p->context.name); ++ fprintf(stderr, "MONITOR archive %s\n", p->context.name); + pmDiscoverMonitor(p->context.name, changed_callback); + } +- +- if (p->flags & PM_DISCOVER_FLAGS_META) { +- if (pmDebugOptions.discovery) +- fprintf(stderr, "MONITOR metadata %s\n", p->context.name); +- pmDiscoverMonitor(p->context.name, changed_callback); +- } +-} +- +-static void +-deleted_callback(pmDiscover *p) +-{ +- if (pmDebugOptions.discovery) +- fprintf(stderr, "DELETED %s (%s)\n", p->context.name, +- pmDiscoverFlagsStr(p)); +- pmDiscoverDelete(p->context.name); +- /* p is now no longer valid */ ++ p->flags &= ~PM_DISCOVER_FLAGS_NEW; + } + + static void +@@ -509,37 +705,84 @@ static void + pmDiscoverInvokeMetricCallBacks(pmDiscover *p, pmTimespec *ts, pmDesc *desc, + int numnames, char **names) + { ++ discoverModuleData *data = getDiscoverModuleData(p->module); + pmDiscoverCallBacks *callbacks; + pmDiscoverEvent event; + char buf[32]; +- int i; ++ int i, sts; + + if (pmDebugOptions.discovery) { + fprintf(stderr, "%s[%s]: %s name%s", "pmDiscoverInvokeMetricCallBacks", + timespec_str(ts, buf, sizeof(buf)), + p->context.source, numnames > 0 ? " " : "(none)\n"); + for (i = 0; i < numnames; i++) +- printf("\"%s\"%s", names[i], i < numnames - 1 ? ", " : "\n"); ++ fprintf(stderr, "[%u/%u] \"%s\"%s", i+1, numnames, names[i], ++ i < numnames - 1 ? ", " : "\n"); + pmPrintDesc(stderr, desc); + if (pmDebugOptions.labels) + fprintf(stderr, "context labels %s\n", p->context.labelset->json); + } + ++ if (data->pmids) { ++ if (dictFind(data->pmids, &desc->pmid) != NULL) ++ goto out; /* metric contains an already excluded PMID */ ++ for (i = 0; i < numnames; i++) { ++ if (regexec(&data->exclude_names, names[i], 0, NULL, 0) == 0) ++ break; ++ } ++ if (i != numnames) { ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "%s: excluding metric %s\n", ++ "pmDiscoverInvokeMetricCallBacks", names[i]); ++ /* add this pmid to the exclusion list and return early */ ++ dictAdd(data->pmids, &desc->pmid, NULL); ++ goto out; ++ } ++ } ++ if (data->indoms) { ++ if (dictFind(data->indoms, &desc->indom) != NULL) ++ goto out; /* metric contains an already excluded InDom */ ++ } ++ ++ if (p->ctx >= 0 && p->context.type == PM_CONTEXT_ARCHIVE) { ++ __pmContext *ctxp = __pmHandleToPtr(p->ctx); ++ __pmArchCtl *acp = ctxp->c_archctl; ++ char idstr[32]; ++ ++ if ((sts = __pmLogAddDesc(acp, desc)) < 0) ++ fprintf(stderr, "%s: failed to add metric descriptor for %s\n", ++ "pmDiscoverInvokeMetricCallBacks", ++ pmIDStr_r(desc->pmid, idstr, sizeof(idstr))); ++ for (i = 0; i < numnames; i++) { ++ if ((sts = __pmLogAddPMNSNode(acp, desc->pmid, names[i])) < 0) ++ fprintf(stderr, "%s: failed to add metric name %s for %s\n", ++ "pmDiscoverInvokeMetricCallBacks", names[i], ++ pmIDStr_r(desc->pmid, idstr, sizeof(idstr))); ++ } ++ PM_UNLOCK(ctxp->c_lock); ++ } ++ + discover_event_init(p, ts, &event); + for (i = 0; i < discoverCallBackTableSize; i++) { + if ((callbacks = discoverCallBackTable[i]) && + callbacks->on_metric != NULL) + callbacks->on_metric(&event, desc, numnames, names, p->data); + } ++ ++out: ++ for (i = 0; i < numnames; i++) ++ free(names[i]); ++ free(names); + } + + static void + pmDiscoverInvokeInDomCallBacks(pmDiscover *p, pmTimespec *ts, pmInResult *in) + { ++ discoverModuleData *data = getDiscoverModuleData(p->module); + pmDiscoverCallBacks *callbacks; + pmDiscoverEvent event; + char buf[32], inbuf[32]; +- int i; ++ int i, sts = PMLOGPUTINDOM_DUP; /* free after callbacks */ + + if (pmDebugOptions.discovery) { + fprintf(stderr, "%s[%s]: %s numinst %d indom %s\n", +@@ -551,22 +794,48 @@ pmDiscoverInvokeInDomCallBacks(pmDiscove + fprintf(stderr, "context labels %s\n", p->context.labelset->json); + } + ++ if (data->indoms) { ++ if (dictFind(data->indoms, &in->indom) != NULL) ++ goto out; /* excluded InDom */ ++ } ++ ++ if (p->ctx >= 0 && p->context.type == PM_CONTEXT_ARCHIVE) { ++ __pmContext *ctxp = __pmHandleToPtr(p->ctx); ++ __pmArchCtl *acp = ctxp->c_archctl; ++ char errmsg[PM_MAXERRMSGLEN]; ++ ++ if ((sts = __pmLogAddInDom(acp, ts, in, NULL, 0)) < 0) ++ fprintf(stderr, "%s: failed to add indom for %s: %s\n", ++ "pmDiscoverInvokeInDomCallBacks", pmIDStr(in->indom), ++ pmErrStr_r(sts, errmsg, sizeof(errmsg))); ++ PM_UNLOCK(ctxp->c_lock); ++ } ++ + discover_event_init(p, ts, &event); + for (i = 0; i < discoverCallBackTableSize; i++) { + if ((callbacks = discoverCallBackTable[i]) && + callbacks->on_indom != NULL) + callbacks->on_indom(&event, in, p->data); + } ++ ++out: ++ if (sts == PMLOGPUTINDOM_DUP) { ++ for (i = 0; i < in->numinst; i++) ++ free(in->namelist[i]); ++ free(in->namelist); ++ free(in->instlist); ++ } + } + + static void + pmDiscoverInvokeLabelsCallBacks(pmDiscover *p, pmTimespec *ts, + int ident, int type, pmLabelSet *sets, int nsets) + { ++ discoverModuleData *data = getDiscoverModuleData(p->module); + pmDiscoverCallBacks *callbacks; + pmDiscoverEvent event; + char buf[32], idbuf[64]; +- int i; ++ int i, sts = -EAGAIN; /* free labelsets after callbacks */ + + if (pmDebugOptions.discovery) { + __pmLabelIdentString(ident, type, idbuf, sizeof(idbuf)); +@@ -579,22 +848,48 @@ pmDiscoverInvokeLabelsCallBacks(pmDiscov + fprintf(stderr, "context labels %s\n", p->context.labelset->json); + } + ++ if ((type & PM_LABEL_ITEM) && data->pmids) { ++ if (dictFind(data->pmids, &ident) != NULL) ++ goto out; /* text from an already excluded InDom */ ++ } ++ if ((type & (PM_LABEL_INDOM|PM_LABEL_INSTANCES)) && data->indoms) { ++ if (dictFind(data->indoms, &ident) != NULL) ++ goto out; /* text from an already excluded InDom */ ++ } ++ ++ if (p->ctx >= 0 && p->context.type == PM_CONTEXT_ARCHIVE) { ++ __pmContext *ctxp = __pmHandleToPtr(p->ctx); ++ __pmArchCtl *acp = ctxp->c_archctl; ++ char errmsg[PM_MAXERRMSGLEN]; ++ ++ if ((sts = __pmLogAddLabelSets(acp, ts, type, ident, nsets, sets)) < 0) ++ fprintf(stderr, "%s: failed to add log labelset: %s\n", ++ "pmDiscoverInvokeLabelsCallBacks", ++ pmErrStr_r(sts, errmsg, sizeof(errmsg))); ++ PM_UNLOCK(ctxp->c_lock); ++ } ++ + discover_event_init(p, ts, &event); + for (i = 0; i < discoverCallBackTableSize; i++) { + if ((callbacks = discoverCallBackTable[i]) && + callbacks->on_labels != NULL) + callbacks->on_labels(&event, ident, type, sets, nsets, p->data); + } ++ ++out: ++ if (sts < 0) ++ pmFreeLabelSets(sets, nsets); + } + + static void + pmDiscoverInvokeTextCallBacks(pmDiscover *p, pmTimespec *ts, + int ident, int type, char *text) + { ++ discoverModuleData *data = getDiscoverModuleData(p->module); + pmDiscoverCallBacks *callbacks; + pmDiscoverEvent event; + char buf[32]; +- int i; ++ int i, sts; + + if (pmDebugOptions.discovery) { + fprintf(stderr, "%s[%s]: %s ", "pmDiscoverInvokeTextCallBacks", +@@ -612,12 +907,36 @@ pmDiscoverInvokeTextCallBacks(pmDiscover + fprintf(stderr, "context labels %s\n", p->context.labelset->json); + } + ++ if ((type & PM_TEXT_PMID) && data->pmids) { ++ if (dictFind(data->pmids, &ident) != NULL) ++ goto out; /* text from an already excluded InDom */ ++ } ++ if ((type & PM_TEXT_INDOM) && data->indoms) { ++ if (dictFind(data->indoms, &ident) != NULL) ++ goto out; /* text from an already excluded InDom */ ++ } ++ ++ if (p->ctx >= 0 && p->context.type == PM_CONTEXT_ARCHIVE) { ++ __pmContext *ctxp = __pmHandleToPtr(p->ctx); ++ __pmArchCtl *acp = ctxp->c_archctl; ++ char errmsg[PM_MAXERRMSGLEN]; ++ ++ if ((sts = __pmLogAddText(acp, ident, type, text)) < 0) ++ fprintf(stderr, "%s: failed to add %u text for %u: %s\n", ++ "pmDiscoverInvokeTextCallBacks", type, ident, ++ pmErrStr_r(sts, errmsg, sizeof(errmsg))); ++ PM_UNLOCK(ctxp->c_lock); ++ } ++ + discover_event_init(p, ts, &event); + for (i = 0; i < discoverCallBackTableSize; i++) { + if ((callbacks = discoverCallBackTable[i]) && + callbacks->on_text != NULL) + callbacks->on_text(&event, ident, type, text, p->data); + } ++ ++out: ++ free(text); + } + + static void +@@ -645,8 +964,8 @@ pmDiscoverNewSource(pmDiscover *p, int c + p->context.labelset = labelset; + + /* use timestamp from file creation as starting time */ +- timestamp.tv_sec = p->statbuf.st_birthtim.tv_sec; +- timestamp.tv_nsec = p->statbuf.st_birthtim.tv_nsec; ++ timestamp.tv_sec = p->statbuf.st_ctim.tv_sec; ++ timestamp.tv_nsec = p->statbuf.st_ctim.tv_nsec; + + /* inform utilities that a source has been discovered */ + pmDiscoverInvokeSourceCallBacks(p, ×tamp); +@@ -664,7 +983,7 @@ process_metadata(pmDiscover *p) + pmDesc desc; + off_t off; + char *buffer; +- int e, i, nb, len, nsets; ++ int e, nb, len, nsets; + int type, id; /* pmID or pmInDom */ + int nnames; + char **names; +@@ -674,6 +993,8 @@ process_metadata(pmDiscover *p) + __pmLogHdr hdr; + sds msg, source; + static uint32_t *buf = NULL; ++ int deleted; ++ struct stat sbuf; + static int buflen = 0; + + /* +@@ -683,14 +1004,17 @@ process_metadata(pmDiscover *p) + */ + p->flags |= PM_DISCOVER_FLAGS_META_IN_PROGRESS; + if (pmDebugOptions.discovery) +- fprintf(stderr, "%s: in progress, flags=%s\n", +- "process_metadata", pmDiscoverFlagsStr(p)); ++ fprintf(stderr, "process_metadata: %s in progress %s\n", ++ p->context.name, pmDiscoverFlagsStr(p)); + for (;;) { + off = lseek(p->fd, 0, SEEK_CUR); + nb = read(p->fd, &hdr, sizeof(__pmLogHdr)); + +- if (nb <= 0) { +- /* we're at EOF or an error. But may still be part way through a record */ ++ deleted = is_deleted(p, &sbuf); ++ if (nb <= 0 || deleted) { ++ /* we're at EOF or an error, or deleted. But may still be part way through a record */ ++ if (deleted) ++ p->flags |= PM_DISCOVER_FLAGS_DELETED; + break; + } + +@@ -750,10 +1074,6 @@ process_metadata(pmDiscover *p) + ts.tv_sec = p->statbuf.st_mtim.tv_sec; + ts.tv_nsec = p->statbuf.st_mtim.tv_nsec; + pmDiscoverInvokeMetricCallBacks(p, &ts, &desc, nnames, names); +- for (i = 0; i < nnames; i++) +- free(names[i]); +- if (names) +- free(names); + break; + + case TYPE_INDOM: +@@ -765,12 +1085,6 @@ process_metadata(pmDiscover *p) + break; + } + pmDiscoverInvokeInDomCallBacks(p, &ts, &inresult); +- if (inresult.numinst > 0) { +- for (i = 0; i < inresult.numinst; i++) +- free(inresult.namelist[i]); +- free(inresult.namelist); +- free(inresult.instlist); +- } + break; + + case TYPE_LABEL: +@@ -795,13 +1109,13 @@ process_metadata(pmDiscover *p) + } else { + sdsfree(p->context.source); + p->context.source = source; +- p->context.labelset = labelset; ++ if (p->context.labelset) ++ pmFreeLabelSets(p->context.labelset, 1); ++ p->context.labelset = __pmDupLabelSets(labelset, 1); + pmDiscoverInvokeSourceCallBacks(p, &ts); + } + } + pmDiscoverInvokeLabelsCallBacks(p, &ts, id, type, labelset, nsets); +- if (labelset != p->context.labelset) +- pmFreeLabelSets(labelset, nsets); + break; + + case TYPE_TEXT: +@@ -819,8 +1133,6 @@ process_metadata(pmDiscover *p) + ts.tv_sec = p->statbuf.st_mtim.tv_sec; + ts.tv_nsec = p->statbuf.st_mtim.tv_nsec; + pmDiscoverInvokeTextCallBacks(p, &ts, id, type, buffer); +- if (buffer) +- free(buffer); + break; + + default: +@@ -833,38 +1145,89 @@ process_metadata(pmDiscover *p) + } + + if (partial == 0) +- /* flag that all available metadata has been now been read */ ++ /* flag that all available metadata has now been read */ + p->flags &= ~PM_DISCOVER_FLAGS_META_IN_PROGRESS; + + if (pmDebugOptions.discovery) +- fprintf(stderr, "%s : completed, partial=%d flags=%s\n", +- "process_metadata", partial, pmDiscoverFlagsStr(p)); ++ fprintf(stderr, "%s: completed, partial=%d %s %s\n", ++ "process_metadata", partial, p->context.name, pmDiscoverFlagsStr(p)); + } + + /* +- * fetch metric values to EOF and call all registered callbacks ++ * Fetch metric values to EOF and call all registered callbacks. ++ * Always process metadata thru to EOF before any logvol data. + */ + static void +-process_logvol_callback(pmDiscover *p) ++process_logvol(pmDiscover *p) + { ++ int sts; + pmResult *r; + pmTimespec ts; ++ int oldcurvol; ++ __pmContext *ctxp; ++ __pmArchCtl *acp; ++ ++ for (;;) { ++ pmUseContext(p->ctx); ++ ctxp = __pmHandleToPtr(p->ctx); ++ acp = ctxp->c_archctl; ++ oldcurvol = acp->ac_curvol; ++ PM_UNLOCK(ctxp->c_lock); ++ ++ if ((sts = pmFetchArchive(&r)) < 0) { ++ /* err handling to skip to the next vol */ ++ ctxp = __pmHandleToPtr(p->ctx); ++ acp = ctxp->c_archctl; ++ if (oldcurvol < acp->ac_curvol) { ++ __pmLogChangeVol(acp, acp->ac_curvol); ++ acp->ac_offset = 0; /* __pmLogFetch will fix it up */ ++ } ++ PM_UNLOCK(ctxp->c_lock); ++ ++ if (sts == PM_ERR_EOL) { ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "process_logvol: %s end of archive reached\n", ++ p->context.name); ++ ++ /* succesfully processed to current end of log */ ++ break; ++ } else { ++ /* ++ * This log vol was probably deleted (likely compressed) ++ * under our feet. Try and skip to the next volume. ++ * We hold the context lock during error recovery here. ++ */ ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "process_logvol: %s fetch failed:%s\n", ++ p->context.name, pmErrStr(sts)); ++ } + +- pmUseContext(p->ctx); +- while (pmFetchArchive(&r) == 0) { ++ /* we are done - return and wait for another callback */ ++ break; ++ } ++ ++ /* ++ * Fetch succeeded - call the values callback and continue ++ */ + if (pmDebugOptions.discovery) { + char tbuf[64], bufs[64]; + +- fprintf(stderr, "FETCHED @%s [%s] %d metrics\n", +- timeval_str(&r->timestamp, tbuf, sizeof(tbuf)), ++ fprintf(stderr, "process_logvol: %s FETCHED @%s [%s] %d metrics\n", ++ p->context.name, timeval_str(&r->timestamp, tbuf, sizeof(tbuf)), + timeval_stream_str(&r->timestamp, bufs, sizeof(bufs)), + r->numpmid); + } ++ ++ /* ++ * TODO: 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; + pmDiscoverInvokeValuesCallBack(p, &ts, r); + pmFreeResult(r); + } ++ + /* datavol is now up-to-date and at EOF */ + p->flags &= ~PM_DISCOVER_FLAGS_DATAVOL_READY; + } +@@ -874,12 +1237,13 @@ pmDiscoverInvokeCallBacks(pmDiscover *p) + { + int sts; + sds msg; ++ sds metaname; + + if (p->ctx < 0) { + /* + * once off initialization on the first event + */ +- if (p->flags & PM_DISCOVER_FLAGS_DATAVOL) { ++ if (p->flags & (PM_DISCOVER_FLAGS_DATAVOL | PM_DISCOVER_FLAGS_META)) { + struct timeval tvp; + + /* create the PMAPI context (once off) */ +@@ -898,28 +1262,25 @@ pmDiscoverInvokeCallBacks(pmDiscover *p) + p->ctx = -1; + return; + } ++ /* seek to end of archive for logvol data - see TODO in process_logvol() */ + pmSetMode(PM_MODE_FORW, &tvp, 1); +- /* note: we do not scan pre-existing logvol data. */ +- } +- else if (p->flags & PM_DISCOVER_FLAGS_META) { +- if ((sts = pmNewContext(p->context.type, p->context.name)) < 0) { +- infofmt(msg, "pmNewContext failed for %s: %s\n", +- p->context.name, pmErrStr(sts)); +- moduleinfo(p->module, PMLOG_ERROR, msg, p->data); +- return; +- } +- pmDiscoverNewSource(p, sts); + +- /* for archive meta files, p->fd is the direct file descriptor */ +- if ((p->fd = open(p->context.name, O_RDONLY)) < 0) { +- infofmt(msg, "open failed for %s: %s\n", p->context.name, +- osstrerror()); ++ /* ++ * For archive meta files, p->fd is the direct file descriptor ++ * and we pre-scan existing metadata. Note: we do NOT scan ++ * pre-existing logvol data (see pmSetMode above) ++ */ ++ 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); ++ sdsfree(metaname); + return; + } +- +- /* process all existing metadata */ ++ /* pre-process all existing metadata */ + process_metadata(p); ++ sdsfree(metaname); + } + } + +@@ -943,15 +1304,61 @@ pmDiscoverInvokeCallBacks(pmDiscover *p) + } + + if (p->flags & PM_DISCOVER_FLAGS_META) { +- /* process metadata */ ++ /* process new metadata, if any */ + process_metadata(p); + } + +- /* process any unprocessed datavol callbacks */ +- pmDiscoverTraverse(PM_DISCOVER_FLAGS_DATAVOL_READY, process_logvol_callback); ++ if ((p->flags & PM_DISCOVER_FLAGS_META_IN_PROGRESS) == 0) { ++ /* no metdata read in progress, so process new datavol data, if any */ ++ process_logvol(p); ++ } ++} ++ ++static void ++print_callback(pmDiscover *p) ++{ ++ if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { ++ fprintf(stderr, " DIRECTORY %s %s\n", ++ p->context.name, pmDiscoverFlagsStr(p)); ++ } ++ else { ++ __pmContext *ctxp; ++ __pmArchCtl *acp; + +- /* finally, purge deleted entries, if any */ +- pmDiscoverPurgeDeleted(); ++ if (p->ctx >= 0 && (ctxp = __pmHandleToPtr(p->ctx)) != NULL) { ++ acp = ctxp->c_archctl; ++ fprintf(stderr, " ARCHIVE %s fd=%d ctx=%d maxvol=%d ac_curvol=%d ac_offset=%ld %s\n", ++ p->context.name, p->fd, p->ctx, acp->ac_log->l_maxvol, acp->ac_curvol, ++ acp->ac_offset, pmDiscoverFlagsStr(p)); ++ PM_UNLOCK(ctxp->c_lock); ++ } else { ++ /* no context yet - probably PM_DISCOVER_FLAGS_NEW */ ++ fprintf(stderr, " ARCHIVE %s fd=%d ctx=%d %s\n", ++ p->context.name, p->fd, p->ctx, pmDiscoverFlagsStr(p)); ++ } ++ } ++} ++ ++/* ++ * p is a tracked archive and arg is a directory path. ++ * If p is in the directory, call it's callbacks to ++ * process metadata and logvol data. This allows better ++ * scalability because we only process archives in the ++ * directories that have changed. ++ */ ++static void ++directory_changed_cb(pmDiscover *p, void *arg) ++{ ++ char *dirpath = (char *)arg; ++ int dlen = strlen(dirpath); ++ ++ if (strncmp(p->context.name, dirpath, dlen) == 0) { ++ /* this archive is in this directory - process it's metadata and logvols */ ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "directory_changed_cb: archive %s is in dir %s\n", ++ p->context.name, dirpath); ++ pmDiscoverInvokeCallBacks(p); ++ } + } + + static void +@@ -962,27 +1369,46 @@ changed_callback(pmDiscover *p) + pmDiscoverFlagsStr(p)); + + if (p->flags & PM_DISCOVER_FLAGS_DELETED) { +- /* path or directory has been deleted - remove from hash table */ +- deleted_callback(p); +- } +- else if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { + /* +- * A changed directory path means a new archive or subdirectory +- * has been created - traverse and update the hash table. ++ * Path has been deleted. Do nothing for now. Will be purged ++ * in due course by pmDiscoverPurgeDeleted. + */ +- pmDiscoverArchives(p->context.name, p->module, p->data); +- pmDiscoverTraverse(PM_DISCOVER_FLAGS_NEW, created_callback); ++ return; ++ + } +- else if (p->flags & PM_DISCOVER_FLAGS_COMPRESSED) { ++ ++ if (p->flags & PM_DISCOVER_FLAGS_COMPRESSED) { + /* we do not monitor compressed files - do nothing */ +- ; /**/ ++ return; + } +- else if (p->flags & (PM_DISCOVER_FLAGS_DATAVOL|PM_DISCOVER_FLAGS_META)) { +- /* +- * We only monitor uncompressed logvol and metadata paths. Fetch new data +- * (metadata or logvol) and call the registered callbacks. ++ ++ if (p->flags & PM_DISCOVER_FLAGS_DIRECTORY) { ++ /* ++ * A changed directory path means a new archive or subdirectory may have ++ * been created or deleted - traverse and update the hash table. + */ +- pmDiscoverInvokeCallBacks(p); ++ if (pmDebugOptions.discovery) { ++ fprintf(stderr, "%s DIRECTORY CHANGED %s (%s)\n", ++ stamp(), p->context.name, pmDiscoverFlagsStr(p)); ++ } ++ pmDiscoverArchives(p->context.name, p->module, p->data); ++ pmDiscoverTraverse(PM_DISCOVER_FLAGS_NEW, created_callback); ++ ++ /* ++ * Walk directory and invoke callbacks for tracked archives in this ++ * directory that have changed ++ */ ++ pmDiscoverTraverseArg(PM_DISCOVER_FLAGS_DATAVOL|PM_DISCOVER_FLAGS_META, ++ directory_changed_cb, (void *)p->context.name); ++ ++ /* finally, purge deleted entries (globally), if any */ ++ pmDiscoverPurgeDeleted(); ++ } ++ ++ if (pmDebugOptions.discovery) { ++ fprintf(stderr, "%s -- tracking status\n", stamp()); ++ pmDiscoverTraverse(PM_DISCOVER_FLAGS_ALL, print_callback); ++ fprintf(stderr, "--\n"); + } + } + +@@ -995,18 +1421,9 @@ dir_callback(pmDiscover *p) + static void + archive_callback(pmDiscover *p) + { +- if (p->flags & PM_DISCOVER_FLAGS_COMPRESSED) +- return; /* compressed archives don't grow */ +- +- if (p->flags & PM_DISCOVER_FLAGS_DATAVOL) { +- if (pmDebugOptions.discovery) +- fprintf(stderr, "DISCOVERED ARCHIVE LOGVOL %s\n", p->context.name); +- pmDiscoverMonitor(p->context.name, changed_callback); +- } +- + if (p->flags & PM_DISCOVER_FLAGS_META) { + if (pmDebugOptions.discovery) +- fprintf(stderr, "DISCOVERED ARCHIVE METADATA %s\n", p->context.name); ++ fprintf(stderr, "DISCOVERED ARCHIVE %s\n", p->context.name); + pmDiscoverMonitor(p->context.name, changed_callback); + } + } +@@ -1048,9 +1465,9 @@ pmDiscoverRegister(const char *dir, pmDi + } + + if (pmDebugOptions.discovery) { +- fprintf(stderr, "Now managing %d directories and %d archive files\n", ++ fprintf(stderr, "Now tracking %d directories and %d archives\n", + pmDiscoverTraverse(PM_DISCOVER_FLAGS_DIRECTORY, NULL), +- pmDiscoverTraverse(PM_DISCOVER_FLAGS_DATAVOL, NULL)); ++ pmDiscoverTraverse(PM_DISCOVER_FLAGS_DATAVOL|PM_DISCOVER_FLAGS_META, NULL)); + } + + /* monitor the directories */ +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/discover.h pcp-5.0.2/src/libpcp_web/src/discover.h +--- pcp-5.0.2.orig/src/libpcp_web/src/discover.h 2019-12-10 17:04:20.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/discover.h 2020-02-03 13:36:09.904659047 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018-2019 Red Hat. ++ * Copyright (c) 2018-2020 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 +@@ -18,7 +18,9 @@ + #include "libpcp.h" + #include "mmv_stats.h" + #include "slots.h" +- ++#ifdef HAVE_REGEX_H ++#include ++#endif + #ifdef HAVE_LIBUV + #include + #else +@@ -84,8 +86,8 @@ typedef struct pmDiscover { + int fd; /* meta file descriptor */ + #ifdef HAVE_LIBUV + uv_fs_event_t *event_handle; /* uv fs_notify event handle */ +- uv_stat_t statbuf; /* stat buffer from event CB */ + #endif ++ struct stat statbuf; /* stat buffer */ + void *baton; /* private internal lib data */ + void *data; /* opaque user data pointer */ + } pmDiscover; +@@ -115,6 +117,10 @@ typedef struct discoverModuleData { + struct dict *config; /* configuration dict */ + uv_loop_t *events; /* event library loop */ + redisSlots *slots; /* server slots data */ ++ regex_t exclude_names; /* metric names to exclude */ ++ struct dict *pmids; /* dict of excluded PMIDs */ ++ unsigned int exclude_indoms; /* exclude instance domains */ ++ struct dict *indoms; /* dict of excluded InDoms */ + void *data; /* user-supplied pointer */ + } discoverModuleData; + +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/exports pcp-5.0.2/src/libpcp_web/src/exports +--- pcp-5.0.2.orig/src/libpcp_web/src/exports 2019-11-26 16:29:58.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/exports 2020-02-03 13:23:15.264762900 +1100 +@@ -178,3 +178,8 @@ PCP_WEB_1.11 { + global: + pmSeriesLabelValues; + } PCP_WEB_1.10; ++ ++PCP_WEB_1.12 { ++ global: ++ SDS_NOINIT; ++} PCP_WEB_1.11; +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/load.c pcp-5.0.2/src/libpcp_web/src/load.c +--- pcp-5.0.2.orig/src/libpcp_web/src/load.c 2019-12-11 14:01:53.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/load.c 2020-02-03 13:36:03.947721365 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019 Red Hat. ++ * Copyright (c) 2017-2020 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 +@@ -112,22 +112,41 @@ load_prepare_metric(const char *name, vo + * Iterate over an instance domain and extract names and labels + * for each instance. + */ +-static unsigned int +-get_instance_metadata(seriesLoadBaton *baton, pmInDom indom) ++static void ++get_instance_metadata(seriesLoadBaton *baton, pmInDom indom, int force_refresh) + { + context_t *cp = &baton->pmapi.context; +- unsigned int count = 0; + domain_t *dp; + indom_t *ip; + + if (indom != PM_INDOM_NULL) { + if ((dp = pmwebapi_add_domain(cp, pmInDom_domain(indom)))) + pmwebapi_add_domain_labels(cp, dp); +- if ((ip = pmwebapi_add_indom(cp, dp, indom)) && +- (count = pmwebapi_add_indom_instances(cp, ip)) > 0) +- pmwebapi_add_instances_labels(cp, ip); ++ if ((ip = pmwebapi_add_indom(cp, dp, indom)) != NULL) { ++ if (force_refresh) ++ ip->updated = 1; ++ if (ip->updated) { ++ pmwebapi_add_indom_instances(cp, ip); ++ pmwebapi_add_instances_labels(cp, ip); ++ } ++ } + } +- return count; ++} ++ ++static void ++get_metric_metadata(seriesLoadBaton *baton, metric_t *metric) ++{ ++ context_t *context = &baton->pmapi.context; ++ ++ if (metric->cluster) { ++ if (metric->cluster->domain) ++ pmwebapi_add_domain_labels(context, metric->cluster->domain); ++ pmwebapi_add_cluster_labels(context, metric->cluster); ++ } ++ if (metric->indom) ++ pmwebapi_add_instances_labels(context, metric->indom); ++ pmwebapi_add_item_labels(context, metric); ++ pmwebapi_metric_hash(metric); + } + + static metric_t * +@@ -140,18 +159,25 @@ new_metric(seriesLoadBaton *baton, pmVal + char **nameall = NULL; + int count, sts, i; + +- if ((sts = pmLookupDesc(vsp->pmid, &desc)) < 0) { ++ if ((sts = pmUseContext(context->context)) < 0) { ++ fprintf(stderr, "%s: failed to use context for PMID %s: %s\n", ++ "new_metric", ++ pmIDStr_r(vsp->pmid, idbuf, sizeof(idbuf)), ++ pmErrStr_r(sts, errmsg, sizeof(errmsg))); ++ } else if ((sts = pmLookupDesc(vsp->pmid, &desc)) < 0) { + if (sts == PM_ERR_IPC) + context->setup = 0; + if (pmDebugOptions.series) +- fprintf(stderr, "failed to lookup metric %s descriptor: %s", ++ fprintf(stderr, "%s: failed to lookup metric %s descriptor: %s\n", ++ "new_metric", + pmIDStr_r(vsp->pmid, idbuf, sizeof(idbuf)), + pmErrStr_r(sts, errmsg, sizeof(errmsg))); + } else if ((sts = count = pmNameAll(vsp->pmid, &nameall)) < 0) { + if (sts == PM_ERR_IPC) + context->setup = 0; + if (pmDebugOptions.series) +- fprintf(stderr, "failed to lookup metric %s names: %s", ++ fprintf(stderr, "%s: failed to lookup metric %s names: %s\n", ++ "new_metric", + pmIDStr_r(vsp->pmid, idbuf, sizeof(idbuf)), + pmErrStr_r(sts, errmsg, sizeof(errmsg))); + } +@@ -160,18 +186,10 @@ new_metric(seriesLoadBaton *baton, pmVal + + if ((metric = pmwebapi_new_metric(context, NULL, &desc, count, nameall)) == NULL) + return NULL; +- if (metric->cluster) { +- if (metric->cluster->domain) +- pmwebapi_add_domain_labels(context, metric->cluster->domain); +- pmwebapi_add_cluster_labels(context, metric->cluster); +- } +- if (metric->indom) +- pmwebapi_add_instances_labels(context, metric->indom); +- pmwebapi_add_item_labels(context, metric); +- pmwebapi_metric_hash(metric); ++ get_metric_metadata(baton, metric); + + if (pmDebugOptions.series) { +- fprintf(stderr, "new_metric [%s] names:", ++ fprintf(stderr, "%s [%s] names:\n", "new_metric", + pmIDStr_r(vsp->pmid, idbuf, sizeof(idbuf))); + for (i = 0; i < count; i++) { + pmwebapi_hash_str(metric->names[i].hash, idbuf, sizeof(idbuf)); +@@ -409,7 +427,7 @@ pmwebapi_add_valueset(metric_t *metric, + } + + static void +-series_cache_update(seriesLoadBaton *baton) ++series_cache_update(seriesLoadBaton *baton, struct dict *exclude) + { + seriesGetContext *context = &baton->pmapi; + context_t *cp = &context->context; +@@ -418,7 +436,7 @@ series_cache_update(seriesLoadBaton *bat + metric_t *metric = NULL; + char ts[64]; + sds timestamp; +- int i, write_meta, write_data; ++ int i, write_meta, write_inst, write_data; + + timestamp = sdsnew(timeval_stream_str(&result->timestamp, ts, sizeof(ts))); + write_data = (!(baton->flags & PM_SERIES_FLAG_METADATA)); +@@ -441,6 +459,12 @@ series_cache_update(seriesLoadBaton *bat + dictFetchValue(baton->wanted, &vsp->pmid) == NULL) + continue; + ++ /* check if metric to be skipped (optional metric exclusion) */ ++ if (exclude && (dictFind(exclude, &vsp->pmid)) != NULL) ++ continue; ++ ++ write_meta = write_inst = 0; ++ + /* check if pmid already in hash list */ + if ((metric = dictFetchValue(cp->pmids, &vsp->pmid)) == NULL) { + /* create a new metric, and add it to load context */ +@@ -448,21 +472,22 @@ series_cache_update(seriesLoadBaton *bat + continue; + write_meta = 1; + } else { /* pmid already observed */ +- write_meta = 0; ++ if ((write_meta = metric->cached) == 0) ++ get_metric_metadata(baton, metric); + } + + /* iterate through result instances and ensure metric_t is complete */ + if (metric->error == 0 && vsp->numval < 0) + write_meta = 1; + if (pmwebapi_add_valueset(metric, vsp) != 0) +- write_meta = 1; ++ write_meta = write_inst = 1; + + /* record the error code in the cache */ + metric->error = (vsp->numval < 0) ? vsp->numval : 0; + + /* make PMAPI calls to cache metadata */ +- if (write_meta && get_instance_metadata(baton, metric->desc.indom) != 0) +- continue; ++ if (write_meta) ++ get_instance_metadata(baton, metric->desc.indom, write_inst); + + /* initiate writes to backend caching servers (Redis) */ + server_cache_metric(baton, metric, timestamp, write_meta, write_data); +@@ -549,7 +574,7 @@ server_cache_window(void *arg) + (finish->tv_sec == result->timestamp.tv_sec && + finish->tv_usec >= result->timestamp.tv_usec)) { + context->done = server_cache_update_done; +- series_cache_update(baton); ++ series_cache_update(baton, NULL); + } + else { + if (pmDebugOptions.series) +@@ -1023,7 +1048,7 @@ pmSeriesDiscoverSource(pmDiscoverEvent * + sds msg; + int i; + +- if (data == NULL || data->slots == NULL) ++ if (data == NULL || data->slots == NULL || data->slots->setup == 0) + return; + + baton = (seriesLoadBaton *)calloc(1, sizeof(seriesLoadBaton)); +@@ -1032,22 +1057,31 @@ pmSeriesDiscoverSource(pmDiscoverEvent * + moduleinfo(module, PMLOG_ERROR, msg, arg); + return; + } ++ if ((set = pmwebapi_labelsetdup(p->context.labelset)) == NULL) { ++ infofmt(msg, "%s: out of memory for labels", "pmSeriesDiscoverSource"); ++ moduleinfo(module, PMLOG_ERROR, msg, arg); ++ free(baton); ++ return; ++ } ++ + initSeriesLoadBaton(baton, module, 0 /*flags*/, + module->on_info, series_discover_done, + data->slots, arg); + initSeriesGetContext(&baton->pmapi, baton); + p->baton = baton; + ++ cp = &baton->pmapi.context; ++ + if (pmDebugOptions.discovery) +- fprintf(stderr, "%s: new source %s context=%d\n", +- "pmSeriesDiscoverSource", p->context.name, p->ctx); ++ fprintf(stderr, "%s: new source %s context=%p ctxid=%d\n", ++ "pmSeriesDiscoverSource", p->context.name, cp, p->ctx); + +- cp = &baton->pmapi.context; + cp->context = p->ctx; + cp->type = p->context.type; + cp->name.sds = sdsdup(p->context.name); +- cp->host = p->context.hostname; +- cp->labelset = set = p->context.labelset; ++ cp->host = sdsdup(p->context.hostname); ++ cp->labelset = set; ++ + pmwebapi_source_hash(cp->name.hash, set->json, set->jsonlen); + pmwebapi_setup_context(cp); + set_source_origin(cp); +@@ -1095,21 +1129,22 @@ pmSeriesDiscoverLabels(pmDiscoverEvent * + sds msg; + int i, id; + ++ if (baton == NULL || baton->slots == NULL || baton->slots->setup == 0) ++ return; ++ + switch (type) { + case PM_LABEL_CONTEXT: + if (pmDebugOptions.discovery) + fprintf(stderr, "%s: context\n", "pmSeriesDiscoverLabels"); + + if ((labels = pmwebapi_labelsetdup(sets)) != NULL) { +-#if 0 /* PCP GH#800 do not free this labelset - it's owned by the discover code */ + if (cp->labelset) + pmFreeLabelSets(cp->labelset, 1); +-#endif + cp->labelset = labels; + pmwebapi_locate_context(cp); + cp->updated = 1; + } else { +- infofmt(msg, "failed to duplicate label set"); ++ infofmt(msg, "failed to duplicate %s label set", "context"); + moduleinfo(event->module, PMLOG_ERROR, msg, arg); + } + break; +@@ -1125,8 +1160,8 @@ pmSeriesDiscoverLabels(pmDiscoverEvent * + pmFreeLabelSets(domain->labelset, 1); + domain->labelset = labels; + domain->updated = 1; +- } else { +- infofmt(msg, "failed to duplicate label set"); ++ } else if (domain) { ++ infofmt(msg, "failed to duplicate %s label set", "domain"); + moduleinfo(event->module, PMLOG_ERROR, msg, arg); + } + break; +@@ -1142,8 +1177,8 @@ pmSeriesDiscoverLabels(pmDiscoverEvent * + pmFreeLabelSets(cluster->labelset, 1); + cluster->labelset = labels; + cluster->updated = 1; +- } else { +- infofmt(msg, "failed to duplicate label set"); ++ } else if (cluster) { ++ infofmt(msg, "failed to duplicate %s label set", "cluster"); + moduleinfo(event->module, PMLOG_ERROR, msg, arg); + } + break; +@@ -1159,8 +1194,8 @@ pmSeriesDiscoverLabels(pmDiscoverEvent * + pmFreeLabelSets(metric->labelset, 1); + metric->labelset = labels; + metric->updated = 1; +- } else { +- infofmt(msg, "failed to duplicate label set"); ++ } else if (metric) { ++ infofmt(msg, "failed to duplicate %s label set", "item"); + moduleinfo(event->module, PMLOG_ERROR, msg, arg); + } + break; +@@ -1177,8 +1212,8 @@ pmSeriesDiscoverLabels(pmDiscoverEvent * + pmFreeLabelSets(indom->labelset, 1); + indom->labelset = labels; + indom->updated = 1; +- } else { +- infofmt(msg, "failed to duplicate label set"); ++ } else if (indom) { ++ infofmt(msg, "failed to duplicate %s label set", "indom"); + moduleinfo(event->module, PMLOG_ERROR, msg, arg); + } + break; +@@ -1196,7 +1231,7 @@ pmSeriesDiscoverLabels(pmDiscoverEvent * + if ((instance = dictFetchValue(indom->insts, &id)) == NULL) + continue; + if ((labels = pmwebapi_labelsetdup(&sets[i])) == NULL) { +- infofmt(msg, "failed to dup %s instance labels: %s", ++ infofmt(msg, "failed to dup indom %s instance label set: %s", + pmInDomStr_r(indom->indom, idbuf, sizeof(idbuf)), + pmErrStr_r(-ENOMEM, errmsg, sizeof(errmsg))); + moduleinfo(event->module, PMLOG_ERROR, msg, arg); +@@ -1229,10 +1264,13 @@ pmSeriesDiscoverMetric(pmDiscoverEvent * + + if (pmDebugOptions.discovery) { + for (i = 0; i < numnames; i++) +- fprintf(stderr, "pmSeriesDiscoverMetric: [%d/%d] %s - %s\n", ++ fprintf(stderr, "%s: [%d/%d] %s - %s\n", "pmSeriesDiscoverMetric", + i + 1, numnames, pmIDStr(desc->pmid), names[i]); + } + ++ if (baton == NULL || baton->slots == NULL || baton->slots->setup == 0) ++ return; ++ + if ((metric = pmwebapi_add_metric(&baton->pmapi.context, + NULL, desc, numnames, names)) == NULL) { + infofmt(msg, "%s: failed metric discovery", "pmSeriesDiscoverMetric"); +@@ -1244,18 +1282,23 @@ pmSeriesDiscoverMetric(pmDiscoverEvent * + void + pmSeriesDiscoverValues(pmDiscoverEvent *event, pmResult *result, void *arg) + { ++ pmDiscoverModule *module = event->module; + pmDiscover *p = (pmDiscover *)event->data; + seriesLoadBaton *baton = p->baton; + seriesGetContext *context = &baton->pmapi; ++ discoverModuleData *data = getDiscoverModuleData(module); + + if (pmDebugOptions.discovery) + fprintf(stderr, "%s: result numpmids=%d\n", "pmSeriesDiscoverValues", result->numpmid); + ++ if (baton == NULL || baton->slots == NULL || baton->slots->setup == 0) ++ return; ++ + seriesBatonReference(context, "pmSeriesDiscoverValues"); + baton->arg = arg; + context->result = result; + +- series_cache_update(baton); ++ series_cache_update(baton, data->pmids); + } + + void +@@ -1271,7 +1314,10 @@ pmSeriesDiscoverInDom(pmDiscoverEvent *e + int i; + + if (pmDebugOptions.discovery) +- fprintf(stderr, "pmSeriesDiscoverInDom: %s\n", pmInDomStr(id)); ++ fprintf(stderr, "%s: %s\n", "pmSeriesDiscoverInDom", pmInDomStr(id)); ++ ++ if (baton == NULL || baton->slots == NULL || baton->slots->setup == 0) ++ return; + + if ((domain = pmwebapi_add_domain(context, pmInDom_domain(id))) == NULL) { + infofmt(msg, "%s: failed indom discovery (domain %u)", +@@ -1303,11 +1349,10 @@ pmSeriesDiscoverText(pmDiscoverEvent *ev + pmDiscover *p = (pmDiscover *)event->data; + seriesLoadBaton *baton = p->baton; + +- (void)baton; +- (void)ident; +- (void)type; +- (void)text; +- (void)arg; ++ if (pmDebugOptions.discovery) ++ fprintf(stderr, "%s: ident=%u type=%u arg=%p\n", ++ "pmSeriesDiscoverText", ident, type, arg); + +- /* for Redis, help text will need special handling (RediSearch) */ ++ if (baton == NULL || baton->slots == NULL || baton->slots->setup == 0) ++ return; + } +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/query.c pcp-5.0.2/src/libpcp_web/src/query.c +--- pcp-5.0.2.orig/src/libpcp_web/src/query.c 2019-12-05 17:29:43.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/query.c 2020-02-03 13:23:15.265762890 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019 Red Hat. ++ * Copyright (c) 2017-2020 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 +@@ -1243,24 +1243,43 @@ series_prepare_time_reply( + 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]; ++ char buffer[64], revbuf[64]; + sds start, end, key, cmd; +- unsigned int i; ++ 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))); ++ } + +- start = sdsnew(timeval_stream_str(&tp->start, buffer, sizeof(buffer))); + if (pmDebugOptions.series) + fprintf(stderr, "START: %s\n", start); + +- if (tp->end.tv_sec) ++ 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); + +@@ -1277,12 +1296,21 @@ series_prepare_time(seriesQueryBaton *ba + + key = sdscatfmt(sdsempty(), "pcp:values:series:%S", sid->name); + +- /* XRANGE key t1 t2 */ +- cmd = redis_command(4); +- cmd = redis_param_str(cmd, XRANGE, XRANGE_LEN); ++ /* 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); ++ } + redisSlotsRequest(baton->slots, XRANGE, key, cmd, + series_prepare_time_reply, sid); + } +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/schema.c pcp-5.0.2/src/libpcp_web/src/schema.c +--- pcp-5.0.2.orig/src/libpcp_web/src/schema.c 2019-11-18 19:35:11.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/schema.c 2020-02-03 13:36:03.948721355 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019 Red Hat. ++ * Copyright (c) 2017-2020 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 +@@ -819,7 +819,7 @@ redis_series_metric(redisSlots *slots, m + */ + + /* ensure all metric name strings are mapped */ +- for (i = 0; i < metric->numnames; i++) { ++ for (i = 0; metric->cached == 0 && i < metric->numnames; i++) { + assert(metric->names[i].sds != NULL); + seriesBatonReference(baton, "redis_series_metric"); + redisGetMap(slots, +@@ -830,7 +830,8 @@ redis_series_metric(redisSlots *slots, m + + /* ensure all metric or instance label strings are mapped */ + if (metric->desc.indom == PM_INDOM_NULL || metric->u.vlist == NULL) { +- series_metric_label_mapping(metric, baton); ++ if (metric->cached == 0) ++ series_metric_label_mapping(metric, baton); + } else { + for (i = 0; i < metric->u.vlist->listcount; i++) { + value = &metric->u.vlist->value[i]; +@@ -847,7 +848,8 @@ redis_series_metric(redisSlots *slots, m + series_name_mapping_callback, + baton->info, baton->userdata, baton); + +- series_instance_label_mapping(metric, instance, baton); ++ if (instance->cached == 0) ++ series_instance_label_mapping(metric, instance, baton); + } + } + +@@ -941,6 +943,9 @@ redis_series_metadata(context_t *context + sds cmd, key; + int i; + ++ if (metric->cached) ++ goto check_instances; ++ + indom = pmwebapi_indom_str(metric, ibuf, sizeof(ibuf)); + pmid = pmwebapi_pmid_str(metric, pbuf, sizeof(pbuf)); + sem = pmwebapi_semantics_str(metric, sbuf, sizeof(sbuf)); +@@ -1000,16 +1005,24 @@ redis_series_metadata(context_t *context + cmd = redis_param_sha(cmd, metric->names[i].hash); + redisSlotsRequest(slots, SADD, key, cmd, redis_series_source_callback, arg); + ++check_instances: + if (metric->desc.indom == PM_INDOM_NULL || metric->u.vlist == NULL) { +- redis_series_labelset(slots, metric, NULL, baton); ++ if (metric->cached == 0) { ++ redis_series_labelset(slots, metric, NULL, baton); ++ metric->cached = 1; ++ } + } else { + for (i = 0; i < metric->u.vlist->listcount; i++) { + value = &metric->u.vlist->value[i]; + if ((instance = dictFetchValue(metric->indom->insts, &value->inst)) == NULL) + continue; +- redis_series_instance(slots, metric, instance, baton); +- redis_series_labelset(slots, metric, instance, baton); ++ if (instance->cached == 0 || metric->cached == 0) { ++ redis_series_instance(slots, metric, instance, baton); ++ redis_series_labelset(slots, metric, instance, baton); ++ } ++ instance->cached = 1; + } ++ metric->cached = 1; + } + } + +@@ -1210,7 +1223,6 @@ redis_series_stream(redisSlots *slots, s + + redisSlotsRequest(slots, XADD, key, cmd, redis_series_stream_callback, baton); + +- + key = sdscatfmt(sdsempty(), "pcp:values:series:%s", hash); + cmd = redis_command(3); /* EXPIRE key timer */ + cmd = redis_param_str(cmd, EXPIRE, EXPIRE_LEN); +@@ -1228,9 +1240,6 @@ redis_series_streamed(sds stamp, metric_ + char hashbuf[42]; + int i; + +- if (metric->updated == 0) +- return; +- + for (i = 0; i < metric->numnames; i++) { + pmwebapi_hash_str(metric->names[i].hash, hashbuf, sizeof(hashbuf)); + redis_series_stream(slots, stamp, metric, hashbuf, arg); +@@ -1545,7 +1554,10 @@ redis_load_slots_callback( + redisSlots *slots = baton->slots; + + seriesBatonCheckMagic(baton, MAGIC_SLOTS, "redis_load_slots_callback"); ++ ++ slots->setup = 1; /* we've received initial response from Redis */ + slots->refresh = 0; /* we're processing CLUSTER SLOTS command now */ ++ + /* no cluster redirection checking is needed for this callback */ + sdsfree(cmd); + +@@ -1832,12 +1844,47 @@ pmDiscoverSetup(pmDiscoverModule *module + const char fallback[] = "/var/log/pcp"; + const char *paths[] = { "pmlogger", "pmmgr" }; + const char *logdir = pmGetOptionalConfig("PCP_LOG_DIR"); ++ struct dict *config; ++ unsigned int domain, serial; ++ pmInDom indom; + char path[MAXPATHLEN]; + char sep = pmPathSeparator(); +- int i, sts, count = 0; ++ sds option, *ids; ++ int i, sts, nids, count = 0; + + if (data == NULL) + return -ENOMEM; ++ config = data->config; ++ ++ /* double-check that we are supposed to be in here */ ++ if ((option = pmIniFileLookup(config, "discover", "enabled"))) { ++ if (strcasecmp(option, "false") == 0) ++ return 0; ++ } ++ ++ /* prepare for optional metric and indom exclusion */ ++ if ((option = pmIniFileLookup(config, "discover", "exclude.metrics"))) { ++ if ((data->pmids = dictCreate(&intKeyDictCallBacks, NULL)) == NULL) ++ return -ENOMEM; ++ /* parse regular expression string for matching on metric names */ ++ regcomp(&data->exclude_names, option, REG_EXTENDED|REG_NOSUB); ++ } ++ if ((option = pmIniFileLookup(config, "discover", "exclude.indoms"))) { ++ if ((data->indoms = dictCreate(&intKeyDictCallBacks, NULL)) == NULL) ++ return -ENOMEM; ++ /* parse comma-separated indoms in 'option', convert to pmInDom */ ++ if ((ids = sdssplitlen(option, sdslen(option), ",", 1, &nids))) { ++ data->exclude_indoms = nids; ++ for (i = 0; i < nids; i++) { ++ if (sscanf(ids[i], "%u.%u", &domain, &serial) == 2) { ++ indom = pmInDom_build(domain, serial); ++ dictAdd(data->indoms, &indom, NULL); ++ } ++ sdsfree(ids[i]); ++ } ++ free(ids); ++ } ++ } + + /* create global EVAL hashes and string map caches */ + redisGlobalsInit(data->config); +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/schema.h pcp-5.0.2/src/libpcp_web/src/schema.h +--- pcp-5.0.2.orig/src/libpcp_web/src/schema.h 2019-10-11 17:16:29.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/schema.h 2020-02-03 13:23:15.266762879 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2018 Red Hat. ++ * Copyright (c) 2017-2020 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 +@@ -51,6 +51,10 @@ + #define HSET_LEN (sizeof(HSET)-1) + #define HVALS "HVALS" + #define HVALS_LEN (sizeof(HVALS)-1) ++#define INFO "INFO" ++#define INFO_LEN (sizeof(INFO)-1) ++#define PING "PING" ++#define PING_LEN (sizeof(PING)-1) + #define PUBLISH "PUBLISH" + #define PUBLISH_LEN (sizeof(PUBLISH)-1) + #define SADD "SADD" +@@ -63,6 +67,8 @@ + #define XADD_LEN (sizeof(XADD)-1) + #define XRANGE "XRANGE" + #define XRANGE_LEN (sizeof(XRANGE)-1) ++#define XREVRANGE "XREVRANGE" ++#define XREVRANGE_LEN (sizeof(XREVRANGE)-1) + + /* create a Redis protocol command (e.g. XADD, SMEMBER) */ + static inline sds +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/slots.c pcp-5.0.2/src/libpcp_web/src/slots.c +--- pcp-5.0.2.orig/src/libpcp_web/src/slots.c 2019-10-11 17:16:29.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/slots.c 2020-02-03 13:23:15.266762879 +1100 +@@ -356,6 +356,21 @@ redisSlotsRequest(redisSlots *slots, con + + if (UNLIKELY(pmDebugOptions.desperate)) + fputs(cmd, stderr); ++ if (UNLIKELY(!key && !slots->setup)) { ++ /* ++ * First request must be CLUSTER, PING, or similar - must ++ * not allow regular requests until these have completed. ++ * This is because the low layers accumulate async requests ++ * until connection establishment, which might not happen. ++ * Over time this becomes a memory leak - if we do not ever ++ * establish an initial connection). ++ */ ++ if (strcmp(topic, CLUSTER) != 0 && ++ strcmp(topic, PING) != 0 && strcmp(topic, INFO) != 0) { ++ sdsfree(cmd); ++ return -ENOTCONN; ++ } ++ } + + sts = redisAsyncFormattedCommand(context, callback, cmd, arg); + if (key) +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/slots.h pcp-5.0.2/src/libpcp_web/src/slots.h +--- pcp-5.0.2.orig/src/libpcp_web/src/slots.h 2019-04-08 09:11:00.000000000 +1000 ++++ pcp-5.0.2/src/libpcp_web/src/slots.h 2020-02-03 13:23:15.266762879 +1100 +@@ -44,10 +44,11 @@ typedef struct redisSlotRange { + typedef struct redisSlots { + unsigned int counter; + unsigned int nslots; ++ unsigned int setup; /* slots info all successfully setup */ ++ unsigned int refresh; /* do slot refresh whenever possible */ + redisSlotRange *slots; /* all instances; e.g. CLUSTER SLOTS */ + redisMap *keymap; /* map command names to key position */ + dict *contexts; /* async contexts access by hostspec */ +- unsigned int refresh; /* do slot refresh whenever possible */ + void *events; + } redisSlots; + +diff -Naurp pcp-5.0.2.orig/src/libpcp_web/src/util.c pcp-5.0.2/src/libpcp_web/src/util.c +--- pcp-5.0.2.orig/src/libpcp_web/src/util.c 2019-12-10 17:39:49.000000000 +1100 ++++ pcp-5.0.2/src/libpcp_web/src/util.c 2020-02-03 13:23:15.266762879 +1100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2019 Red Hat. ++ * Copyright (c) 2017-2020 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 +@@ -535,6 +535,8 @@ pmwebapi_metric_hash(metric_t *metric) + sdsclear(identifier); + } + sdsfree(identifier); ++ ++ metric->cached = 0; + } + + void +@@ -574,6 +576,8 @@ pmwebapi_instance_hash(indom_t *ip, inst + SHA1Update(&shactx, (unsigned char *)identifier, sdslen(identifier)); + SHA1Final(instance->name.hash, &shactx); + sdsfree(identifier); ++ ++ instance->cached = 0; + } + + sds +@@ -1046,7 +1050,6 @@ pmwebapi_add_instance(struct indom *indo + instance->name.sds = sdscatlen(instance->name.sds, name, length); + pmwebapi_string_hash(instance->name.id, name, length); + pmwebapi_instance_hash(indom, instance); +- instance->cached = 0; + } + return instance; + } +@@ -1202,12 +1205,14 @@ struct metric * + pmwebapi_add_metric(context_t *cp, const sds base, pmDesc *desc, int numnames, char **names) + { + struct metric *metric; +- sds name = sdsempty(); ++ sds name; + int i; + + /* search for a match on any of the given names */ + if (base && (metric = dictFetchValue(cp->metrics, base)) != NULL) + return metric; ++ ++ name = sdsempty(); + for (i = 0; i < numnames; i++) { + sdsclear(name); + name = sdscat(name, names[i]); +@@ -1217,6 +1222,7 @@ pmwebapi_add_metric(context_t *cp, const + } + } + sdsfree(name); ++ + return pmwebapi_new_metric(cp, base, desc, numnames, names); + } + +@@ -1230,21 +1236,24 @@ pmwebapi_new_pmid(context_t *cp, const s + int sts, numnames; + + if ((sts = pmUseContext(cp->context)) < 0) { +- fprintf(stderr, "failed to use context for PMID %s: %s", ++ fprintf(stderr, "%s: failed to use context for PMID %s: %s\n", ++ "pmwebapi_new_pmid", + pmIDStr_r(pmid, buffer, sizeof(buffer)), + pmErrStr_r(sts, errmsg, sizeof(errmsg))); + } else if ((sts = pmLookupDesc(pmid, &desc)) < 0) { + if (sts == PM_ERR_IPC) + cp->setup = 0; + if (pmDebugOptions.series) +- fprintf(stderr, "failed to lookup metric %s descriptor: %s", ++ fprintf(stderr, "%s: failed to lookup metric %s descriptor: %s\n", ++ "pmwebapi_new_pmid", + pmIDStr_r(pmid, buffer, sizeof(buffer)), + pmErrStr_r(sts, errmsg, sizeof(errmsg))); + } else if ((numnames = sts = pmNameAll(pmid, &names)) < 0) { + if (sts == PM_ERR_IPC) + cp->setup = 0; + if (pmDebugOptions.series) +- fprintf(stderr, "failed to lookup metric %s names: %s", ++ fprintf(stderr, "%s: failed to lookup metric %s names: %s\n", ++ "pmwebapi_new_pmid", + pmIDStr_r(pmid, buffer, sizeof(buffer)), + pmErrStr_r(sts, errmsg, sizeof(errmsg))); + } else { +diff -Naurp pcp-5.0.2.orig/src/pmproxy/pmproxy.conf pcp-5.0.2/src/pmproxy/pmproxy.conf +--- pcp-5.0.2.orig/src/pmproxy/pmproxy.conf 2019-08-09 15:50:17.000000000 +1000 ++++ pcp-5.0.2/src/pmproxy/pmproxy.conf 2020-02-03 13:36:03.948721355 +1100 +@@ -43,6 +43,11 @@ secure.enabled = true + # propogate archives from pmlogger(1) into Redis querying + enabled = true + ++# metrics name regex to skip during discovery (eg due to high volume) ++exclude.metrics = proc.* ++ ++# comma-separated list of instance domains to skip during discovery ++exclude.indoms = 3.9,79.7 + + ##################################################################### + ## settings for fast, scalable time series quering via Redis +diff -Naurp pcp-5.0.2.orig/src/pmproxy/src/redis.c pcp-5.0.2/src/pmproxy/src/redis.c +--- pcp-5.0.2.orig/src/pmproxy/src/redis.c 2019-12-02 16:39:33.000000000 +1100 ++++ pcp-5.0.2/src/pmproxy/src/redis.c 2020-02-03 13:36:13.585620539 +1100 +@@ -145,11 +145,11 @@ setup_redis_module(struct proxy *proxy) + proxy->slots = redisSlotsConnect(proxy->config, + flags, proxylog, on_redis_connected, + proxy, proxy->events, proxy); +- if (archive_discovery) ++ if (archive_discovery && series_queries) + pmDiscoverSetSlots(&redis_discover.module, proxy->slots); + } + +- if (archive_discovery) { ++ if (archive_discovery && series_queries) { + pmDiscoverSetEventLoop(&redis_discover.module, proxy->events); + pmDiscoverSetConfiguration(&redis_discover.module, proxy->config); + pmDiscoverSetMetricRegistry(&redis_discover.module, metric_registry); diff --git a/SOURCES/multilib-pcp-devel.patch b/SOURCES/multilib-pcp-devel.patch new file mode 100644 index 0000000..74bfaf3 --- /dev/null +++ b/SOURCES/multilib-pcp-devel.patch @@ -0,0 +1,22 @@ +commit 43cc36abff0fbaa5b5b434ca17b4b74f45dad98a +Author: Nathan Scott +Date: Thu Jan 9 16:01:18 2020 +1100 + + build: ensure generated demo Makefile matches on 32/64 Linux + + This corrects a multilib issue with the pcp-devel RPMs. + Resolves Red Hat bugzilla #1788119 + +diff --git a/src/pmdas/trace/GNUmakefile b/src/pmdas/trace/GNUmakefile +index b7087d017..b5e0589ad 100644 +--- a/src/pmdas/trace/GNUmakefile ++++ b/src/pmdas/trace/GNUmakefile +@@ -101,7 +101,7 @@ MY_INC_DIR = -I$(PCP_INC_DIR)/.. + else + MY_INC_DIR = + endif +-ifneq "$(PCP_LIB_DIR)" "/usr/lib" ++ifeq "$(findstring $(PCP_LIB_DIR), /usr/lib /usr/lib64)" "" + # for ld add -L and include -rpath when + # $(PCP_LIB_DIR) may not be on the default ld search path. + # diff --git a/SOURCES/s390x-interrupts.patch b/SOURCES/s390x-interrupts.patch new file mode 100644 index 0000000..6a1bb59 --- /dev/null +++ b/SOURCES/s390x-interrupts.patch @@ -0,0 +1,108 @@ +commit 04be64dc8a08203decc6fe206700dcb1f06c8d79 +Author: Nathan Scott +Date: Mon Feb 24 17:28:48 2020 +1100 + + pmdalinux: fix interrupts file parser for s390x /proc/interrupts layout + + The s390x interrupts file produced by the kernel was causing a failure + in pmdalinux because the code expected first numeric interrupt lines & + then named (text) lines, whereas on this platform they're intermixed. + + Add a sample interrupts file from these kernels for qa/886 to test. + + Resolves Red Hat BZ #1798058 + +diff --git a/qa/886.out.bz2 b/qa/886.out.bz2 +index 59bfae0e2..8db30e566 100644 +Binary files a/qa/886.out.bz2 and b/qa/886.out.bz2 differ +diff --git a/qa/linux/interrupts-16cpu-s390x b/qa/linux/interrupts-16cpu-s390x +new file mode 100644 +index 000000000..574dec6b0 +--- /dev/null ++++ b/qa/linux/interrupts-16cpu-s390x +@@ -0,0 +1,59 @@ ++ CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 CPU8 CPU9 CPU10 CPU11 CPU12 CPU13 CPU14 CPU15 ++EXT: 30368 5872 22695 18176 19463 5347 21306 15838 21533 6333 32165 7468 23182 5010 28665 6909 ++I/O: 675 559 764 682 764 631 646 645 822 909 464 463 645 653 574 377 ++AIO: 39 32 101 122 58 67 87 65 156 145 33 50 64 51 48 34 ++ 3: 6 4 43 44 13 22 37 26 64 55 11 29 20 15 10 7 PCI-MSI mlx5_async@pci:0002:00:00.0 ++ 4: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 PCI-MSI mlx5_comp0@pci:0002:00:00.0 ++ 5: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 PCI-MSI mlx5_comp1@pci:0002:00:00.0 ++ 6: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 PCI-MSI mlx5_comp2@pci:0002:00:00.0 ++ 7: 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 PCI-MSI mlx5_comp3@pci:0002:00:00.0 ++ 8: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 PCI-MSI mlx5_comp4@pci:0002:00:00.0 ++ 9: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 PCI-MSI mlx5_comp5@pci:0002:00:00.0 ++ 10: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 PCI-MSI mlx5_comp6@pci:0002:00:00.0 ++ 11: 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 PCI-MSI mlx5_comp7@pci:0002:00:00.0 ++ 12: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 PCI-MSI mlx5_comp8@pci:0002:00:00.0 ++ 13: 15 11 39 49 24 25 18 13 64 64 3 12 27 13 22 7 PCI-MSI mlx5_async@pci:0003:00:00.0 ++ 14: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 PCI-MSI mlx5_comp0@pci:0003:00:00.0 ++ 15: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 PCI-MSI mlx5_comp1@pci:0003:00:00.0 ++ 16: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 PCI-MSI mlx5_comp2@pci:0003:00:00.0 ++ 17: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 PCI-MSI mlx5_comp3@pci:0003:00:00.0 ++ 18: 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 PCI-MSI mlx5_comp4@pci:0003:00:00.0 ++ 19: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 PCI-MSI mlx5_comp5@pci:0003:00:00.0 ++ 20: 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 PCI-MSI mlx5_comp6@pci:0003:00:00.0 ++ 21: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 PCI-MSI mlx5_comp7@pci:0003:00:00.0 ++ 22: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 PCI-MSI mlx5_comp8@pci:0003:00:00.0 ++ 23: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 PCI-MSI 0000:00:00.0 ++ 24: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 PCI-MSI 0001:00:00.0 ++CLK: 2876 2246 9129 14527 2478 1653 2830 3374 8696 1867 12976 3002 2341 1935 3066 3063 [EXT] Clock Comparator ++EXC: 27474 3626 13527 3649 16970 3694 18487 12464 12834 4466 19188 4466 20848 3077 25599 3846 [EXT] External Call ++EMS: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] Emergency Signal ++TMR: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] CPU Timer ++TAL: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] Timing Alert ++PFL: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] Pseudo Page Fault ++DSD: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] DASD Diag ++VRT: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] Virtio ++SCP: 18 0 39 0 15 0 5 0 3 0 1 0 0 0 0 0 [EXT] Service Call ++IUC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] IUCV ++CMS: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] CPU-Measurement: Sampling ++CMC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] CPU-Measurement: Counter ++FTP: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [EXT] HMC FTP Service ++CIO: 62 57 80 90 101 81 91 81 93 112 59 46 70 97 46 37 [I/O] Common I/O Layer Interrupt ++DAS: 613 502 684 592 663 550 555 564 729 797 405 417 575 556 528 340 [I/O] DASD ++C15: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] 3215 ++C70: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] 3270 ++TAP: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] Tape ++VMR: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] Unit Record Devices ++LCS: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] LCS ++CTC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] CTC ++ADM: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] EADM Subchannel ++CSC: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] CHSC Subchannel ++VIR: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [I/O] Virtual I/O Devices ++QAI: 18 17 18 27 20 20 31 26 28 25 18 7 15 20 15 18 [AIO] QDIO Adapter Interrupt ++APB: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [AIO] AP Bus ++PCF: 21 15 83 95 38 48 56 39 128 120 15 43 49 31 33 16 [AIO] PCI Floating Interrupt ++PCD: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [AIO] PCI Directed Interrupt ++MSI: 21 15 83 95 38 48 56 39 128 120 15 43 49 31 33 16 [AIO] MSI Interrupt ++VAI: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [AIO] Virtual I/O Devices AI ++GAL: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [AIO] GIB Alert ++NMI: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [NMI] Machine Check ++RST: 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [CPU] CPU Restart +diff --git a/src/pmdas/linux/interrupts.c b/src/pmdas/linux/interrupts.c +index f8a4d9b1b..f57af9e43 100644 +--- a/src/pmdas/linux/interrupts.c ++++ b/src/pmdas/linux/interrupts.c +@@ -456,7 +456,9 @@ refresh_interrupt_values(void) + while (fgets(iobuf, iobufsz, fp) != NULL) { + iobuf[iobufsz - 1] = '\0'; + /* next we parse each interrupt line row (starting with a digit) */ +- sts = extract_interrupt_lines(iobuf, ncolumns, i++); ++ sts = extract_interrupt_lines(iobuf, ncolumns, i); ++ if (sts > 0) ++ i++; + if (sts > 1) + resized++; + if (sts) +@@ -466,7 +468,9 @@ refresh_interrupt_values(void) + if (extract_interrupt_misses(iobuf)) + continue; + /* parse other per-CPU interrupt counter rows (starts non-digit) */ +- sts = extract_interrupt_other(iobuf, ncolumns, j++); ++ sts = extract_interrupt_other(iobuf, ncolumns, j); ++ if (sts > 0) ++ j++; + if (sts > 1) + resized++; + if (!sts) diff --git a/SPECS/pcp.spec b/SPECS/pcp.spec new file mode 100644 index 0000000..e2c345d --- /dev/null +++ b/SPECS/pcp.spec @@ -0,0 +1,3672 @@ +Name: pcp +Version: 5.0.2 +Release: 5%{?dist} +Summary: System-level performance monitoring and performance management +License: GPLv2+ and LGPLv2+ and CC-BY +URL: https://pcp.io + +%global bintray https://bintray.com/artifact/download +Source0: %{bintray}/pcp/source/pcp-%{version}.src.tar.gz + +# RHBZ 1788119 +Patch1: multilib-pcp-devel.patch +# RHBZ 1785560 +Patch2: archive-discovery.patch +# RHBZ 1788881 +Patch3: activemq-modules.patch +# RHBZ 1798058 +Patch4: s390x-interrupts.patch + +%if 0%{?fedora} >= 26 || 0%{?rhel} > 7 +%global __python2 python2 +%else +%global __python2 python +%endif + +%if 0%{?fedora} || 0%{?rhel} > 5 +%global disable_selinux 0 +%else +%global disable_selinux 1 +%endif + +%global disable_snmp 0 + +# No libpfm devel packages for s390, armv7hl nor for some rhels, disable +%ifarch s390 s390x armv7hl +%global disable_perfevent 1 +%else +%if 0%{?fedora} >= 20 || 0%{?rhel} > 6 +%global disable_perfevent 0 +%else +%global disable_perfevent 1 +%endif +%endif + +# libvarlink and pmdapodman +%if 0%{?fedora} >= 28 || 0%{?rhel} > 7 +%global disable_podman 0 +%else +%global disable_podman 1 +%endif + +# libchan, libhdr_histogram and pmdastatsd +%if 0%{?fedora} >= 29 || 0%{?rhel} > 8 +%global disable_statsd 0 +%else +%global disable_statsd 1 +%endif + +%if 0%{?fedora} >= 30 || 0%{?rhel} > 7 +%global _with_python2 --with-python=no +%global disable_python2 1 +%else +%global disable_python2 0 +%endif + +# Default for epel5 is python24, so use the (optional) python26 packages +%if 0%{?rhel} == 5 +%global default_python 26 +%endif +# No python3 development environment before el8 +%if 0%{?rhel} == 0 || 0%{?rhel} > 7 +%global disable_python3 0 +# Do we wish to mandate python3 use in pcp? (f22+ and el8+) +%if 0%{?fedora} >= 22 || 0%{?rhel} > 7 +%global default_python 3 +%endif +%else +%global disable_python3 1 +%endif + +%if 0%{?fedora} >= 24 || 0%{?rhel} > 7 +%global perl_interpreter perl-interpreter +%else +%global perl_interpreter perl +%endif + +# support for pmdabcc, check bcc.spec for supported architectures of bcc +%if 0%{?fedora} >= 25 || 0%{?rhel} > 6 +%ifarch x86_64 %{power64} aarch64 s390x +%global disable_bcc 0 +%else +%global disable_bcc 1 +%endif +%else +%global disable_bcc 1 +%endif + +# support for pmdabpftrace, check bpftrace.spec for supported architectures of bpftrace +%if 0%{?fedora} >= 30 || 0%{?rhel} > 7 +%ifarch x86_64 %{power64} aarch64 s390x +%global disable_bpftrace 0 +%else +%global disable_bpftrace 1 +%endif +%else +%global disable_bpftrace 1 +%endif + +# support for pmdajson +%if 0%{?rhel} == 0 || 0%{?rhel} > 6 +%if !%{disable_python2} || !%{disable_python3} +%global disable_json 0 +%else +%global disable_json 1 +%endif +%else +%global disable_json 1 +%endif + +# No mssql ODBC driver on non-x86 platforms +%ifarch x86_64 +%if !%{disable_python2} || !%{disable_python3} +%global disable_mssql 0 +%else +%global disable_mssql 1 +%endif +%else +%global disable_mssql 1 +%endif + +# support for pmdanutcracker (perl deps missing on rhel) +%if 0%{?rhel} == 0 +%global disable_nutcracker 0 +%else +%global disable_nutcracker 1 +%endif + +# support for pmdarpm +%if 0%{?rhel} == 0 || 0%{?rhel} > 5 +%global disable_rpm 0 +%else +%global disable_rpm 1 +%endif + +# Qt development and runtime environment missing components before el6 +%if 0%{?rhel} == 0 || 0%{?rhel} > 5 +%global disable_qt 0 +%if 0%{?fedora} != 0 || 0%{?rhel} > 7 +%global default_qt 5 +%endif +%else +%global disable_qt 1 +%endif + +# systemd services and pmdasystemd +%if 0%{?fedora} >= 19 || 0%{?rhel} >= 7 +%global disable_systemd 0 +%else +%global disable_systemd 1 +%endif + +# static probes, missing before el6 and on some architectures +%if 0%{?rhel} == 0 || 0%{?rhel} > 5 +%global disable_sdt 0 +%else +%ifnarch ppc ppc64 +%global disable_sdt 0 +%else +%global disable_sdt 1 +%endif +%endif + +# libuv async event library +%if 0%{?fedora} >= 28 || 0%{?rhel} > 7 +%global disable_libuv 0 +%else +%global disable_libuv 1 +%endif + +%global disable_openssl 0 + +# rpm producing "noarch" packages +%if 0%{?rhel} == 0 || 0%{?rhel} > 5 +%global disable_noarch 0 +%else +%global disable_noarch 1 +%endif + +%if 0%{?fedora} >= 24 +%global disable_xlsx 0 +%else +%global disable_xlsx 1 +%endif + +# prevent conflicting binary and man page install for pcp(1) +Conflicts: librapi < 0.16 + +# KVM PMDA moved into pcp (no longer using Perl, default on) +Obsoletes: pcp-pmda-kvm < 4.1.1 +Provides: pcp-pmda-kvm + +# PCP REST APIs are now provided by pmproxy +Obsoletes: pcp-webapi-debuginfo < 5.0.0 +Obsoletes: pcp-webapi < 5.0.0 +Provides: pcp-webapi + +# https://fedoraproject.org/wiki/Packaging "C and C++" +BuildRequires: gcc gcc-c++ +BuildRequires: procps autoconf bison flex +BuildRequires: nss-devel +BuildRequires: rpm-devel +BuildRequires: avahi-devel +BuildRequires: xz-devel +BuildRequires: zlib-devel +%if !%{disable_python2} +%if 0%{?default_python} != 3 +BuildRequires: python%{?default_python}-devel +%else +BuildRequires: %{__python2}-devel +%endif +%endif +%if !%{disable_python3} +BuildRequires: python3-devel +%endif +BuildRequires: ncurses-devel +BuildRequires: readline-devel +BuildRequires: cyrus-sasl-devel +%if !%{disable_podman} +BuildRequires: libvarlink-devel +%endif +%if !%{disable_statsd} +BuildRequires: ragel chan-devel HdrHistogram_c-devel +%endif +%if !%{disable_perfevent} +BuildRequires: libpfm-devel >= 4 +%endif +%if !%{disable_sdt} +BuildRequires: systemtap-sdt-devel +%endif +%if !%{disable_libuv} +BuildRequires: libuv-devel >= 1.0 +%endif +%if !%{disable_openssl} +BuildRequires: openssl-devel >= 1.1.1 +%endif +%if 0%{?rhel} == 0 || 0%{?rhel} > 7 +BuildRequires: perl-generators +%endif +BuildRequires: perl-devel perl(strict) +BuildRequires: perl(ExtUtils::MakeMaker) perl(LWP::UserAgent) perl(JSON) +BuildRequires: perl(LWP::UserAgent) perl(Time::HiRes) perl(Digest::MD5) +BuildRequires: man hostname +%if !%{disable_systemd} +BuildRequires: systemd-devel +%endif +%if !%{disable_qt} +BuildRequires: desktop-file-utils +%if 0%{?default_qt} != 5 +BuildRequires: qt4-devel >= 4.4 +%else +BuildRequires: qt5-qtbase-devel +BuildRequires: qt5-qtsvg-devel +%endif +%endif + +Requires: bash xz gawk sed grep findutils which hostname +Requires: pcp-libs = %{version}-%{release} +%if !%{disable_selinux} +Requires: pcp-selinux = %{version}-%{release} +%endif + +# Some older releases did not update or replace pcp-gui-debuginfo properly +%if 0%{?fedora} < 27 && 0%{?rhel} <= 7 && "%{_vendor}" == "redhat" +Obsoletes: pcp-gui-debuginfo < 4.1.1 +%endif + +Obsoletes: pcp-compat < 4.2.0 +Obsoletes: pcp-monitor < 4.2.0 +Obsoletes: pcp-collector < 4.2.0 +Obsoletes: pcp-pmda-nvidia < 3.10.5 + +Requires: pcp-libs = %{version}-%{release} + +%global _confdir %{_sysconfdir}/pcp +%global _logsdir %{_localstatedir}/log/pcp +%global _pmnsdir %{_localstatedir}/lib/pcp/pmns +%global _tempsdir %{_localstatedir}/lib/pcp/tmp +%global _pmdasdir %{_localstatedir}/lib/pcp/pmdas +%global _testsdir %{_localstatedir}/lib/pcp/testsuite +%global _selinuxdir %{_localstatedir}/lib/pcp/selinux +%global _logconfdir %{_localstatedir}/lib/pcp/config/pmlogconf +%global _ieconfdir %{_localstatedir}/lib/pcp/config/pmieconf +%global _tapsetdir %{_datadir}/systemtap/tapset +%global _bashcompdir %{_datadir}/bash-completion/completions +%global _pixmapdir %{_datadir}/pcp-gui/pixmaps +%global _hicolordir %{_datadir}/icons/hicolor +%global _booksdir %{_datadir}/doc/pcp-doc + +%if 0%{?fedora} >= 20 || 0%{?rhel} >= 8 +%global _with_doc --with-docdir=%{_docdir}/%{name} +%endif + +%if 0%{?fedora} >= 29 || 0%{?rhel} >= 8 +%global _with_dstat --with-dstat-symlink=yes +%global disable_dstat 0 +%else +%global _with_dstat --with-dstat-symlink=no +%global disable_dstat 1 +%endif + +%if !%{disable_systemd} +%global _initddir %{_datadir}/pcp/lib +%else +%global _initddir %{_sysconfdir}/rc.d/init.d +%global _with_initd --with-rcdir=%{_initddir} +%endif + +# we never want Infiniband on s390 and armv7hl platforms +%ifarch s390 s390x armv7hl +%global disable_infiniband 1 +%else +# we never want Infiniband on RHEL5 or earlier +%if 0%{?rhel} != 0 && 0%{?rhel} < 6 +%global disable_infiniband 1 +%else +%global disable_infiniband 0 +%endif +%endif + +%if !%{disable_infiniband} +%global _with_ib --with-infiniband=yes +%endif + +%if %{disable_perfevent} +%global _with_perfevent --with-perfevent=no +%else +%global _with_perfevent --with-perfevent=yes +%endif + +%if %{disable_podman} +%global _with_podman --with-podman=no +%else +%global _with_podman --with-podman=yes +%endif + +%if %{disable_statsd} +%global _with_statsd --with-statsd=no +%else +%global _with_statsd --with-statsd=yes +%endif + +%if %{disable_bcc} +%global _with_bcc --with-pmdabcc=no +%else +%global _with_bcc --with-pmdabcc=yes +%endif + +%if %{disable_bpftrace} +%global _with_bpftrace --with-pmdabpftrace=no +%else +%global _with_bpftrace --with-pmdabpftrace=yes +%endif + +%if %{disable_json} +%global _with_json --with-pmdajson=no +%else +%global _with_json --with-pmdajson=yes +%endif + +%if %{disable_nutcracker} +%global _with_nutcracker --with-pmdanutcracker=no +%else +%global _with_nutcracker --with-pmdanutcracker=yes +%endif + +%if %{disable_snmp} +%global _with_snmp --with-pmdasnmp=no +%else +%global _with_snmp --with-pmdasnmp=yes +%endif + +%global pmda_remove() %{expand: +if [ %1 -eq 0 ] +then + PCP_PMDAS_DIR=%{_pmdasdir} + PCP_PMCDCONF_PATH=%{_confdir}/pmcd/pmcd.conf + if [ -f "$PCP_PMCDCONF_PATH" -a -f "$PCP_PMDAS_DIR/%2/domain.h" ] + then + (cd "$PCP_PMDAS_DIR/%2/" && ./Remove >/dev/null 2>&1) + fi +fi +} + +%global selinux_handle_policy() %{expand: +if [ %1 -ge 1 ] +then + %{_libexecdir}/pcp/bin/selinux-setup %{_selinuxdir} install %2 +elif [ %1 -eq 0 ] +then + %{_libexecdir}/pcp/bin/selinux-setup %{_selinuxdir} remove %2 +fi +} + +%description +Performance Co-Pilot (PCP) provides a framework and services to support +system-level performance monitoring and performance management. + +The PCP open source release provides a unifying abstraction for all of +the interesting performance data in a system, and allows client +applications to easily retrieve and process any subset of that data. + +# +# pcp-conf +# +%package conf +License: LGPLv2+ +Summary: Performance Co-Pilot run-time configuration +URL: https://pcp.io + +# http://fedoraproject.org/wiki/Packaging:Conflicts "Splitting Packages" +Conflicts: pcp-libs < 3.9 + +%description conf +Performance Co-Pilot (PCP) run-time configuration + +# +# pcp-libs +# +%package libs +License: LGPLv2+ +Summary: Performance Co-Pilot run-time libraries +URL: https://pcp.io +Requires: pcp-conf = %{version}-%{release} + +%description libs +Performance Co-Pilot (PCP) run-time libraries + +# +# pcp-libs-devel +# +%package libs-devel +License: GPLv2+ and LGPLv2+ +Summary: Performance Co-Pilot (PCP) development headers +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} + +%description libs-devel +Performance Co-Pilot (PCP) headers for development. + +# +# pcp-devel +# +%package devel +License: GPLv2+ and LGPLv2+ +Summary: Performance Co-Pilot (PCP) development tools and documentation +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +Requires: pcp-libs-devel = %{version}-%{release} + +%description devel +Performance Co-Pilot (PCP) documentation and tools for development. + +# +# pcp-testsuite +# +%package testsuite +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) test suite +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +Requires: pcp-libs-devel = %{version}-%{release} +Requires: pcp-devel = %{version}-%{release} +Obsoletes: pcp-gui-testsuite < 3.9.5 +# The following are inherited from pcp-collector and pcp-monitor, +# both of which are now obsoleted by the base pcp package +Requires: pcp-pmda-activemq pcp-pmda-bonding pcp-pmda-dbping pcp-pmda-ds389 pcp-pmda-ds389log +Requires: pcp-pmda-elasticsearch pcp-pmda-gpfs pcp-pmda-gpsd pcp-pmda-lustre +Requires: pcp-pmda-memcache pcp-pmda-mysql pcp-pmda-named pcp-pmda-netfilter pcp-pmda-news +Requires: pcp-pmda-nginx pcp-pmda-nfsclient pcp-pmda-pdns pcp-pmda-postfix pcp-pmda-postgresql pcp-pmda-oracle +Requires: pcp-pmda-samba pcp-pmda-slurm pcp-pmda-vmware pcp-pmda-zimbra +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-lustrecomm pcp-pmda-logger pcp-pmda-docker pcp-pmda-bind2 +%if !%{disable_podman} +Requires: pcp-pmda-podman +%endif +%if !%{disable_statsd} +Requires: pcp-pmda-statsd +%endif +%if !%{disable_nutcracker} +Requires: pcp-pmda-nutcracker +%endif +%if !%{disable_bcc} +Requires: pcp-pmda-bcc +%endif +%if !%{disable_bpftrace} +Requires: pcp-pmda-bpftrace +%endif +%if !%{disable_python2} || !%{disable_python3} +Requires: pcp-pmda-gluster pcp-pmda-zswap pcp-pmda-unbound pcp-pmda-mic +Requires: pcp-pmda-libvirt pcp-pmda-lio pcp-pmda-openmetrics pcp-pmda-haproxy +Requires: pcp-pmda-lmsensors pcp-pmda-netcheck +%endif +%if !%{disable_mssql} +Requires: pcp-pmda-mssql +%endif +%if !%{disable_snmp} +Requires: pcp-pmda-snmp +%endif +%if !%{disable_json} +Requires: pcp-pmda-json +%endif +%if !%{disable_rpm} +Requires: pcp-pmda-rpm +%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 +Requires: bc gcc gzip bzip2 +Requires: redhat-rpm-config + +%description testsuite +Quality assurance test suite for Performance Co-Pilot (PCP). +# end testsuite + +# +# pcp-manager +# +%package manager +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) manager daemon +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} + +%description manager +An optional daemon (pmmgr) that manages a collection of pmlogger and +pmie daemons, for a set of discovered local and remote hosts running +the performance metrics collection daemon (pmcd). It ensures these +daemons are running when appropriate, and manages their log rotation +needs. It is an alternative to the cron-based pmlogger/pmie service +scripts. + +# +# perl-PCP-PMDA. This is the PCP agent perl binding. +# +%package -n perl-PCP-PMDA +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Perl bindings and documentation +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: %{perl_interpreter} + +%description -n perl-PCP-PMDA +The PCP::PMDA Perl module contains the language bindings for +building Performance Metric Domain Agents (PMDAs) using Perl. +Each PMDA exports performance data for one specific domain, for +example the operating system kernel, Cisco routers, a database, +an application, etc. + +# +# perl-PCP-MMV +# +%package -n perl-PCP-MMV +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Perl bindings for PCP Memory Mapped Values +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: %{perl_interpreter} + +%description -n perl-PCP-MMV +The PCP::MMV module contains the Perl language bindings for +building scripts instrumented with the Performance Co-Pilot +(PCP) Memory Mapped Value (MMV) mechanism. +This mechanism allows arbitrary values to be exported from an +instrumented script into the PCP infrastructure for monitoring +and analysis with pmchart, pmie, pmlogger and other PCP tools. + +# +# perl-PCP-LogImport +# +%package -n perl-PCP-LogImport +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Perl bindings for importing external data into PCP archives +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: %{perl_interpreter} + +%description -n perl-PCP-LogImport +The PCP::LogImport module contains the Perl language bindings for +importing data in various 3rd party formats into PCP archives so +they can be replayed with standard PCP monitoring tools. + +# +# perl-PCP-LogSummary +# +%package -n perl-PCP-LogSummary +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Perl bindings for post-processing output of pmlogsummary +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: %{perl_interpreter} + +%description -n perl-PCP-LogSummary +The PCP::LogSummary module provides a Perl module for using the +statistical summary data produced by the Performance Co-Pilot +pmlogsummary utility. This utility produces various averages, +minima, maxima, and other calculations based on the performance +data stored in a PCP archive. The Perl interface is ideal for +exporting this data into third-party tools (e.g. spreadsheets). + +# +# pcp-import-sar2pcp +# +%package import-sar2pcp +License: LGPLv2+ +Summary: Performance Co-Pilot tools for importing sar data into PCP archive logs +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: perl-PCP-LogImport = %{version}-%{release} +Requires: perl(XML::TokeParser) + +%description import-sar2pcp +Performance Co-Pilot (PCP) front-end tools for importing sar data +into standard PCP archive logs for replay with any PCP monitoring tool. + +# +# pcp-import-iostat2pcp +# +%package import-iostat2pcp +License: LGPLv2+ +Summary: Performance Co-Pilot tools for importing iostat data into PCP archive logs +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: perl-PCP-LogImport = %{version}-%{release} + +%description import-iostat2pcp +Performance Co-Pilot (PCP) front-end tools for importing iostat data +into standard PCP archive logs for replay with any PCP monitoring tool. + +# +# pcp-import-mrtg2pcp +# +%package import-mrtg2pcp +License: LGPLv2+ +Summary: Performance Co-Pilot tools for importing MTRG data into PCP archive logs +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: perl-PCP-LogImport = %{version}-%{release} + +%description import-mrtg2pcp +Performance Co-Pilot (PCP) front-end tools for importing MTRG data +into standard PCP archive logs for replay with any PCP monitoring tool. + +# +# pcp-import-ganglia2pcp +# +%package import-ganglia2pcp +License: LGPLv2+ +Summary: Performance Co-Pilot tools for importing ganglia data into PCP archive logs +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +Requires: perl-PCP-LogImport = %{version}-%{release} + +%description import-ganglia2pcp +Performance Co-Pilot (PCP) front-end tools for importing ganglia data +into standard PCP archive logs for replay with any PCP monitoring tool. + +# +# pcp-import-collectl2pcp +# +%package import-collectl2pcp +License: LGPLv2+ +Summary: Performance Co-Pilot tools for importing collectl log files into PCP archive logs +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} + +%description import-collectl2pcp +Performance Co-Pilot (PCP) front-end tools for importing collectl data +into standard PCP archive logs for replay with any PCP monitoring tool. + +# +# pcp-export-zabbix-agent +# +%package export-zabbix-agent +License: GPLv2+ +Summary: Module for exporting PCP metrics to Zabbix agent +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} + +%description export-zabbix-agent +Performance Co-Pilot (PCP) module for exporting metrics from PCP to +Zabbix via the Zabbix agent - see zbxpcp(3) for further details. + +%if !%{disable_python2} || !%{disable_python3} +# +# pcp-export-pcp2elasticsearch +# +%package export-pcp2elasticsearch +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics to ElasticSearch +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +Requires: python3-requests +BuildRequires: python3-requests +%else +Requires: %{__python2}-pcp = %{version}-%{release} +Requires: %{__python2}-requests +BuildRequires: %{__python2}-requests +%endif + +%description export-pcp2elasticsearch +Performance Co-Pilot (PCP) front-end tools for exporting metric values +to Elasticsearch - a distributed, RESTful search and analytics engine. +See https://www.elastic.co/community for further details. + +# +# pcp-export-pcp2graphite +# +%package export-pcp2graphite +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics to Graphite +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +%else +Requires: %{__python2}-pcp = %{version}-%{release} +%endif + +%description export-pcp2graphite +Performance Co-Pilot (PCP) front-end tools for exporting metric values +to graphite (http://graphite.readthedocs.org). + +# pcp-export-pcp2influxdb +# +%package export-pcp2influxdb +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics to InfluxDB +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +Requires: python3-requests +%else +Requires: %{__python2}-pcp = %{version}-%{release} +Requires: %{__python2}-requests +%endif + +%description export-pcp2influxdb +Performance Co-Pilot (PCP) front-end tools for exporting metric values +to InfluxDB (https://influxdata.com/time-series-platform/influxdb). + +# +# pcp-export-pcp2json +# +%package export-pcp2json +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics in JSON format +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +%else +Requires: %{__python2}-pcp = %{version}-%{release} +%endif + +%description export-pcp2json +Performance Co-Pilot (PCP) front-end tools for exporting metric values +in JSON format. + +# +# pcp-export-pcp2spark +# +%package export-pcp2spark +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics to Apache Spark +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +%else +Requires: %{__python2}-pcp = %{version}-%{release} +%endif + +%description export-pcp2spark +Performance Co-Pilot (PCP) front-end tools for exporting metric values +in JSON format to Apache Spark. See https://spark.apache.org/ for +further details on Apache Spark. + +# +# pcp-export-pcp2xlsx +# +%if !%{disable_xlsx} +%package export-pcp2xlsx +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics to Excel +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +Requires: python3-openpyxl +BuildRequires: python3-openpyxl +%else +Requires: %{__python2}-pcp = %{version}-%{release} +Requires: %{__python2}-openpyxl +BuildRequires: %{__python2}-openpyxl +%endif + +%description export-pcp2xlsx +Performance Co-Pilot (PCP) front-end tools for exporting metric values +in Excel spreadsheet format. +%endif +# +# pcp-export-pcp2xml +# +%package export-pcp2xml +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics in XML format +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +%else +Requires: %{__python2}-pcp = %{version}-%{release} +%endif + +%description export-pcp2xml +Performance Co-Pilot (PCP) front-end tools for exporting metric values +in XML format. + +# +# pcp-export-pcp2zabbix +# +%package export-pcp2zabbix +License: GPLv2+ +Summary: Performance Co-Pilot tools for exporting PCP metrics to Zabbix +URL: https://pcp.io +Requires: pcp-libs >= %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +%else +Requires: %{__python2}-pcp = %{version}-%{release} +%endif + +%description export-pcp2zabbix +Performance Co-Pilot (PCP) front-end tools for exporting metric values +to the Zabbix (https://www.zabbix.org/) monitoring software. +%endif + +%if !%{disable_podman} +# +# pcp-pmda-podman +# +%package pmda-podman +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for podman containers +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: libvarlink +BuildRequires: libvarlink-devel + +%description pmda-podman +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting podman container and pod statistics through libvarlink. +%endif + +%if !%{disable_statsd} +# +# pcp-pmda-statsd +# +%package pmda-statsd +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from statsd +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: chan HdrHistogram_c + +%description pmda-statsd +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting statistics from the statsd daemon. +%endif + +%if !%{disable_perfevent} +# +# pcp-pmda-perfevent +# +%package pmda-perfevent +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for hardware counters +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: libpfm >= 4 +BuildRequires: libpfm-devel >= 4 +Obsoletes: pcp-pmda-papi < 5.0.0 +Obsoletes: pcp-pmda-papi-debuginfo < 5.0.0 + +%description pmda-perfevent +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting hardware counters statistics through libpfm. +%endif + +%if !%{disable_infiniband} +# +# pcp-pmda-infiniband +# +%package pmda-infiniband +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Infiniband HCAs and switches +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: libibmad >= 1.3.7 libibumad >= 1.3.7 +BuildRequires: libibmad-devel >= 1.3.7 libibumad-devel >= 1.3.7 + +%description pmda-infiniband +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting Infiniband statistics. By default, it monitors the local HCAs +but can also be configured to monitor remote GUIDs such as IB switches. +%endif + +# +# pcp-pmda-activemq +# +%package pmda-activemq +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for ActiveMQ +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl(LWP::UserAgent) + +%description pmda-activemq +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the ActiveMQ message broker. +#end pcp-pmda-activemq + +# +# pcp-pmda-bind2 +# +%package pmda-bind2 +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for BIND servers +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl(LWP::UserAgent) +Requires: perl(XML::LibXML) +Requires: perl(File::Slurp) + +%description pmda-bind2 +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from BIND (Berkeley Internet Name Domain). +#end pcp-pmda-bind2 + +# +# pcp-pmda-redis +# +%package pmda-redis +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Redis +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-redis +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from Redis servers (redis.io). +#end pcp-pmda-redis + +%if !%{disable_nutcracker} +# +# pcp-pmda-nutcracker +# +%package pmda-nutcracker +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for NutCracker (TwemCache) +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl(YAML::XS::LibYAML) +Requires: perl(JSON) + +%description pmda-nutcracker +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from NutCracker (TwemCache). +#end pcp-pmda-nutcracker +%endif + +# +# pcp-pmda-bonding +# +%package pmda-bonding +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Bonded network interfaces +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-bonding +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about bonded network interfaces. +#end pcp-pmda-bonding + +# +# pcp-pmda-dbping +# +%package pmda-dbping +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Database response times and Availablility +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-dbping +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Database response times and Availablility. +#end pcp-pmda-dbping + +# +# pcp-pmda-ds389 +# +%package pmda-ds389 +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for 389 Directory Servers +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +%if 0%{?rhel} <= 7 +Requires: perl-LDAP +%endif + +%description pmda-ds389 +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about a 389 Directory Server. +#end pcp-pmda-ds389 + +# +# pcp-pmda-ds389log +# +%package pmda-ds389log +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for 389 Directory Server Loggers +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl-Date-Manip + +%description pmda-ds389log +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from a 389 Directory Server log. +#end pcp-pmda-ds389log + + +# +# pcp-pmda-gpfs +# +%package pmda-gpfs +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for GPFS Filesystem +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-gpfs +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the GPFS filesystem. +#end pcp-pmda-gpfs + +# +# pcp-pmda-gpsd +# +%package pmda-gpsd +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for a GPS Daemon +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-gpsd +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about a GPS Daemon. +#end pcp-pmda-gpsd + +# +# pcp-pmda-docker +# +%package pmda-docker +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from the Docker daemon +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} + +%description pmda-docker +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics using the Docker daemon REST API. +#end pcp-pmda-docker + +# +# pcp-pmda-lustre +# +%package pmda-lustre +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Lustre Filesytem +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-lustre +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Lustre Filesystem. +#end pcp-pmda-lustre + +# +# pcp-pmda-lustrecomm +# +%package pmda-lustrecomm +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Lustre Filesytem Comms +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} + +%description pmda-lustrecomm +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Lustre Filesystem Comms. +#end pcp-pmda-lustrecomm + +# +# pcp-pmda-memcache +# +%package pmda-memcache +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Memcached +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-memcache +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Memcached. +#end pcp-pmda-memcache + +# +# pcp-pmda-mysql +# +%package pmda-mysql +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for MySQL +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl(DBI) perl(DBD::mysql) +BuildRequires: perl(DBI) perl(DBD::mysql) + +%description pmda-mysql +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the MySQL database. +#end pcp-pmda-mysql + +# +# pcp-pmda-named +# +%package pmda-named +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Named +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-named +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Named nameserver. +#end pcp-pmda-named + +# pcp-pmda-netfilter +# +%package pmda-netfilter +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Netfilter framework +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-netfilter +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Netfilter packet filtering framework. +#end pcp-pmda-netfilter + +# +# pcp-pmda-news +# +%package pmda-news +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Usenet News +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-news +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Usenet News. +#end pcp-pmda-news + +# +# pcp-pmda-nginx +# +%package pmda-nginx +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Nginx Webserver +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl(LWP::UserAgent) +BuildRequires: perl(LWP::UserAgent) + +%description pmda-nginx +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Nginx Webserver. +#end pcp-pmda-nginx + +# +# pcp-pmda-oracle +# +%package pmda-oracle +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Oracle database +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl(DBI) +BuildRequires: perl(DBI) + +%description pmda-oracle +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Oracle database. +#end pcp-pmda-oracle + +# +# pcp-pmda-pdns +# +%package pmda-pdns +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for PowerDNS +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-pdns +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the PowerDNS. +#end pcp-pmda-pdns + +# +# pcp-pmda-postfix +# +%package pmda-postfix +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Postfix (MTA) +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +Requires: perl-Time-HiRes +%if 0%{?fedora} > 16 || 0%{?rhel} > 5 +Requires: postfix-perl-scripts +BuildRequires: postfix-perl-scripts +%endif +%if 0%{?rhel} <= 5 +Requires: postfix +BuildRequires: postfix +%endif +%if "%{_vendor}" == "suse" +Requires: postfix-doc +BuildRequires: postfix-doc +%endif + +%description pmda-postfix +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Postfix (MTA). +#end pcp-pmda-postfix + +# +# pcp-pmda-rsyslog +# +%package pmda-rsyslog +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Rsyslog +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-rsyslog +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Rsyslog. +#end pcp-pmda-rsyslog + +# +# pcp-pmda-samba +# +%package pmda-samba +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Samba +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-samba +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Samba. +#end pcp-pmda-samba + +# +# pcp-pmda-slurm +# +%package pmda-slurm +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the SLURM Workload Manager +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-slurm +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from the SLURM Workload Manager. +#end pcp-pmda-slurm + +%if !%{disable_snmp} +# +# pcp-pmda-snmp +# +%package pmda-snmp +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Simple Network Management Protocol +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} +# There are no perl-Net-SNMP packages in rhel, disable unless non-rhel or epel5 +%if 0%{?rhel} == 0 || 0%{?rhel} < 6 +Requires: perl(Net::SNMP) +%endif + +%description pmda-snmp +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about SNMP. +#end pcp-pmda-snmp +%endif + +# +# pcp-pmda-vmware +# +%package pmda-vmware +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for VMware +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-vmware +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics for VMware. +#end pcp-pmda-vmware + +# +# pcp-pmda-zimbra +# +%package pmda-zimbra +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Zimbra +URL: https://pcp.io +Requires: perl-PCP-PMDA = %{version}-%{release} + +%description pmda-zimbra +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Zimbra. +#end pcp-pmda-zimbra + +# +# pcp-pmda-dm +# +%package pmda-dm +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Device Mapper Cache and Thin Client +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +BuildRequires: device-mapper-devel +%description pmda-dm +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Device Mapper Cache and Thin Client. +# end pcp-pmda-dm + + +%if !%{disable_bcc} +# +# pcp-pmda-bcc +# +%package pmda-bcc +License: ASL 2.0 and GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from eBPF/BCC modules +URL: https://pcp.io +Requires: python3-bcc +Requires: python3-pcp +%description pmda-bcc +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +extracting performance metrics from eBPF/BCC Python modules. +# end pcp-pmda-bcc +%endif + +%if !%{disable_bpftrace} +# +# pcp-pmda-bpftrace +# +%package pmda-bpftrace +License: ASL 2.0 and GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from bpftrace scripts +URL: https://pcp.io +Requires: bpftrace >= 0.9.2 +Requires: python3-pcp +Requires: python3 >= 3.6 +%description pmda-bpftrace +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +extracting performance metrics from bpftrace scripts. +# end pcp-pmda-bpftrace +%endif + +%if !%{disable_python2} || !%{disable_python3} +# +# pcp-pmda-gluster +# +%package pmda-gluster +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Gluster filesystem +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-gluster +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the gluster filesystem. +# end pcp-pmda-gluster + +# +# pcp-pmda-nfsclient +# +%package pmda-nfsclient +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for NFS Clients +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-nfsclient +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics for NFS Clients. +#end pcp-pmda-nfsclient + +# +# pcp-pmda-postgresql +# +%package pmda-postgresql +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for PostgreSQL +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +Requires: python3-psycopg2 +BuildRequires: python3-psycopg2 +%else +Requires: %{__python2}-pcp +Requires: %{__python2}-psycopg2 +BuildRequires: %{__python2}-psycopg2 +%endif +%description pmda-postgresql +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the PostgreSQL database. +#end pcp-pmda-postgresql + +# +# pcp-pmda-zswap +# +%package pmda-zswap +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for compressed swap +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-zswap +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about compressed swap. +# end pcp-pmda-zswap + +# +# pcp-pmda-unbound +# +%package pmda-unbound +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Unbound DNS Resolver +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-unbound +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Unbound DNS Resolver. +# end pcp-pmda-unbound + +# +# pcp-pmda-mic +# +%package pmda-mic +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Intel MIC cards +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-mic +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Intel MIC cards. +# end pcp-pmda-mic + +# +# pcp-pmda-haproxy +# +%package pmda-haproxy +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for HAProxy +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-haproxy +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +extracting performance metrics from HAProxy over the HAProxy stats socket. +# end pcp-pmda-haproxy + +# +# pcp-pmda-libvirt +# +%package pmda-libvirt +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for virtual machines +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +Requires: libvirt-python3 python3-lxml +BuildRequires: libvirt-python3 python3-lxml +%else +%if 0%{?rhel} == 0 || 0%{?fedora} >= 27 +Requires: %{__python2}-pcp +Requires: %{__python2}-libvirt %{__python2}-lxml +BuildRequires: %{__python2}-libvirt %{__python2}-lxml +%endif +%if 0%{?rhel} > 5 +Requires: %{__python2}-pcp +Requires: libvirt-%{__python2} %{__python2}-lxml +BuildRequires: libvirt-%{__python2} %{__python2}-lxml +%endif +%endif +%description pmda-libvirt +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +extracting virtualisation statistics from libvirt about behaviour of guest +and hypervisor machines. +# end pcp-pmda-libvirt + +# +# pcp-pmda-elasticsearch +# +%package pmda-elasticsearch +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Elasticsearch +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-elasticsearch +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Elasticsearch. +#end pcp-pmda-elasticsearch + +# +# pcp-pmda-lio +# +%package pmda-lio +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the LIO subsystem +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +Requires: python3-rtslib +BuildRequires: python3-rtslib +%else +Requires: %{__python2}-pcp +Requires: %{__python2}-rtslib +BuildRequires: %{__python2}-rtslib +%endif +%description pmda-lio +This package provides a PMDA to gather performance metrics from the kernels +iSCSI target interface (LIO). The metrics are stored by LIO within the Linux +kernels configfs filesystem. The PMDA provides per LUN level stats, and a +summary instance per iSCSI target, which aggregates all LUN metrics within the +target. +#end pcp-pmda-lio + +# +# pcp-pmda-openmetrics +# +%package pmda-openmetrics +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from OpenMetrics endpoints +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp +Requires: python3-requests +BuildRequires: python3-requests +%else +Requires: %{__python2}-pcp +Requires: %{__python2}-requests +BuildRequires: %{__python2}-requests +%endif +Obsoletes: pcp-pmda-prometheus < 5.0.0 +Provides: pcp-pmda-prometheus < 5.0.0 + +%description pmda-openmetrics +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +extracting metrics from OpenMetrics (https://openmetrics.io/) endpoints. +#end pcp-pmda-openmetrics + +# +# pcp-pmda-lmsensors +# +%package pmda-lmsensors +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for hardware sensors +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +# rewritten in python, so there is no longer a debuginfo package +Obsoletes: pcp-pmda-lmsensors-debuginfo < 4.2.0 +%description pmda-lmsensors +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Linux hardware monitoring sensors. +# end pcp-pmda-lmsensors + +# +# pcp-pmda-netcheck +# +%package pmda-netcheck +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for simple network checks +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-netcheck +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from simple network checks. +# end pcp-pmda-netcheck + +%endif + +%if !%{disable_mssql} +# +# pcp-pmda-mssql +# +%package pmda-mssql +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Microsoft SQL Server +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%if !%{disable_python3} +Requires: python3-pcp +%else +Requires: %{__python2}-pcp +%endif +%description pmda-mssql +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from Microsoft SQL Server. +# end pcp-pmda-mssql +%endif + +%if !%{disable_json} +# +# pcp-pmda-json +# +%package pmda-json +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for JSON data +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp +Requires: python3-jsonpointer python3-six +BuildRequires: python3-jsonpointer python3-six +%else +Requires: %{__python2}-pcp +Requires: %{__python2}-jsonpointer %{__python2}-six +BuildRequires: %{__python2}-jsonpointer %{__python2}-six +%endif +%description pmda-json +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics output in JSON. +# end pcp-pmda-json +%endif + +# +# C pmdas +# pcp-pmda-apache +# +%package pmda-apache +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Apache webserver +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-apache +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Apache webserver. +# end pcp-pmda-apache + +# +# pcp-pmda-bash +# +%package pmda-bash +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Bash shell +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-bash +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Bash shell. +# end pcp-pmda-bash + +# +# pcp-pmda-cifs +# +%package pmda-cifs +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the CIFS protocol +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-cifs +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Common Internet Filesytem. +# end pcp-pmda-cifs + +# +# pcp-pmda-cisco +# +%package pmda-cisco +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Cisco routers +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-cisco +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Cisco routers. +# end pcp-pmda-cisco + +# +# pcp-pmda-gfs2 +# +%package pmda-gfs2 +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the GFS2 filesystem +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-gfs2 +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the Global Filesystem v2. +# end pcp-pmda-gfs2 + +# +# pcp-pmda-logger +# +%package pmda-logger +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from arbitrary log files +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-logger +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from a specified set of log files (or pipes). The PMDA +supports both sampled and event-style metrics. +# end pcp-pmda-logger + +# +# pcp-pmda-mailq +# +%package pmda-mailq +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the sendmail queue +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-mailq +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about email queues managed by sendmail. +# end pcp-pmda-mailq + +# +# pcp-pmda-mounts +# +%package pmda-mounts +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for filesystem mounts +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-mounts +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about filesystem mounts. +# end pcp-pmda-mounts + +# +# pcp-pmda-nvidia-gpu +# +%package pmda-nvidia-gpu +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the Nvidia GPU +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-nvidia-gpu +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Nvidia GPUs. +# end pcp-pmda-nvidia-gpu + +# +# pcp-pmda-roomtemp +# +%package pmda-roomtemp +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the room temperature +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +%description pmda-roomtemp +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the room temperature. +# end pcp-pmda-roomtemp + +%if !%{disable_rpm} +# +# pcp-pmda-rpm +# +%package pmda-rpm +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for the RPM package manager +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +%description pmda-rpm +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about the installed RPM packages. +%endif +# end pcp-pmda-rpm + + +# +# pcp-pmda-sendmail +# +%package pmda-sendmail +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for Sendmail +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +%description pmda-sendmail +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about Sendmail traffic. +# end pcp-pmda-sendmail + +# +# pcp-pmda-shping +# +%package pmda-shping +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for shell command responses +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-shping +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about quality of service and response time measurements of +arbitrary shell commands. +# end pcp-pmda-shping + +# +# pcp-pmda-smart +# +%package pmda-smart +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for S.M.A.R.T values +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-smart +This package contains the PCP Performance Metric Domain Agent (PMDA) for +collecting metrics of disk S.M.A.R.T values making use of data from the +smartmontools package. +#end pcp-pmda-smart + +# +# pcp-pmda-summary +# +%package pmda-summary +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) summary metrics from pmie +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +%description pmda-summary +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about other installed PMDAs. +# end pcp-pmda-summary + +%if !%{disable_systemd} +# +# pcp-pmda-systemd +# +%package pmda-systemd +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from the Systemd journal +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-systemd +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics from the Systemd journal. +# end pcp-pmda-systemd +%endif + +# +# pcp-pmda-trace +# +%package pmda-trace +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics for application tracing +URL: https://pcp.io +Requires: pcp-libs = %{version}-%{release} +%description pmda-trace +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about trace performance data in applications. +# end pcp-pmda-trace + +# +# pcp-pmda-weblog +# +%package pmda-weblog +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) metrics from web server logs +URL: https://pcp.io +Requires: pcp = %{version}-%{release} +Requires: pcp-libs = %{version}-%{release} +%description pmda-weblog +This package contains the PCP Performance Metrics Domain Agent (PMDA) for +collecting metrics about web server logs. +# end pcp-pmda-weblog +# end C pmdas + +%package zeroconf +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Zeroconf Package +URL: https://pcp.io +Requires: pcp pcp-doc pcp-system-tools +Requires: pcp-pmda-dm pcp-pmda-nfsclient +%description zeroconf +This package contains configuration tweaks and files to increase metrics +gathering frequency, several extended pmlogger configurations, as well as +automated pmie diagnosis, alerting and self-healing for the localhost. +A cron script also writes daily performance summary reports similar to +those written by sysstat. + +%if !%{disable_python2} +# +# python2-pcp. This is the PCP library bindings for python. +# +%package -n %{__python2}-pcp +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Python bindings and documentation +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +%if 0%{?fedora} >= 26 || 0%{?rhel} > 7 +# on these platforms, python2-pcp replaces python-pcp +Obsoletes: python-pcp < %{version} +%endif +%if 0%{?rhel} == 5 +Requires: python%{default_python} +%else +Requires: %{__python2} +%endif + +%description -n %{__python2}-pcp +This python PCP module contains the language bindings for +Performance Metric API (PMAPI) monitor tools and Performance +Metric Domain Agent (PMDA) collector tools written in Python. +%endif + +%if !%{disable_python3} +# +# python3-pcp. This is the PCP library bindings for python3. +# +%package -n python3-pcp +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) Python3 bindings and documentation +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: python3 + +%description -n python3-pcp +This python PCP module contains the language bindings for +Performance Metric API (PMAPI) monitor tools and Performance +Metric Domain Agent (PMDA) collector tools written in Python3. +%endif + +%if !%{disable_python2} || !%{disable_python3} +# +# pcp-system-tools +# +%package system-tools +License: GPLv2+ +Summary: Performance Co-Pilot (PCP) System and Monitoring Tools +URL: https://pcp.io +%if !%{disable_python3} +Requires: python3-pcp = %{version}-%{release} +%else +Requires: %{__python2}-pcp = %{version}-%{release} +%endif +Requires: 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 + +%description system-tools +This PCP module contains additional system monitoring tools written +in the Python language. +%endif + +%if !%{disable_qt} +# +# pcp-gui package for Qt tools +# +%package gui +License: GPLv2+ and LGPLv2+ and LGPLv2+ with exceptions +Summary: Visualization tools for the Performance Co-Pilot toolkit +URL: https://pcp.io +Requires: pcp = %{version}-%{release} pcp-libs = %{version}-%{release} +Requires: liberation-sans-fonts +BuildRequires: hicolor-icon-theme + +%description gui +Visualization tools for the Performance Co-Pilot toolkit. +The pcp-gui package primarily includes visualization tools for +monitoring systems using live and archived Performance Co-Pilot +(PCP) sources. +%endif + +# +# pcp-doc package +# +%package doc +License: GPLv2+ and CC-BY +%if !%{disable_noarch} +BuildArch: noarch +%endif +Summary: Documentation and tutorial for the Performance Co-Pilot +URL: https://pcp.io +# http://fedoraproject.org/wiki/Packaging:Conflicts "Splitting Packages" +# (all man pages migrated to pcp-doc during great package split of '15) +Conflicts: pcp-pmda-infiniband < 3.10.5 + +%description doc +Documentation and tutorial for the Performance Co-Pilot +Performance Co-Pilot (PCP) provides a framework and services to support +system-level performance monitoring and performance management. + +The pcp-doc package provides useful information on using and +configuring the Performance Co-Pilot (PCP) toolkit for system +level performance management. It includes tutorials, HOWTOs, +and other detailed documentation about the internals of core +PCP utilities and daemons, and the PCP graphical tools. + +# +# pcp-selinux package +# +%if !%{disable_selinux} +%package selinux +License: GPLv2+ and CC-BY +Summary: Selinux policy package +URL: https://pcp.io +BuildRequires: selinux-policy-devel +BuildRequires: selinux-policy-targeted +%if 0%{?rhel} == 5 +BuildRequires: setools +%else +BuildRequires: setools-console +%endif +Requires: policycoreutils selinux-policy-targeted + +%description selinux +This package contains SELinux support for PCP. The package contains +interface rules, type enforcement and file context adjustments for an +updated policy package. +%endif + +%prep +%setup -q +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 + +%build +%if !%{disable_python2} && 0%{?default_python} != 3 +export PYTHON=python%{?default_python} +%endif +%configure %{?_with_initd} %{?_with_doc} %{?_with_dstat} %{?_with_ib} %{?_with_podman} %{?_with_statsd} %{?_with_perfevent} %{?_with_bcc} %{?_with_bpftrace} %{?_with_json} %{?_with_snmp} %{?_with_nutcracker} %{?_with_python2} +make %{?_smp_mflags} default_pcp + +%install +rm -Rf $RPM_BUILD_ROOT +export NO_CHOWN=true DIST_ROOT=$RPM_BUILD_ROOT +make install_pcp + +PCP_GUI='pmchart|pmconfirm|pmdumptext|pmmessage|pmquery|pmsnap|pmtime' + +# Fix stuff we do/don't want to ship +rm -f $RPM_BUILD_ROOT/%{_libdir}/*.a + +# remove sheet2pcp until BZ 830923 and BZ 754678 are resolved. +rm -f $RPM_BUILD_ROOT/%{_bindir}/sheet2pcp $RPM_BUILD_ROOT/%{_mandir}/man1/sheet2pcp.1* + +# remove {config,platform}sz.h as these are not multilib friendly. +rm -f $RPM_BUILD_ROOT/%{_includedir}/pcp/configsz.h +rm -f $RPM_BUILD_ROOT/%{_includedir}/pcp/platformsz.h + +%if %{disable_infiniband} +# remove pmdainfiniband on platforms lacking IB devel packages. +rm -f $RPM_BUILD_ROOT/%{_pmdasdir}/ib +rm -fr $RPM_BUILD_ROOT/%{_pmdasdir}/infiniband +%endif + +%if %{disable_mssql} +# remove pmdamssql on platforms lacking MSODBC driver packages. +rm -fr $RPM_BUILD_ROOT/%{_pmdasdir}/mssql +%endif + +%if %{disable_selinux} +rm -fr $RPM_BUILD_ROOT/%{_selinuxdir} +%endif + +%if %{disable_qt} +rm -fr $RPM_BUILD_ROOT/%{_pixmapdir} +rm -fr $RPM_BUILD_ROOT/%{_hicolordir} +rm -fr $RPM_BUILD_ROOT/%{_confdir}/pmsnap +rm -fr $RPM_BUILD_ROOT/%{_localstatedir}/lib/pcp/config/pmsnap +rm -fr $RPM_BUILD_ROOT/%{_localstatedir}/lib/pcp/config/pmchart +rm -f $RPM_BUILD_ROOT/%{_localstatedir}/lib/pcp/config/pmafm/pcp-gui +rm -f $RPM_BUILD_ROOT/%{_datadir}/applications/pmchart.desktop +rm -f `find $RPM_BUILD_ROOT/%{_mandir}/man1 | grep -E "$PCP_GUI"` +%else +rm -rf $RPM_BUILD_ROOT/usr/share/doc/pcp-gui +desktop-file-validate $RPM_BUILD_ROOT/%{_datadir}/applications/pmchart.desktop +%endif + +%if %{disable_xlsx} +rm -f $RPM_BUILD_ROOT/%{_bashcompdir}/pcp2xlsx +%endif + +%if 0%{?rhel} || 0%{?fedora} +# Fedora and RHEL default local only access for pmcd and pmlogger +sed -i -e '/^# .*_LOCAL=1/s/^# //' $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/{pmcd,pmlogger} +%endif + +# default chkconfig off (all RPM platforms) +for f in $RPM_BUILD_ROOT/%{_initddir}/{pcp,pmcd,pmlogger,pmie,pmmgr,pmproxy}; do + test -f "$f" || continue + sed -i -e '/^# chkconfig/s/:.*$/: - 95 05/' -e '/^# Default-Start:/s/:.*$/:/' $f +done + +# list of PMDAs in the base pkg +ls -1 $RPM_BUILD_ROOT/%{_pmdasdir} |\ + grep -E -v '^simple|sample|trivial|txmon' |\ + grep -E -v '^perfevent|perfalloc.1' |\ + grep -E -v '^ib$|^infiniband' |\ + grep -E -v '^activemq' |\ + grep -E -v '^bonding' |\ + grep -E -v '^bind2' |\ + grep -E -v '^dbping' |\ + grep -E -v '^docker' |\ + grep -E -v '^ds389log'|\ + grep -E -v '^ds389' |\ + grep -E -v '^elasticsearch' |\ + grep -E -v '^gpfs' |\ + grep -E -v '^gpsd' |\ + grep -E -v '^lio' |\ + grep -E -v '^lustre' |\ + grep -E -v '^lustrecomm' |\ + grep -E -v '^memcache' |\ + grep -E -v '^mysql' |\ + grep -E -v '^named' |\ + grep -E -v '^netfilter' |\ + grep -E -v '^news' |\ + grep -E -v '^nfsclient' |\ + grep -E -v '^nginx' |\ + grep -E -v '^nutcracker' |\ + grep -E -v '^oracle' |\ + grep -E -v '^openmetrics' |\ + grep -E -v '^pdns' |\ + grep -E -v '^podman' |\ + grep -E -v '^postfix' |\ + grep -E -v '^postgresql' |\ + grep -E -v '^redis' |\ + grep -E -v '^rsyslog' |\ + grep -E -v '^samba' |\ + grep -E -v '^slurm' |\ + grep -E -v '^snmp' |\ + grep -E -v '^statsd' |\ + grep -E -v '^vmware' |\ + grep -E -v '^zimbra' |\ + grep -E -v '^dm' |\ + grep -E -v '^apache' |\ + grep -E -v '^bash' |\ + grep -E -v '^cifs' |\ + grep -E -v '^cisco' |\ + grep -E -v '^gfs2' |\ + grep -E -v '^libvirt' |\ + grep -E -v '^lmsensors' |\ + grep -E -v '^logger' |\ + grep -E -v '^mailq' |\ + grep -E -v '^mounts' |\ + grep -E -v '^mssql' |\ + grep -E -v '^netcheck' |\ + grep -E -v '^nvidia' |\ + grep -E -v '^roomtemp' |\ + grep -E -v '^sendmail' |\ + grep -E -v '^shping' |\ + grep -E -v '^smart' |\ + grep -E -v '^summary' |\ + grep -E -v '^trace' |\ + grep -E -v '^weblog' |\ + grep -E -v '^rpm' |\ + grep -E -v '^json' |\ + grep -E -v '^mic' |\ + grep -E -v '^bcc' |\ + grep -E -v '^bpftrace' |\ + grep -E -v '^gluster' |\ + grep -E -v '^zswap' |\ + grep -E -v '^unbound' |\ + grep -E -v '^haproxy' |\ + sed -e 's#^#'%{_pmdasdir}'\/#' >base_pmdas.list + +# all base pcp package files except those split out into sub-packages +ls -1 $RPM_BUILD_ROOT/%{_bindir} |\ + grep -E -v 'pmiostat|zabbix|zbxpcp|dstat|pmrep' |\ + grep -E -v 'pcp2spark|pcp2graphite|pcp2influxdb|pcp2zabbix' |\ + grep -E -v 'pcp2elasticsearch|pcp2json|pcp2xlsx|pcp2xml' |\ + grep -E -v 'pmdbg|pmclient|pmerr|genpmda' |\ +sed -e 's#^#'%{_bindir}'\/#' >base_bin.list +ls -1 $RPM_BUILD_ROOT/%{_bashcompdir} |\ + grep -E -v 'pcp2spark|pcp2graphite|pcp2influxdb|pcp2zabbix' |\ + grep -E -v 'pcp2elasticsearch|pcp2json|pcp2xlsx|pcp2xml' |\ + grep -E -v 'pmrep|pmdumptext' |\ +sed -e 's#^#'%{_bashcompdir}'\/#' >base_bashcomp.list + +# Separate the pcp-system-tools package files. +# pmiostat is a back-compat symlink to its pcp(1) sub-command variant +# so its also in pcp-system-tools. +%if !%{disable_python2} || !%{disable_python3} +ls -1 $RPM_BUILD_ROOT/%{_bindir} |\ + egrep -e 'pmiostat|pmrep|dstat' |\ + sed -e 's#^#'%{_bindir}'\/#' >pcp-system-tools.list +ls -1 $RPM_BUILD_ROOT/%{_libexecdir}/pcp/bin |\ + egrep -e 'atop|collectl|dmcache|dstat|free|iostat|ipcs|lvmcache|mpstat' \ + -e 'numastat|pidstat|shping|tapestat|uptime|verify' |\ + sed -e 's#^#'%{_libexecdir}/pcp/bin'\/#' >>pcp-system-tools.list +%endif +# Separate the pcp-selinux package files. +%if !%{disable_selinux} +ls -1 $RPM_BUILD_ROOT/%{_selinuxdir} |\ + sed -e 's#^#'%{_selinuxdir}'\/#' > pcp-selinux.list +ls -1 $RPM_BUILD_ROOT/%{_libexecdir}/pcp/bin |\ + grep -E 'selinux-setup' |\ + sed -e 's#^#'%{_libexecdir}/pcp/bin'\/#' >> pcp-selinux.list +%endif + +ls -1 $RPM_BUILD_ROOT/%{_libexecdir}/pcp/bin |\ +%if !%{disable_python2} || !%{disable_python3} + grep -E -v 'atop|collectl|dmcache|dstat|free|iostat|ipcs|lvmcache|mpstat' |\ + grep -E -v 'numastat|shping|tapestat|uptime|verify|selinux-setup' |\ +%endif + grep -E -v 'pmlogger_daily_report' |\ + sed -e 's#^#'%{_libexecdir}/pcp/bin'\/#' >base_exec.list +ls -1 $RPM_BUILD_ROOT/%{_booksdir} |\ + sed -e 's#^#'%{_booksdir}'\/#' > pcp-doc.list +ls -1 $RPM_BUILD_ROOT/%{_mandir}/man1 |\ + sed -e 's#^#'%{_mandir}'\/man1\/#' >>pcp-doc.list +ls -1 $RPM_BUILD_ROOT/%{_mandir}/man5 |\ + sed -e 's#^#'%{_mandir}'\/man5\/#' >>pcp-doc.list +ls -1 $RPM_BUILD_ROOT/%{_datadir}/pcp/demos/tutorials |\ + sed -e 's#^#'%{_datadir}/pcp/demos/tutorials'\/#' >>pcp-doc.list +%if !%{disable_qt} +ls -1 $RPM_BUILD_ROOT/%{_pixmapdir} |\ + sed -e 's#^#'%{_pixmapdir}'\/#' > pcp-gui.list +ls -1 $RPM_BUILD_ROOT/%{_hicolordir} |\ + sed -e 's#^#'%{_hicolordir}'\/#' >> pcp-gui.list +cat base_bin.list base_exec.list base_bashcomp.list |\ + grep -E "$PCP_GUI" >> pcp-gui.list +%endif +ls -1 $RPM_BUILD_ROOT/%{_logconfdir}/ |\ + sed -e 's#^#'%{_logconfdir}'\/#' |\ + grep -E -v 'zeroconf' >pcp-logconf.list +ls -1 $RPM_BUILD_ROOT/%{_ieconfdir}/ |\ + sed -e 's#^#'%{_ieconfdir}'\/#' |\ + grep -E -v 'zeroconf' >pcp-ieconf.list +cat base_pmdas.list base_bin.list base_exec.list base_bashcomp.list \ + pcp-logconf.list pcp-ieconf.list |\ + grep -E -v 'pmdaib|pmmgr|pmsnap|2pcp|pmdas/systemd|zeroconf' |\ + grep -E -v "$PCP_GUI|pixmaps|hicolor|pcp-doc|tutorials|selinux" |\ + grep -E -v %{_confdir} | grep -E -v %{_logsdir} > base.list + +# all devel pcp package files except those split out into sub packages +ls -1 $RPM_BUILD_ROOT/%{_mandir}/man3 |\ +sed -e 's#^#'%{_mandir}'\/man3\/#' | grep -v '3pm' >>pcp-doc.list +ls -1 $RPM_BUILD_ROOT/%{_datadir}/pcp/demos |\ +sed -e 's#^#'%{_datadir}'\/pcp\/demos\/#' | grep -E -v tutorials >> devel.list +ls -1 $RPM_BUILD_ROOT/%{_bindir} |\ +grep -E 'pmdbg|pmclient|pmerr|genpmda' |\ +sed -e 's#^#'%{_bindir}'\/#' >>devel.list + +%pre testsuite +test -d %{_testsdir} || mkdir -p -m 755 %{_testsdir} +getent group pcpqa >/dev/null || groupadd -r pcpqa +getent passwd pcpqa >/dev/null || \ + useradd -c "PCP Quality Assurance" -g pcpqa -d %{_testsdir} -M -r -s /bin/bash pcpqa 2>/dev/null +chown -R pcpqa:pcpqa %{_testsdir} 2>/dev/null +exit 0 + +%post testsuite +chown -R pcpqa:pcpqa %{_testsdir} 2>/dev/null +%if 0%{?rhel} +%if !%{disable_systemd} + systemctl restart pmcd >/dev/null 2>&1 + systemctl restart pmlogger >/dev/null 2>&1 + systemctl enable pmcd >/dev/null 2>&1 + systemctl enable pmlogger >/dev/null 2>&1 +%else + /sbin/chkconfig --add pmcd >/dev/null 2>&1 + /sbin/chkconfig --add pmlogger >/dev/null 2>&1 + /sbin/service pmcd condrestart + /sbin/service pmlogger condrestart +%endif +%endif +exit 0 + +%pre +getent group pcp >/dev/null || groupadd -r pcp +getent passwd pcp >/dev/null || \ + useradd -c "Performance Co-Pilot" -g pcp -d %{_localstatedir}/lib/pcp -M -r -s /sbin/nologin pcp +exit 0 + +%preun manager +if [ "$1" -eq 0 ] +then +%if !%{disable_systemd} + systemctl --no-reload disable pmmgr.service >/dev/null 2>&1 + systemctl stop pmmgr.service >/dev/null 2>&1 +%else + /sbin/service pmmgr stop >/dev/null 2>&1 + /sbin/chkconfig --del pmmgr >/dev/null 2>&1 +%endif +fi + +%if !%{disable_rpm} +%preun pmda-rpm +%{pmda_remove "$1" "rpm"} +%endif + +%if !%{disable_systemd} +%preun pmda-systemd +%{pmda_remove "$1" "systemd"} +%endif + +%if !%{disable_infiniband} +%preun pmda-infiniband +%{pmda_remove "$1" "infiniband"} +%endif + +%if !%{disable_perfevent} +%preun pmda-perfevent +%{pmda_remove "$1" "perfevent"} +%endif + +%if !%{disable_podman} +%preun pmda-podman +%{pmda_remove "$1" "podman"} +%endif + +%if !%{disable_statsd} +%preun pmda-statsd +%{pmda_remove "$1" "statsd"} +%endif + +%if !%{disable_json} +%preun pmda-json +%{pmda_remove "$1" "json"} +%endif + +%preun pmda-nginx +%{pmda_remove "$1" "nginx"} + +%preun pmda-oracle +%{pmda_remove "$1" "oracle"} + +%preun pmda-postgresql +%{pmda_remove "$1" "postgresql"} + +%preun pmda-postfix +%{pmda_remove "$1" "postfix"} + +%preun pmda-elasticsearch +%{pmda_remove "$1" "elasticsearch"} + +%if !%{disable_snmp} +%preun pmda-snmp +%{pmda_remove "$1" "snmp"} +%endif + +%preun pmda-mysql +%{pmda_remove "$1" "mysql"} + +%preun pmda-activemq +%{pmda_remove "$1" "activemq"} + +%preun pmda-bind2 +%{pmda_remove "$1" "bind2"} + +%preun pmda-bonding +%{pmda_remove "$1" "bonding"} + +%preun pmda-dbping +%{pmda_remove "$1" "dbping"} + +%preun pmda-docker +%{pmda_remove "$1" "docker"} + +%preun pmda-ds389 +%{pmda_remove "$1" "ds389"} + +%preun pmda-ds389log +%{pmda_remove "$1" "ds389log"} + +%preun pmda-gpfs +%{pmda_remove "$1" "gpfs"} + +%preun pmda-gpsd +%{pmda_remove "$1" "gpsd"} + +%preun pmda-lio +%{pmda_remove "$1" "lio"} + +%preun pmda-openmetrics +%{pmda_remove "$1" "openmetrics"} + +%preun pmda-lustre +%{pmda_remove "$1" "lustre"} + +%preun pmda-lustrecomm +%{pmda_remove "$1" "lustrecomm"} + +%preun pmda-memcache +%{pmda_remove "$1" "memcache"} + +%preun pmda-named +%{pmda_remove "$1" "named"} + +%preun pmda-netfilter +%{pmda_remove "$1" "netfilter"} + +%preun pmda-news +%{pmda_remove "$1" "news"} + +%preun pmda-nfsclient +%{pmda_remove "$1" "nfsclient"} + +%if !%{disable_nutcracker} +%preun pmda-nutcracker +%{pmda_remove "$1" "nutcracker"} +%endif + +%preun pmda-pdns +%{pmda_remove "$1" "pdns"} + +%preun pmda-rsyslog +%{pmda_remove "$1" "rsyslog"} + +%preun pmda-redis +%{pmda_remove "$1" "redis"} + +%preun pmda-samba +%{pmda_remove "$1" "samba"} + +%preun pmda-vmware +%{pmda_remove "$1" "vmware"} + +%preun pmda-zimbra +%{pmda_remove "$1" "zimbra"} + +%preun pmda-dm +%{pmda_remove "$1" "dm"} + +%if !%{disable_bcc} +%preun pmda-bcc +%{pmda_remove "$1" "bcc"} +%endif + +%if !%{disable_bpftrace} +%preun pmda-bpftrace +%{pmda_remove "$1" "bpftrace"} +%endif + +%if !%{disable_python2} || !%{disable_python3} +%preun pmda-gluster +%{pmda_remove "$1" "gluster"} + +%preun pmda-zswap +%{pmda_remove "$1" "zswap"} + +%preun pmda-unbound +%{pmda_remove "$1" "unbound"} + +%preun pmda-mic +%{pmda_remove "$1" "mic"} + +%preun pmda-haproxy +%{pmda_remove "$1" "haproxy"} + +%preun pmda-libvirt +%{pmda_remove "$1" "libvirt"} + +%preun pmda-lmsensors +%{pmda_remove "$1" "lmsensors"} + +%if !%{disable_mssql} +%preun pmda-mssql +%{pmda_remove "$1" "mssql"} +%endif + +%preun pmda-netcheck +%{pmda_remove "$1" "netcheck"} + +%endif + +%preun pmda-apache +%{pmda_remove "$1" "apache"} + +%preun pmda-bash +%{pmda_remove "$1" "bash"} + +%preun pmda-cifs +%{pmda_remove "$1" "cifs"} + +%preun pmda-cisco +%{pmda_remove "$1" "cisco"} + +%preun pmda-gfs2 +%{pmda_remove "$1" "gfs2"} + +%preun pmda-logger +%{pmda_remove "$1" "logger"} + +%preun pmda-mailq +%{pmda_remove "$1" "mailq"} + +%preun pmda-mounts +%{pmda_remove "$1" "mounts"} + +%preun pmda-nvidia-gpu +%{pmda_remove "$1" "nvidia"} + +%preun pmda-roomtemp +%{pmda_remove "$1" "roomtemp"} + +%preun pmda-sendmail +%{pmda_remove "$1" "sendmail"} + +%preun pmda-shping +%{pmda_remove "$1" "shping"} + +%preun pmda-smart +%{pmda_remove "$1" "smart"} + +%preun pmda-summary +%{pmda_remove "$1" "summary"} + +%preun pmda-trace +%{pmda_remove "$1" "trace"} + +%preun pmda-weblog +%{pmda_remove "$1" "weblog"} + +%if !%{disable_systemd} +%preun zeroconf +if [ "$1" -eq 0 ] +then + %systemd_preun pmlogger_daily_report.timer + %systemd_preun pmlogger_daily_report.service + %systemd_preun pmlogger_daily_report-poll.timer + %systemd_preun pmlogger_daily_report-poll.service +fi +%endif + +%preun +if [ "$1" -eq 0 ] +then + # stop daemons before erasing the package + %if !%{disable_systemd} + %systemd_preun pmlogger.service + %systemd_preun pmie.service + %systemd_preun pmproxy.service + %systemd_preun pmcd.service + systemctl stop pmlogger.service >/dev/null 2>&1 + systemctl stop pmie.service >/dev/null 2>&1 + systemctl stop pmproxy.service >/dev/null 2>&1 + systemctl stop pmcd.service >/dev/null 2>&1 + %else + /sbin/service pmlogger stop >/dev/null 2>&1 + /sbin/service pmie stop >/dev/null 2>&1 + /sbin/service pmproxy stop >/dev/null 2>&1 + /sbin/service pmcd stop >/dev/null 2>&1 + + /sbin/chkconfig --del pcp >/dev/null 2>&1 + /sbin/chkconfig --del pmcd >/dev/null 2>&1 + /sbin/chkconfig --del pmlogger >/dev/null 2>&1 + /sbin/chkconfig --del pmie >/dev/null 2>&1 + /sbin/chkconfig --del pmproxy >/dev/null 2>&1 + %endif + # cleanup namespace state/flag, may still exist + PCP_PMNS_DIR=%{_pmnsdir} + rm -f "$PCP_PMNS_DIR/.NeedRebuild" >/dev/null 2>&1 +fi + +%post manager +chown -R pcp:pcp %{_logsdir}/pmmgr 2>/dev/null +%if !%{disable_systemd} + systemctl condrestart pmmgr.service >/dev/null 2>&1 +%else + /sbin/chkconfig --add pmmgr >/dev/null 2>&1 + /sbin/service pmmgr condrestart +%endif + +%post zeroconf +PCP_PMDAS_DIR=%{_pmdasdir} +PCP_SYSCONFIG_DIR=%{_sysconfdir}/sysconfig +PCP_PMCDCONF_PATH=%{_confdir}/pmcd/pmcd.conf +# auto-install important PMDAs for RH Support (if not present already) +for PMDA in dm nfsclient ; do + if ! grep -q "$PMDA/pmda$PMDA" "$PCP_PMCDCONF_PATH" + then + touch "$PCP_PMDAS_DIR/$PMDA/.NeedInstall" + fi +done +# increase default pmlogger recording frequency +sed -i 's/^\#\ PMLOGGER_INTERVAL.*/PMLOGGER_INTERVAL=10/g' "$PCP_SYSCONFIG_DIR/pmlogger" +# auto-enable these usually optional pmie rules +pmieconf -c enable dmthin +%if 0%{?rhel} +%if !%{disable_systemd} + systemctl restart pmcd >/dev/null 2>&1 + systemctl restart pmlogger >/dev/null 2>&1 + systemctl restart pmie >/dev/null 2>&1 + systemctl enable pmcd >/dev/null 2>&1 + systemctl enable pmlogger >/dev/null 2>&1 + systemctl enable pmie >/dev/null 2>&1 +%else + /sbin/chkconfig --add pmcd >/dev/null 2>&1 + /sbin/chkconfig --add pmlogger >/dev/null 2>&1 + /sbin/chkconfig --add pmie >/dev/null 2>&1 + /sbin/service pmcd condrestart + /sbin/service pmlogger condrestart + /sbin/service pmie condrestart +%endif +%endif + +%if !%{disable_selinux} +%post selinux +%{selinux_handle_policy "$1" "pcpupstream"} + +%triggerin selinux -- docker-selinux +%{selinux_handle_policy "$1" "pcpupstream-docker"} + +%triggerin selinux -- container-selinux +%{selinux_handle_policy "$1" "pcpupstream-container"} +%endif + +%post +PCP_PMNS_DIR=%{_pmnsdir} +chown -R pcp:pcp %{_logsdir}/pmcd 2>/dev/null +chown -R pcp:pcp %{_logsdir}/pmlogger 2>/dev/null +chown -R pcp:pcp %{_logsdir}/sa 2>/dev/null +chown -R pcp:pcp %{_logsdir}/pmie 2>/dev/null +chown -R pcp:pcp %{_logsdir}/pmproxy 2>/dev/null +touch "$PCP_PMNS_DIR/.NeedRebuild" +chmod 644 "$PCP_PMNS_DIR/.NeedRebuild" +%if !%{disable_systemd} + %systemd_postun_with_restart pmcd.service + %systemd_post pmcd.service + %systemd_postun_with_restart pmlogger.service + %systemd_post pmlogger.service + %systemd_postun_with_restart pmie.service + %systemd_post pmie.service + systemctl condrestart pmproxy.service >/dev/null 2>&1 +%else + /sbin/chkconfig --add pmcd >/dev/null 2>&1 + /sbin/service pmcd condrestart + /sbin/chkconfig --add pmlogger >/dev/null 2>&1 + /sbin/service pmlogger condrestart + /sbin/chkconfig --add pmie >/dev/null 2>&1 + /sbin/service pmie condrestart + /sbin/chkconfig --add pmproxy >/dev/null 2>&1 + /sbin/service pmproxy condrestart +%endif + +cd "$PCP_PMNS_DIR" && ./Rebuild -s && rm -f .NeedRebuild +cd + +%if 0%{?fedora} >= 26 || 0%{?rhel} > 7 +%ldconfig_scriptlets libs +%else +%post libs -p /sbin/ldconfig +%postun libs -p /sbin/ldconfig +%endif + +%if !%{disable_selinux} +%preun selinux +%{selinux_handle_policy "$1" "pcpupstream"} + +%triggerun selinux -- docker-selinux +%{selinux_handle_policy "$1" "pcpupstream-docker"} + +%triggerun selinux -- container-selinux +%{selinux_handle_policy "$1" "pcpupstream-container"} + +%endif +%files -f base.list +# +# Note: there are some headers (e.g. domain.h) and in a few cases some +# C source files that rpmlint complains about. These are not devel files, +# but rather they are (slightly obscure) PMDA config files. +# +%doc CHANGELOG COPYING INSTALL.md README.md VERSION.pcp pcp.lsm + +%dir %{_confdir} +%dir %{_pmdasdir} +%dir %{_datadir}/pcp +%dir %{_libexecdir}/pcp +%dir %{_libexecdir}/pcp/bin +%dir %{_localstatedir}/lib/pcp +%dir %{_localstatedir}/lib/pcp/config +%dir %attr(0775,pcp,pcp) %{_tempsdir} +%dir %attr(0775,pcp,pcp) %{_tempsdir}/bash +%dir %attr(0775,pcp,pcp) %{_tempsdir}/json +%dir %attr(0775,pcp,pcp) %{_tempsdir}/mmv +%dir %attr(0775,pcp,pcp) %{_tempsdir}/pmie +%dir %attr(0775,pcp,pcp) %{_tempsdir}/pmlogger +%dir %attr(0775,pcp,pcp) %{_tempsdir}/pmproxy +%dir %attr(0700,root,root) %{_tempsdir}/pmcd + +%dir %{_datadir}/pcp/lib +%{_datadir}/pcp/lib/ReplacePmnsSubtree +%{_datadir}/pcp/lib/bashproc.sh +%{_datadir}/pcp/lib/lockpmns +%{_datadir}/pcp/lib/pmdaproc.sh +%{_datadir}/pcp/lib/utilproc.sh +%{_datadir}/pcp/lib/rc-proc.sh +%{_datadir}/pcp/lib/rc-proc.sh.minimal +%{_datadir}/pcp/lib/unlockpmns + +%dir %attr(0775,pcp,pcp) %{_logsdir} +%attr(0775,pcp,pcp) %{_logsdir}/pmcd +%attr(0775,pcp,pcp) %{_logsdir}/pmlogger +%attr(0775,pcp,pcp) %{_logsdir}/pmie +%attr(0775,pcp,pcp) %{_logsdir}/pmproxy +%{_localstatedir}/lib/pcp/pmns +%{_initddir}/pcp +%{_initddir}/pmcd +%{_initddir}/pmlogger +%{_initddir}/pmie +%{_initddir}/pmproxy +%if !%{disable_systemd} +%{_unitdir}/pmcd.service +%{_unitdir}/pmlogger.service +%{_unitdir}/pmie.service +%{_unitdir}/pmproxy.service +# services and timers replacing the old cron scripts +%{_unitdir}/pmlogger_check.service +%{_unitdir}/pmlogger_check.timer +%{_unitdir}/pmlogger_daily.service +%{_unitdir}/pmlogger_daily.timer +%{_unitdir}/pmlogger_daily-poll.service +%{_unitdir}/pmlogger_daily-poll.timer +%{_unitdir}/pmie_check.service +%{_unitdir}/pmie_check.timer +%{_unitdir}/pmie_daily.service +%{_unitdir}/pmie_daily.timer +%config(noreplace) %{_sysconfdir}/sysconfig/pmie_timers +%config(noreplace) %{_sysconfdir}/sysconfig/pmlogger_timers +%else +# cron scripts +%config(noreplace) %{_sysconfdir}/cron.d/pcp-pmlogger +%config(noreplace) %{_sysconfdir}/cron.d/pcp-pmie +%endif +%config(noreplace) %{_sysconfdir}/sasl2/pmcd.conf +%config(noreplace) %{_sysconfdir}/sysconfig/pmlogger +%config(noreplace) %{_sysconfdir}/sysconfig/pmproxy +%config(noreplace) %{_sysconfdir}/sysconfig/pmcd +%config %{_sysconfdir}/pcp.env +%dir %{_confdir}/pipe.conf.d +%dir %{_confdir}/labels +%dir %{_confdir}/pmcd +%config(noreplace) %{_confdir}/pmcd/pmcd.conf +%config(noreplace) %{_confdir}/pmcd/pmcd.options +%config(noreplace) %{_confdir}/pmcd/rc.local +%dir %{_confdir}/pmproxy +%config(noreplace) %{_confdir}/pmproxy/pmproxy.options +%config(noreplace) %{_confdir}/pmproxy/pmproxy.conf +%dir %{_confdir}/pmie +%dir %{_confdir}/pmie/control.d +%config(noreplace) %{_confdir}/pmie/control +%config(noreplace) %{_confdir}/pmie/control.d/local +%dir %{_confdir}/pmlogger +%dir %{_confdir}/pmlogger/control.d +%config(noreplace) %{_confdir}/pmlogger/control +%config(noreplace) %{_confdir}/pmlogger/control.d/local +%dir %attr(0775,pcp,pcp) %{_confdir}/nssdb +%dir %{_confdir}/discover +%config(noreplace) %{_confdir}/discover/pcp-kube-pods.conf +%if !%{disable_libuv} +%dir %{_confdir}/pmseries +%config(noreplace) %{_confdir}/pmseries/pmseries.conf +%endif + +%ghost %dir %attr(0775,pcp,pcp) %{_localstatedir}/run/pcp +%{_localstatedir}/lib/pcp/config/pmafm +%dir %attr(0775,pcp,pcp) %{_localstatedir}/lib/pcp/config/pmie +%{_localstatedir}/lib/pcp/config/pmie +%{_localstatedir}/lib/pcp/config/pmieconf +%dir %attr(0775,pcp,pcp) %{_localstatedir}/lib/pcp/config/pmlogger +%{_localstatedir}/lib/pcp/config/pmlogger/* +%{_localstatedir}/lib/pcp/config/pmlogrewrite +%dir %attr(0775,pcp,pcp) %{_localstatedir}/lib/pcp/config/pmda + +%{_datadir}/zsh/site-functions/_pcp +%if !%{disable_sdt} +%{_tapsetdir}/pmcd.stp +%endif + +%files zeroconf +%{_libexecdir}/pcp/bin/pmlogger_daily_report +%if !%{disable_systemd} +# systemd services for pmlogger_daily_report to replace the cron script +%{_unitdir}/pmlogger_daily_report.service +%{_unitdir}/pmlogger_daily_report.timer +%{_unitdir}/pmlogger_daily_report-poll.service +%{_unitdir}/pmlogger_daily_report-poll.timer +%else +%config(noreplace) %{_sysconfdir}/cron.d/pcp-pmlogger-daily-report +%endif +%{_ieconfdir}/zeroconf +%{_logconfdir}/zeroconf + +#additional pmlogger config files + +%files conf +%dir %{_includedir}/pcp +%{_includedir}/pcp/builddefs +%{_includedir}/pcp/buildrules +%config %{_sysconfdir}/pcp.conf +%dir %{_localstatedir}/lib/pcp/config/derived +%config %{_localstatedir}/lib/pcp/config/derived/* + +%files libs +%{_libdir}/libpcp.so.3 +%{_libdir}/libpcp_gui.so.2 +%{_libdir}/libpcp_mmv.so.1 +%{_libdir}/libpcp_pmda.so.3 +%{_libdir}/libpcp_trace.so.2 +%{_libdir}/libpcp_import.so.1 +%{_libdir}/libpcp_web.so.1 + +%files libs-devel +%{_libdir}/libpcp.so +%{_libdir}/libpcp_gui.so +%{_libdir}/libpcp_mmv.so +%{_libdir}/libpcp_pmda.so +%{_libdir}/libpcp_trace.so +%{_libdir}/libpcp_import.so +%{_libdir}/libpcp_web.so +%{_libdir}/pkgconfig/libpcp.pc +%{_libdir}/pkgconfig/libpcp_pmda.pc +%{_libdir}/pkgconfig/libpcp_import.pc +%{_includedir}/pcp/*.h + +%files devel -f devel.list +%{_datadir}/pcp/examples + +# PMDAs that ship src and are not for production use +# straight out-of-the-box, for devel or QA use only. +%{_pmdasdir}/simple +%{_pmdasdir}/sample +%{_pmdasdir}/trivial +%{_pmdasdir}/txmon + +%files testsuite +%defattr(-,pcpqa,pcpqa) +%{_testsdir} + +%files manager +%{_initddir}/pmmgr +%if !%{disable_systemd} +%{_unitdir}/pmmgr.service +%endif +%{_libexecdir}/pcp/bin/pmmgr +%attr(0775,pcp,pcp) %{_logsdir}/pmmgr +%config(missingok,noreplace) %{_confdir}/pmmgr +%config(noreplace) %{_confdir}/pmmgr/pmmgr.options + +%files import-sar2pcp +%{_bindir}/sar2pcp + +%files import-iostat2pcp +%{_bindir}/iostat2pcp + +%files import-mrtg2pcp +%{_bindir}/mrtg2pcp + +%files import-ganglia2pcp +%{_bindir}/ganglia2pcp + +%files import-collectl2pcp +%{_bindir}/collectl2pcp + +%if !%{disable_podman} +%files pmda-podman +%{_pmdasdir}/podman +%endif + +%if !%{disable_statsd} +%files pmda-statsd +%{_pmdasdir}/statsd +%config(noreplace) %{_pmdasdir}/statsd/pmdastatsd.ini +%endif + +%if !%{disable_perfevent} +%files pmda-perfevent +%{_pmdasdir}/perfevent +%config(noreplace) %{_pmdasdir}/perfevent/perfevent.conf +%endif + +%if !%{disable_infiniband} +%files pmda-infiniband +%{_pmdasdir}/ib +%{_pmdasdir}/infiniband +%endif + +%files pmda-activemq +%{_pmdasdir}/activemq + +%files pmda-bonding +%{_pmdasdir}/bonding + +%files pmda-bind2 +%{_pmdasdir}/bind2 + +%files pmda-dbping +%{_pmdasdir}/dbping + +%files pmda-ds389log +%{_pmdasdir}/ds389log + +%files pmda-ds389 +%{_pmdasdir}/ds389 + +%files pmda-elasticsearch +%{_pmdasdir}/elasticsearch + +%files pmda-gpfs +%{_pmdasdir}/gpfs + +%files pmda-gpsd +%{_pmdasdir}/gpsd + +%files pmda-docker +%{_pmdasdir}/docker + +%files pmda-lio +%{_pmdasdir}/lio + +%files pmda-openmetrics +%{_pmdasdir}/openmetrics + +%files pmda-lustre +%{_pmdasdir}/lustre + +%files pmda-lustrecomm +%{_pmdasdir}/lustrecomm + +%files pmda-memcache +%{_pmdasdir}/memcache + +%files pmda-mysql +%{_pmdasdir}/mysql + +%files pmda-named +%{_pmdasdir}/named + +%files pmda-netfilter +%{_pmdasdir}/netfilter + +%files pmda-news +%{_pmdasdir}/news + +%files pmda-nginx +%{_pmdasdir}/nginx + +%files pmda-nfsclient +%{_pmdasdir}/nfsclient + +%if !%{disable_nutcracker} +%files pmda-nutcracker +%{_pmdasdir}/nutcracker +%endif + +%files pmda-oracle +%{_pmdasdir}/oracle + +%files pmda-pdns +%{_pmdasdir}/pdns + +%files pmda-postfix +%{_pmdasdir}/postfix + +%files pmda-postgresql +%{_pmdasdir}/postgresql +%config(noreplace) %{_pmdasdir}/postgresql/pmdapostgresql.conf + +%files pmda-redis +%{_pmdasdir}/redis + +%files pmda-rsyslog +%{_pmdasdir}/rsyslog + +%files pmda-samba +%{_pmdasdir}/samba + +%if !%{disable_snmp} +%files pmda-snmp +%{_pmdasdir}/snmp +%endif + +%files pmda-slurm +%{_pmdasdir}/slurm + +%files pmda-vmware +%{_pmdasdir}/vmware + +%files pmda-zimbra +%{_pmdasdir}/zimbra + +%files pmda-dm +%{_pmdasdir}/dm +%{_ieconfdir}/dm + +%if !%{disable_bcc} +%files pmda-bcc +%{_pmdasdir}/bcc +%endif + +%if !%{disable_bpftrace} +%files pmda-bpftrace +%{_pmdasdir}/bpftrace +%endif + +%if !%{disable_python2} || !%{disable_python3} +%files pmda-gluster +%{_pmdasdir}/gluster + +%files pmda-zswap +%{_pmdasdir}/zswap + +%files pmda-unbound +%{_pmdasdir}/unbound + +%files pmda-mic +%{_pmdasdir}/mic + +%files pmda-haproxy +%{_pmdasdir}/haproxy + +%files pmda-libvirt +%{_pmdasdir}/libvirt + +%files export-pcp2elasticsearch +%{_bindir}/pcp2elasticsearch +%{_bashcompdir}/pcp2elasticsearch + +%files export-pcp2graphite +%{_bindir}/pcp2graphite +%{_bashcompdir}/pcp2graphite + +%files export-pcp2influxdb +%{_bindir}/pcp2influxdb +%{_bashcompdir}/pcp2influxdb + +%files export-pcp2json +%{_bindir}/pcp2json +%{_bashcompdir}/pcp2json + +%files export-pcp2spark +%{_bindir}/pcp2spark +%{_bashcompdir}/pcp2spark + +%if !%{disable_xlsx} +%files export-pcp2xlsx +%{_bindir}/pcp2xlsx +%{_bashcompdir}/pcp2xlsx +%endif + +%files export-pcp2xml +%{_bindir}/pcp2xml +%{_bashcompdir}/pcp2xml + +%files export-pcp2zabbix +%{_bindir}/pcp2zabbix +%{_bashcompdir}/pcp2zabbix + +%files pmda-lmsensors +%{_pmdasdir}/lmsensors + +%files pmda-netcheck +%{_pmdasdir}/netcheck + +%endif + +%files export-zabbix-agent +%{_libdir}/zabbix +%{_sysconfdir}/zabbix/zabbix_agentd.d/zbxpcp.conf + +%if !%{disable_mssql} +%files pmda-mssql +%{_pmdasdir}/mssql +%endif + +%if !%{disable_json} +%files pmda-json +%{_pmdasdir}/json +%endif + +%files pmda-apache +%{_pmdasdir}/apache + +%files pmda-bash +%{_pmdasdir}/bash + +%files pmda-cifs +%{_pmdasdir}/cifs + +%files pmda-cisco +%{_pmdasdir}/cisco + +%files pmda-gfs2 +%{_pmdasdir}/gfs2 + +%files pmda-logger +%{_pmdasdir}/logger + +%files pmda-mailq +%{_pmdasdir}/mailq + +%files pmda-mounts +%{_pmdasdir}/mounts + +%files pmda-nvidia-gpu +%{_pmdasdir}/nvidia + +%files pmda-roomtemp +%{_pmdasdir}/roomtemp + +%if !%{disable_rpm} +%files pmda-rpm +%{_pmdasdir}/rpm +%endif + +%files pmda-sendmail +%{_pmdasdir}/sendmail + +%files pmda-shping +%{_pmdasdir}/shping + +%files pmda-smart +%{_pmdasdir}/smart + +%files pmda-summary +%{_pmdasdir}/summary + +%if !%{disable_systemd} +%files pmda-systemd +%{_pmdasdir}/systemd +%endif + +%files pmda-trace +%{_pmdasdir}/trace + +%files pmda-weblog +%{_pmdasdir}/weblog + +%files -n perl-PCP-PMDA -f perl-pcp-pmda.list + +%files -n perl-PCP-MMV -f perl-pcp-mmv.list + +%files -n perl-PCP-LogImport -f perl-pcp-logimport.list + +%files -n perl-PCP-LogSummary -f perl-pcp-logsummary.list + +%if !%{disable_python2} +%files -n %{__python2}-pcp -f python-pcp.list.rpm +%endif + +%if !%{disable_python3} +%files -n python3-pcp -f python3-pcp.list.rpm +%endif + +%if !%{disable_qt} +%files gui -f pcp-gui.list + +%{_confdir}/pmsnap +%config(noreplace) %{_confdir}/pmsnap/control +%{_localstatedir}/lib/pcp/config/pmsnap +%{_localstatedir}/lib/pcp/config/pmchart +%{_localstatedir}/lib/pcp/config/pmafm/pcp-gui +%{_datadir}/applications/pmchart.desktop +%{_bashcompdir}/pmdumptext +%endif + +%files doc -f pcp-doc.list + +%if !%{disable_selinux} +%files selinux -f pcp-selinux.list +%dir %{_selinuxdir} +%endif + +%if !%{disable_python2} || !%{disable_python3} +%files system-tools -f pcp-system-tools.list +%dir %{_confdir}/dstat +%dir %{_confdir}/pmrep +%config(noreplace) %{_confdir}/dstat/* +%config(noreplace) %{_confdir}/pmrep/* +%{_bashcompdir}/pmrep +%endif + +%changelog +* Tue Feb 25 2020 Nathan Scott - 5.0.2-5 +- Fix /proc/interrupts parsing on s390x platforms (BZ 1798058) + +* Mon Feb 03 2020 Nathan Scott - 5.0.2-4 +- Restrict pcp-pmda-mssql to ODBC architectures (BZ 1795804) +- Fix pcp-pmda-activemq perl module installation (BZ 1788881) +- Update archive discovery code with latest fixes (BZ 1785560) +- Update bpftrace and BCC PMDAs architecture lists (BZ 1795798) + +* Tue Jan 21 2020 Nathan Scott - 5.0.2-3 +- Fix issue with multilib pcp-devel installation (BZ 1788119) +- Archive discovery fixes in pmproxy and libpcp_web (BZ 1785560) + +* Thu Dec 12 2019 Nathan Scott - 5.0.2-2 +- Reenable infiniband PMDA in the rpm spec, deps fixed. + +* Wed Dec 11 2019 Nathan Scott - 5.0.2-1 +- Update to latest PCP v5 sources via rebase (BZ 1723598) +- Resolve selinux policy issue with bcc PMDA (BZ 1709237) +- Resolve selinux policy issue with unbound PMDA (BZ 1778813) +- Updates to perfevent PMDA for hv_24x7 events (BZ 1765434, 1779507) +- Fix perl packaging dependency for postfix PMDA (BZ 1773459) +- Fix pcp-dstat handling of large numbers of disks (BZ 1779419) +- Fix pmie exit status on receipt of TERM signal (BZ 1780003) +- Fix pmlogger timeout handling on fresh install (BZ 1780073) + +* Mon Nov 11 2019 Nathan Scott - 5.0.1-1 +- Update to latest PCP v5 sources via rebase (BZ 1723598) +- Resolve selinux policy installation issues (BZ 1730206) + +* Mon May 06 2019 Nathan Scott - 4.3.2-2 +- Update metrics for device mapper VDO driver (BZ 1670548) +- Update to a more recent PCP bug fix release (BZ 1685302) + +* Thu Jan 10 2019 Mark Goodwin - 4.3.0-3 +- add missing build deps on libuv for pmseries and libpcp_web (BZ 1630540) + +* Wed Dec 26 2018 Mark Goodwin - 4.3.0-2 +- Revert pmlogger_daily daystart patch (BZ 1662034) + +* Thu Jul 07 2016 Nathan Scott - 3.11.3-2 +- Export filesys metrics with persistent DM naming (BZ 1349932) + +* Fri Jun 17 2016 Nathan Scott - 3.11.3-1 +- Fix memory leak in derived metrics error handling (BZ 1331973) +- Correctly propogate indom in mixed derived metrics (BZ 1337212, BZ 1336130) +- Disallow stopping pmie/pmlogger daemons from cron (BZ 1336792) +- Fail fast for easily detected bad pmcd configuration (BZ 1336210) +- Implement primary (local) pmie concept in rc pmie (BZ 1323851) +- Update to latest PCP sources. + +* Mon May 16 2016 Jitka Plesnikova - 3.11.2-2.1 +- Perl 5.24 rebuild + +* Fri Apr 29 2016 Lukas Berk - 3.11.2-1 +- Negative nice values reported incorrectly (BZ 1328432) +- Multithreaded clients with concurrent pmNewContext improvements (BZ 1325363) +- PMCD agent auto-restart (BZ 1323521) +- Segv in libpcp during discovery error processing (BZ 1319288) +- Update to latest PCP sources. + +* Fri Mar 18 2016 Dave Brolley - 3.11.1-1 +- Call Remove script when uninstalling individual PMDAs (BZ 1304722) +- Restrict pmcd.services to checking known pcp services (BZ 1286361) +- Support for multi-archive contexts, across all clients (BZ 1262723) +- Remove the default shotgun approach to stopping daemons (BZ 1210976) +- Add mechanism for automatic recovery from PMDA timeouts (BZ 1065803) +- Update to latest PCP sources. + +* Fri Jan 29 2016 Mark Goodwin - 3.11.0-1 +- Significant speedups to elapsed time stopping pmcd (BZ 1292027) +- Fix python derived metric exception handling issues (BZ 1299806) +- incorrect interpolation across record in a merged archive (BZ 1296750) +- pcp requires pcp-compat pulling in a lot of unneeded pcp-pmda-* packages (BZ 1293466) +- Update to latest PCP sources. + +* Wed Dec 16 2015 Lukas Berk - 3.10.9-1 +- Add -V/--version support to several more commands (BZ 1284411) +- Resolve a pcp-iostat(1) transient device exception (BZ 1249572) +- Provides pmdapipe, an output-capturing domain agent (BZ 1163413) +- Python PMAPI pmSetMode allows None timeval parameter (BZ 1284417) +- Python PMI pmiPutValue now supports singular metrics (BZ 1285371) +- Fix python PMAPI pmRegisterDerived wrapper interface (BZ 1286733) +- Fix pmstat SEGV when run with graphical time control (BZ 1287678) +- Make pmNonOptionsFromList error message less cryptic (BZ 1287778) +- Drop unimplemented pmdumptext options from usage, man page (BZ 1289909) +- Stop creating configuration files in tmp_t locations (BZ 1256125) +- Update to latest PCP sources. + +* Fri Oct 30 2015 Mark Goodwin - 3.10.8-1 +- Update pmlogger to log an immediate sample first (BZ 1269921) +- Add pmOption host and archive setter python APIs (BZ 1270176) +- Replace old pmatop(1) man page with pcp-atop(1) (BZ 1270761) +- Update to latest PCP sources. + +* Wed Sep 16 2015 Nathan Scott - 3.10.7-1 +- Resolved pmchart sigsegv opening view without context (BZ 1256708) +- Fixed pmchart memory corruption restoring Saved Hosts (BZ 1257009) +- Fix perl PMDA API double-free on socket error path (BZ 1258862) +- Fix python API pmGetOption(3) alignment interface (BZ 1262722) +- Added missing RPM dependencies to several PMDA sub-packages. +- Update to latest stable Vector release for pcp-vector-webapp. +- Update to latest PCP sources. + +* Sat Sep 05 2015 Kalev Lember - 3.10.6-2.1 +- Rebuilt for librpm soname bump + +* Thu Aug 06 2015 Lukas Berk - 3.10.6-2 +- Fix SDT related build error (BZ 1250894) + +* Tue Aug 04 2015 Nathan Scott - 3.10.6-1 +- Fix pcp2graphite write method invocation failure (BZ 1243123) +- Reduce diagnostics in pmdaproc unknown state case (BZ 1224431) +- Derived metrics via multiple files, directory expansion (BZ 1235556) +- Update to latest PCP sources. + +* Mon Jun 15 2015 Mark Goodwin - 3.10.5-1 +- Provide and use non-exit(1)ing pmGetConfig(3) variant (BZ 1187588) +- Resolve a pmdaproc.sh pmlogger restart regression (BZ 1229458) +- Replacement of pmatop/pcp-atop(1) utility (BZ 1160811, BZ 1018575) +- Reduced installation size for minimal applications (BZ 1182184) +- Ensure pmlogger start scripts wait on pmcd startup (BZ 1185760) +- Need to run pmcd at least once before pmval -L will work (BZ 185749) + +* Wed Apr 15 2015 Nathan Scott - 3.10.4-1 +- Update to latest PCP, pcp-webjs and Vector sources. +- Packaging improvements after re-review (BZ 1204467) +- Start pmlogger/pmie independent of persistent state (BZ 1185755) +- Fix cron error reports for disabled pmlogger service (BZ 1208699) +- Incorporate Vector from Netflix (https://github.com/Netflix/vector) +- Sub-packages for pcp-webjs allowing choice and reducing used space. + +* Wed Mar 04 2015 Dave Brolley - 3.10.3-2 +- papi 5.4.1 rebuild + +* Mon Mar 02 2015 Dave Brolley - 3.10.3-1 +- Update to latest PCP sources. +- New sub-package for pcp-import-ganglia2pcp. +- Python3 support, enabled by default in f22 onward (BZ 1194324) + +* Mon Feb 23 2015 Slavek Kabrda - 3.10.2-3 +- Only use Python 3 in Fedora >= 23, more info at + https://bugzilla.redhat.com/show_bug.cgi?id=1194324#c4 + +* Mon Feb 23 2015 Nathan Scott - 3.10.2-2 +- Initial changes to support python3 as default (BZ 1194324) + +* Fri Jan 23 2015 Dave Brolley - 3.10.2-1 +- Update to latest PCP sources. +- Improve pmdaInit diagnostics for DSO helptext (BZ 1182949) +- Tighten up PMDA termination on pmcd stop (BZ 1180109) +- Correct units for cgroup memory metrics (BZ 1180351) +- Add the pcp2graphite(1) export script (BZ 1163986) + +* Mon Dec 01 2014 Nathan Scott - 3.10.1-1 +- New conditionally-built pcp-pmda-perfevent sub-package. +- Update to latest PCP sources. + +* Tue Nov 18 2014 Dave Brolley - 3.10.0-2 +- papi 5.4.0 rebuild + +* Fri Oct 31 2014 Nathan Scott - 3.10.0-1 +- Create new sub-packages for pcp-webjs and python3-pcp. +- Fix __pmDiscoverServicesWithOptions(1) codes (BZ 1139529) +- Update to latest PCP sources. + +* Fri Sep 05 2014 Nathan Scott - 3.9.10-1 +- Convert PCP init scripts to systemd services (BZ 996438) +- Fix pmlogsummary -S/-T time window reporting (BZ 1132476) +- Resolve pmdumptext segfault with invalid host (BZ 1131779) +- Fix signedness in some service discovery codes (BZ 1136166) +- New conditionally-built pcp-pmda-papi sub-package. +- Update to latest PCP sources. + +* Tue Aug 26 2014 Jitka Plesnikova - 3.9.9-1.2 +- Perl 5.20 rebuild + +* Sun Aug 17 2014 Fedora Release Engineering - 3.9.9-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Aug 13 2014 Nathan Scott - 3.9.9-1 +- Update to latest PCP sources. + +* Wed Jul 16 2014 Mark Goodwin - 3.9.7-1 +- Update to latest PCP sources. + +* Wed Jun 18 2014 Dave Brolley - 3.9.5-1 +- Daemon signal handlers no longer use unsafe APIs (BZ 847343) +- Handle /var/run setups on a temporary filesystem (BZ 656659) +- Resolve pmlogcheck sigsegv for some archives (BZ 1077432) +- Ensure pcp-gui-{testsuite,debuginfo} packages get replaced. +- Revive support for EPEL5 builds, post pcp-gui merge. +- Update to latest PCP sources. + +* Fri Jun 06 2014 Fedora Release Engineering - 3.9.4-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu May 15 2014 Nathan Scott - 3.9.4-1 +- Merged pcp-gui and pcp-doc packages into core PCP. +- Allow for conditional libmicrohttpd builds in spec file. +- Adopt slow-start capability in systemd PMDA (BZ 1073658) +- Resolve pmcollectl network/disk mis-reporting (BZ 1097095) +- Update to latest PCP sources. + +* Tue Apr 15 2014 Dave Brolley - 3.9.2-1 +- Improve pmdarpm(1) concurrency complications (BZ 1044297) +- Fix pmconfig(1) shell output string quoting (BZ 1085401) +- Update to latest PCP sources. + +* Wed Mar 19 2014 Nathan Scott - 3.9.1-1 +- Update to latest PCP sources. + +* Thu Feb 20 2014 Nathan Scott - 3.9.0-2 +- Workaround further PowerPC/tapset-related build fallout. + +* Wed Feb 19 2014 Nathan Scott - 3.9.0-1 +- Create new sub-packages for pcp-webapi and pcp-manager +- Split configuration from pcp-libs into pcp-conf (multilib) +- Fix pmdagluster to handle more volumes, fileops (BZ 1066544) +- Update to latest PCP sources. + +* Wed Jan 29 2014 Nathan Scott - 3.8.12-1 +- Resolves SNMP procfs file ICMP line parse issue (BZ 1055818) +- Update to latest PCP sources. + +* Wed Jan 15 2014 Nathan Scott - 3.8.10-1 +- Update to latest PCP sources. + +* Thu Dec 12 2013 Nathan Scott - 3.8.9-1 +- Reduce set of exported symbols from DSO PMDAs (BZ 1025694) +- Symbol-versioning for PCP shared libraries (BZ 1037771) +- Fix pmcd/Avahi interaction with multiple ports (BZ 1035513) +- Update to latest PCP sources. + +* Sun Nov 03 2013 Nathan Scott - 3.8.8-1 +- Update to latest PCP sources (simple build fixes only). + +* Fri Nov 01 2013 Nathan Scott - 3.8.6-1 +- Update to latest PCP sources. +- Rework pmpost test which confused virus checkers (BZ 1024850) +- Tackle pmatop reporting issues via alternate metrics (BZ 998735) + +* Fri Oct 18 2013 Nathan Scott - 3.8.5-1 +- Update to latest PCP sources. +- Disable pcp-pmda-infiniband sub-package on RHEL5 (BZ 1016368) + +* Mon Sep 16 2013 Nathan Scott - 3.8.4-2 +- Disable the pcp-pmda-infiniband sub-package on s390 platforms. + +* Sun Sep 15 2013 Nathan Scott - 3.8.4-1 +- Very minor release containing mostly QA related changes. +- Enables many more metrics to be logged for Linux hosts. + +* Wed Sep 11 2013 Stan Cox - 3.8.3-2 +- Disable pmcd.stp on el5 ppc. + +* Mon Sep 09 2013 Nathan Scott - 3.8.3-1 +- Default to Unix domain socket (authenticated) local connections. +- Introduces new pcp-pmda-infiniband sub-package. +- Disable systemtap-sdt-devel usage on ppc. + +* Sat Aug 03 2013 Petr Pisar - 3.8.2-1.1 +- Perl 5.18 rebuild + +* Wed Jul 31 2013 Nathan Scott - 3.8.2-1 +- Update to latest PCP sources. +- Integrate gluster related stats with PCP (BZ 969348) +- Fix for iostat2pcp not parsing iostat output (BZ 981545) +- Start pmlogger with usable config by default (BZ 953759) +- Fix pmatop failing to start, gives stacktrace (BZ 963085) + +* Wed Jun 19 2013 Nathan Scott - 3.8.1-1 +- Update to latest PCP sources. +- Fix log import silently dropping >1024 metrics (BZ 968210) +- Move some commonly used tools on the usual PATH (BZ 967709) +- Improve pmatop handling of missing proc metrics (BZ 963085) +- Stop out-of-order records corrupting import logs (BZ 958745) + +* Tue May 14 2013 Nathan Scott - 3.8.0-1 +- Update to latest PCP sources. +- Validate metric names passed into pmiAddMetric (BZ 958019) +- Install log directories with correct ownership (BZ 960858) + +* Fri Apr 19 2013 Nathan Scott - 3.7.2-1 +- Update to latest PCP sources. +- Ensure root namespace exists at the end of install (BZ 952977) + +* Wed Mar 20 2013 Nathan Scott - 3.7.1-1 +- Update to latest PCP sources. +- Migrate all tempfiles correctly to the new tempdir hierarchy. + +* Sun Mar 10 2013 Nathan Scott - 3.7.0-1 +- Update to latest PCP sources. +- Migrate all configuration files below the /etc/pcp hierarchy. + +* Thu Feb 14 2013 Fedora Release Engineering - 3.6.10-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Nov 28 2012 Nathan Scott - 3.6.10-2 +- Ensure tmpfile directories created in %%files section. +- Resolve tmpfile create/teardown race conditions. + +* Mon Nov 19 2012 Nathan Scott - 3.6.10-1 +- Update to latest PCP sources. +- Resolve tmpfile security flaws: CVE-2012-5530 +- Introduces new "pcp" user account for all daemons to use. + +* Fri Oct 12 2012 Nathan Scott - 3.6.9-1 +- Update to latest PCP sources. +- Fix pmcd sigsegv in NUMA/CPU indom setup (BZ 858384) +- Fix sar2pcp uninitialised perl variable warning (BZ 859117) +- Fix pcp.py and pmcollectl with older python versions (BZ 852234) + +* Fri Sep 14 2012 Nathan Scott - 3.6.8-1 +- Update to latest PCP sources. + +* Wed Sep 05 2012 Nathan Scott - 3.6.6-1.1 +- Move configure step from prep to build section of spec (BZ 854128) + +* Tue Aug 28 2012 Mark Goodwin - 3.6.6-1 +- Update to latest PCP sources, see installed CHANGELOG for details. +- Introduces new python-pcp and pcp-testsuite sub-packages. + +* Thu Aug 16 2012 Mark Goodwin - 3.6.5-1 +- Update to latest PCP sources, see installed CHANGELOG for details. +- Fix security flaws: CVE-2012-3418 CVE-2012-3419 CVE-2012-3420 and CVE-2012-3421 (BZ 848629) + +* Thu Jul 19 2012 Mark Goodwin +- pmcd and pmlogger services are not supposed to be enabled by default (BZ 840763) - 3.6.3-1.3 + +* Thu Jun 21 2012 Mark Goodwin +- remove pcp-import-sheet2pcp subpackage due to missing deps (BZ 830923) - 3.6.3-1.2 + +* Fri May 18 2012 Dan Hork - 3.6.3-1.1 +- fix build on s390x + +* Mon Apr 30 2012 Mark Goodwin - 3.6.3-1 +- Update to latest PCP sources + +* Thu Apr 26 2012 Mark Goodwin - 3.6.2-1 +- Update to latest PCP sources + +* Thu Apr 12 2012 Mark Goodwin - 3.6.1-1 +- Update to latest PCP sources + +* Thu Mar 22 2012 Mark Goodwin - 3.6.0-1 +- use %%configure macro for correct libdir logic +- update to latest PCP sources + +* Thu Dec 15 2011 Mark Goodwin - 3.5.11-2 +- patched configure.in for libdir=/usr/lib64 on ppc64 + +* Thu Dec 01 2011 Mark Goodwin - 3.5.11-1 +- Update to latest PCP sources. + +* Fri Nov 04 2011 Mark Goodwin - 3.5.10-1 +- Update to latest PCP sources. + +* Mon Oct 24 2011 Mark Goodwin - 3.5.9-1 +- Update to latest PCP sources. + +* Mon Aug 08 2011 Mark Goodwin - 3.5.8-1 +- Update to latest PCP sources. + +* Fri Aug 05 2011 Mark Goodwin - 3.5.7-1 +- Update to latest PCP sources. + +* Fri Jul 22 2011 Mark Goodwin - 3.5.6-1 +- Update to latest PCP sources. + +* Tue Jul 19 2011 Mark Goodwin - 3.5.5-1 +- Update to latest PCP sources. + +* Thu Feb 03 2011 Mark Goodwin - 3.5.0-1 +- Update to latest PCP sources. + +* Thu Sep 30 2010 Mark Goodwin - 3.4.0-1 +- Update to latest PCP sources. + +* Fri Jul 16 2010 Mark Goodwin - 3.3.3-1 +- Update to latest PCP sources. + +* Sat Jul 10 2010 Mark Goodwin - 3.3.2-1 +- Update to latest PCP sources. + +* Tue Jun 29 2010 Mark Goodwin - 3.3.1-1 +- Update to latest PCP sources. + +* Fri Jun 25 2010 Mark Goodwin - 3.3.0-1 +- Update to latest PCP sources. + +* Thu Mar 18 2010 Mark Goodwin - 3.1.2-1 +- Update to latest PCP sources. + +* Wed Jan 27 2010 Mark Goodwin - 3.1.0-1 +- BuildRequires: initscripts for %%{_vendor} == redhat. + +* Thu Dec 10 2009 Mark Goodwin - 3.0.3-1 +- BuildRequires: initscripts for FC12. + +* Wed Dec 02 2009 Mark Goodwin - 3.0.2-1 +- Added sysfs.kernel metrics, rebased to minor community release. + +* Mon Oct 19 2009 Martin Hicks - 3.0.1-2 +- Remove IB dependencies. The Infiniband PMDA is being moved to + a stand-alone package. +- Move cluster PMDA to a stand-alone package. + +* Fri Oct 09 2009 Mark Goodwin - 3.0.0-9 +- This is the initial import for Fedora +- See 3.0.0 details in CHANGELOG