diff options
Diffstat (limited to 'src/pmns')
-rw-r--r-- | src/pmns/GNUmakefile | 79 | ||||
-rw-r--r-- | src/pmns/GNUmakefile.install | 35 | ||||
-rwxr-xr-x | src/pmns/Make.stdpmid | 169 | ||||
-rwxr-xr-x | src/pmns/Rebuild | 395 | ||||
-rw-r--r-- | src/pmns/ReplacePmnsSubtree | 184 | ||||
-rw-r--r-- | src/pmns/lockpmns | 46 | ||||
-rwxr-xr-x | src/pmns/pmnsadd | 125 | ||||
-rw-r--r-- | src/pmns/pmnsdel.c | 216 | ||||
-rw-r--r-- | src/pmns/pmnsmerge.c | 322 | ||||
-rw-r--r-- | src/pmns/pmnsutil.c | 99 | ||||
-rw-r--r-- | src/pmns/pmnsutil.h | 21 | ||||
-rw-r--r-- | src/pmns/stdpmid.local | 5 | ||||
-rw-r--r-- | src/pmns/stdpmid.pcp | 128 | ||||
-rw-r--r-- | src/pmns/unlockpmns | 30 |
14 files changed, 1854 insertions, 0 deletions
diff --git a/src/pmns/GNUmakefile b/src/pmns/GNUmakefile new file mode 100644 index 0000000..32ebe34 --- /dev/null +++ b/src/pmns/GNUmakefile @@ -0,0 +1,79 @@ +# +# Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +TOPDIR = ../.. +include $(TOPDIR)/src/include/builddefs +-include ./GNUlocaldefs + +PMNS_VAR_DIR = $(PCP_VAR_DIR)/pmns +PMNS_BIN_DIR = $(PCP_BINADM_DIR) +PMNS_LIB_DIR = $(PCP_SHARE_DIR)/lib + +# Take control here ... do not need to search in libpcp_pmda directory +# for libpcp_pmda DSO, and it is not even built yet for a virgin make. +# +PCPLIB_LDFLAGS = -L$(TOPDIR)/src/libpcp/src + +CFILES = pmnsmerge.c pmnsutil.c pmnsdel.c +HFILES = pmnsutil.h +TARGETS = pmnsmerge$(EXECSUFFIX) pmnsdel$(EXECSUFFIX) +SCRIPTS = pmnsadd +LOCKERS = lockpmns unlockpmns +STDPMID = stdpmid.pcp stdpmid.local + +LSRCFILES = Make.stdpmid GNUmakefile.install Rebuild ReplacePmnsSubtree \ + $(STDPMID) $(SCRIPTS) $(LOCKERS) + +LLDLIBS = $(PCPLIB) +LDIRT = *.log *.pmns stdpmid .NeedRebuild build.script $(TARGETS) + +default: $(SCRIPTS) $(LOCKERS) $(TARGETS) \ + GNUmakefile.install .NeedRebuild Rebuild ReplacePmnsSubtree stdpmid + +include $(BUILDRULES) + +pmnsmerge$(EXECSUFFIX): pmnsmerge.o pmnsutil.o + $(CCF) -o $@ $(LDFLAGS) pmnsmerge.o pmnsutil.o $(LDLIBS) + +pmnsdel$(EXECSUFFIX): pmnsdel.o pmnsutil.o + $(CCF) -o $@ $(LDFLAGS) pmnsdel.o pmnsutil.o $(LDLIBS) + +.NeedRebuild: + echo "This file flags the rc scripts to rebuild the PMNS" > .NeedRebuild + +# All PMNS config stuff goes in $PCP_VAR_DIR/pmns +# For platforms that want it, the .NeedRebuild hook is added there, +# else a manual touch(1) here is as close as it gets unfortunately. +# +install: default + $(INSTALL) -m 755 $(TARGETS) $(SCRIPTS) $(PMNS_BIN_DIR) + $(INSTALL) -m 755 $(LOCKERS) ReplacePmnsSubtree $(PMNS_LIB_DIR) + $(INSTALL) -m 644 GNUmakefile.install $(PMNS_VAR_DIR)/Makefile + $(INSTALL) -m 755 Rebuild $(PMNS_VAR_DIR)/Rebuild + $(INSTALL) -m 755 Make.stdpmid $(PMNS_VAR_DIR)/Make.stdpmid + $(INSTALL) -m 644 $(STDPMID) $(PMNS_VAR_DIR) +ifeq (, $(filter redhat debian, $(PACKAGE_DISTRIBUTION))) + $(INSTALL) -m 644 .NeedRebuild $(PMNS_VAR_DIR)/.NeedRebuild +endif + +stdpmid: $(STDPMID) + rm -f build.script + $(AWK) <Make.stdpmid >build.script '\ +/^. \$$PCP_DIR/ { print "PCP_CONF=../include/pcp.conf"; print ". ../include/pcp.env"; next }\ + { print }' + sh ./build.script + +default_pcp: default + +install_pcp: install diff --git a/src/pmns/GNUmakefile.install b/src/pmns/GNUmakefile.install new file mode 100644 index 0000000..772c80a --- /dev/null +++ b/src/pmns/GNUmakefile.install @@ -0,0 +1,35 @@ +# +# Copyright (c) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Makefile to rebuild the Performance Metrics Names Space (PMNS) (root) +# and the standard Performance Metric Domain numbers (stdpmid) +# + +TARGETS = root +PMNS != echo root_* +STDPMID != echo stdpmid.* + +default: root stdpmid + +root: $(PMNS) + ./Rebuild + +stdpmid: $(STDPMID) + ./Make.stdpmid + +clobber: + rm -f stdpmid diff --git a/src/pmns/Make.stdpmid b/src/pmns/Make.stdpmid new file mode 100755 index 0000000..c50423e --- /dev/null +++ b/src/pmns/Make.stdpmid @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 1995,2003 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +# source the PCP configuration environment variables +. $PCP_DIR/etc/pcp.env + +if [ -d "$PCP_TMPFILE_DIR" ] +then + tmp=`mktemp -d "$PCP_TMPFILE_DIR/pcp.XXXXXXXXX"` || exit 1 +else + # if configure --prefix is used in a the build, then $PCP_TMPFILE_DIR + # may not yet exist ... /tmp is a safe bet + # + tmp=`mktemp -d /tmp/pcp.XXXXXXXXX` || exit 1 +fi +status=1 +trap "rm -rf $tmp; exit \$status" 0 1 2 3 15 + +prog=`basename $0` +OLD=stdpmid +NEW=$tmp/new +SOURCE="" +for file in `echo stdpmid.*` +do + case $file + in + stdpmid.'*'|stdpmid.O|stdpmid.O.*|stdpmid.N|stdpmid.N.*|stdpmid.rpmorig|stdpmid.*.rpmorig) + ;; + *) + SOURCE="$SOURCE $file" + ;; + esac +done + +[ -z "$SOURCE" ] && exit # nothing to do - the norm nowadays + +# post-processing with sed ... +# - removes comments +# - maps white space to a single space +# - performs domain re-numbering that occured for LAB and ASH +# between PCP 2.0 and PCP 2.1 to avoid duplicates in the interim +# +# Note on sort. Used to be "sort -n +1 -2", but changed to "sort -n -k2,3" +# to avoid problems with more recent Linux coreutils versions. +# +for file in $SOURCE +do + sed <$file \ + -e '/^#/d' \ + -e 's/[ ][ ]*/ /' \ + -e '/^LAB /s/254/246/' \ + -e '/^ASH /s/7/11/' +done \ +| sort -n -k2,3 \ +| uniq >$tmp/tmp + +if [ -s "$tmp/tmp" ] +then + error=false +else + echo "$prog: Error: failed to create temporary file" + exit +fi + +# scan for duplicate domain name, but different domain number +# +$PCP_AWK_PROG '{ print $1 }' <$tmp/tmp \ +| sort \ +| uniq -c \ +| while read cnt domain +do + [ $cnt -eq 1 ] && continue + echo "$prog: Error: duplicate for domain name \"$domain\" ..." + grep "^$domain[ ]" $SOURCE | sed -e 's/^/ /' + error=true +done + +# scan for duplicate domain number, but different domain name +# +$PCP_AWK_PROG '{ print $2 }' <$tmp/tmp \ +| sort \ +| uniq -c \ +| while read cnt number +do + [ $cnt -eq 1 ] && continue + echo "$prog: Error: duplicate for domain number \"$number\" ..." + grep "[ ]$number\$" $SOURCE | sed -e 's/^/ /' + error=true +done + +$error && exit + +# preamble +# +cat <<'End-of-File' >$NEW +/* + * NOTE: + * Do not edit this file (it is re-created by Make.stdpmid). + * To make changes, edit one of the stdpmid.* files, most probably + * stdpmid.local, and as root + * # make stdpmid + * + * The following domain number assignments are assumed to apply + * + * Domain Number Range Use + * 0 reserved -- DO NOT USE + * 1-31 production PMDAs from PCP packages (#1) + * 32-39 ORACLE DBMS PMDAs + * 40-47 Sybase DBMS PMDAs + * 48-55 Informix DBMS PMDAs + * 56-58 SNMP Gateway PMDA + * 59-63 Linux PMDAs + * 64-69 ISV PMDAs + * 70-128 production PMDAs from PCP packages (#2) + * 129-510 End-User PMDAs and demo PMDAs + * 511 reserved for dynamic PMNS entries -- DO NOT USE + * + * A Performance Metrics Identifier (PMID) is internally encoded as + * 1 bits - flag reserved for internal use + * 9 bits - the Performance Metric Domain Agent (PMDA) domain number + * from the list below + * 12 bits - cluster within domain + * 10 bits - serial within cluster + */ + +#ifndef __STDPMID +#define __STDPMID + +End-of-File + +cat $tmp/tmp \ +| while read domain number +do + echo "#define $domain $number" >>$NEW +done + +echo ' +#endif' >>$NEW + +# only update if it has changed +# +if [ -f $OLD ] +then + if cmp -s $OLD $NEW >/dev/null 2>&1 + then + rm -f $NEW + fi +fi + +if [ -f $NEW ] +then + cp $NEW $OLD + chmod 444 $NEW +fi + +status=0 +exit diff --git a/src/pmns/Rebuild b/src/pmns/Rebuild new file mode 100755 index 0000000..1d69e04 --- /dev/null +++ b/src/pmns/Rebuild @@ -0,0 +1,395 @@ +#!/bin/sh +# +# Copyright (c) 2000-2001,2003 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Rebuild the PMNS, handling assorted errors +# + +# Note. has to be run from where the PMNS files are installed as local +# file names (not full paths) are used +# + +# source the PCP configuration environment variables +. $PCP_DIR/etc/pcp.env + +tmp=`mktemp -d ./pcp.XXXXXXXXX` || exit 1 +status=1 + +$PCP_SHARE_DIR/lib/lockpmns root +trap "$PCP_SHARE_DIR/lib/unlockpmns root; rm -rf $tmp; exit \$status" 0 1 2 3 15 + +_trace() +{ + if $silent + then + : + else + if $nochanges + then + echo "$*" + else + echo "$*" >>$tmp/trace + fi + fi +} + +_trace_file() +{ + if $silent + then + : + else + if $nochanges + then + cat $1 + else + cat $1 >>$tmp/trace + fi + fi +} + +_syslog() +{ + $PCP_SYSLOG_PROG -p user.alert -t PCP "$*" + _trace "$*" +} + +_die() +{ + [ -f $tmp/trace ] && cat $tmp/trace + rm -f root.new + exit +} + +prog=`basename $0` +debug=false +nochanges=false +root=root +root_updated=false +update=false +verbose="" +dupok=false +silent=false + +_usage() +{ + _trace "Usage: Rebuild [-dnsuv]" + _trace "Options:" + _trace " -d allow duplicate PMIDs in the PMNS" + _trace " -n dry run, show me what would be done" + _trace " -s silent, exit status says it all" + _trace " -u once only upgrade processing for a new PCP version" + _trace " -v verbose, for the paranoid" +} + +# Fixup "root" after PCP upgrade +# +_upgrade_root() +{ + [ ! -f root ] && return + _trace "Rebuild: PCP upgrade processing for \"root\" PMNS changes ..." + $nochanges && _trace "+ cull root_* names from PMNS ... <root >$tmp/root" + + # Cull root to remove all metrics from root_* files, so only metrics + # for optional PMDAs remain + + # If there are deprecated top-level names (below "root") that are + # no longer in a root_* file, add them here ... + EXCLUDE="pagebuf origin" + if [ "$PCP_PLATFORM" = linux ] + then + # If we're on Linux and the proc PMDA is _not_ included in + # the pmcd configuration file, add the top-level metrics + # that migrated from the linux PMDA to the proc PMDA + # + if [ -f $PCP_PMCDCONF_PATH ] + then + if grep '^proc[ ]' $PCP_PMCDCONF_PATH >/dev/null + then + # proc PMDA is installed + # + : + else + EXCLUDE="$EXCLUDE proc cgroup" + fi + else + EXCLUDE="$EXCLUDE proc cgroup" + fi + else + EXCLUDE="$EXCLUDE proc cgroup" + fi + + # now gather top-level names from root_* files + # + if [ "`echo root_*`" != "root_*" ] + then + EXCLUDE_TMP=`for file in root_* + do + $PCP_AWK_PROG <$file ' +$1 == "}" { exit } +in_root==1 { printf "%s ",$1 } +$1 == "root" && $2 == "{" { in_root = 1 }' +done` + EXCLUDE="$EXCLUDE $EXCLUDE_TMP" + fi + + if [ ! -z "$verbose" -a ! -z "$EXCLUDE" ] + then + _trace "Exclude these top-level names ..." + _trace "`echo $EXCLUDE | fmt | sed -e 's/^/ /'`" + fi + + $PCP_AWK_PROG <root >$tmp/root ' +BEGIN { # exclude these top-level names and all their descendents + # + n = split("'"$EXCLUDE"'", e) + for (i=1; i <= n; i++) { + not_in_root[e[i]] = 1 + } + + in_root = 0 + skip = 0 + } +$1 == "root" && $2 == "{" { in_root = 1 } +$1 == "}" { in_root = 0 } +in_root { if (!($1 in not_in_root)) print + next + } +$2 == "{" { n = split($1, name, ".") + if (n > 0 && name[1] in not_in_root) + skip = 1 + } +skip && $1 == "}" { skip = 0; next } +skip { next } + { print }' + if cmp -s root $tmp/root >/dev/null 2>&1 + then + # no changes ... already been here? + : + else + # we will usually end up here + root=$tmp/root + root_updated=true + fi +} + +while getopts dnusv\? c +do + case $c + in + d) dupok=true + ;; + n) nochanges=true + echo "$prog: Warning: dry run, no changes will be made" + ;; + u) update=true + ;; + s) silent=true + ;; + v) verbose="-v" + ;; + \?) _usage + status=0 + _die + ;; + esac +done +shift `expr $OPTIND - 1` + +# some preliminary checks +# +for file in $PCP_BINADM_DIR/pmnsmerge +do + if [ ! -x $file ] + then + _syslog "$prog: $file is missing. Cannot proceed." + _die + fi +done + +# remove all trace of old binary pmns (not used in PCP 3.6 or later) +# +rm -f root.bin + +here=`pwd` +_trace "Rebuilding the Performance Metrics Name Space (PMNS) in $here ..." + +if [ $# -ne 0 ] +then + _usage + _die +fi + +if $nochanges +then + CP="_trace + cp" + MV="_trace + mv" + LN="_trace + ln" + RM="_trace + rm" + PMNSMERGE="_trace + pmnsmerge ..." +else + CP=cp + MV=mv + LN=ln + RM=rm + PMNSMERGE= + + if [ ! -w `pwd` ] + then + _syslog "$prog: cannot write in directory `pwd`, script should be run as \"root\"?" + _die + fi + + if [ ! -f root ] + then + echo "root {" >root + echo "}" >>root + chmod 644 root + fi + + if [ ! -w root ] + then + _syslog "$prog: cannot write file \"root\" in directory `pwd`, script should be run as \"root\"?" + _die + fi +fi + +if $update +then + # PCP upgrade fix ups + # + _upgrade_root +fi + +if [ -f $root ] +then + haveroot=true +else + haveroot=false + if $nochanges + then + _trace "+ create empty root PMNS ..." + else + root=$tmp/root + cat <<EOFEOF >$root +root { +} +EOFEOF + fi +fi + +# Merge $root and root_* to produce the new root. +# Each root_* file should be a complete namespace, +# i.e. it should include an entry for root. +# +mergelist="" +if [ "`echo root_*`" != "root_*" ] +then + mergelist=`ls -1 root_* | $PCP_AWK_PROG ' + /root_web/ {next} + {print}'` +fi + +_trace "$prog: merging the following PMNS files: " +_trace $root $mergelist | fmt | sed -e 's/^/ /' + +rm -f root.new +eval $PMNSMERGE +if $dupok +then + pmnsmerge $verbose -d $root $mergelist root.new >$tmp/out 2>&1 +else + pmnsmerge $verbose $root $mergelist root.new >$tmp/out 2>&1 +fi + +if [ $? != 0 ] +then + cat $tmp/out + _syslog "$prog: pmnsmerge failed" + _trace " \"root\" has not been changed." + _die +fi + +# Multiple Rebuilds in succession should be a no-op. +# +if [ -f root ] +then + if $dupok + then + pminfo -m -N root 2>/dev/null | sort >$tmp/list.old + else + pminfo -m -n root 2>/dev/null | sort >$tmp/list.old + fi +fi +if [ ! -s $tmp/list.old ] +then + if $dupok + then + pminfo -m -N $root 2>/dev/null | sort >$tmp/list.old + else + pminfo -m -n $root 2>/dev/null | sort >$tmp/list.old + fi +fi +if $dupok +then + pminfo -m -N root.new | sort >$tmp/list.new +else + pminfo -m -n root.new | sort >$tmp/list.new +fi +if cmp -s $tmp/list.old $tmp/list.new > /dev/null 2>&1 +then + [ ! -f root ] && eval $MV root.new root + _trace "$prog: PMNS is unchanged." +else + # Install the new root + # + [ ! -z "$verbose" ] && _trace_file $tmp/out + if $haveroot + then + _trace "$prog: PMNS \"$here/root\" updated." + _trace "... previous version saved as \"$here/root.prev\"" + eval $MV root root.prev + else + _trace "$prog: new PMNS \"$here/root\" created." + fi + eval $MV root.new root + + # signal pmcd if it is running + # + pminfo -v pmcd.version >/dev/null 2>&1 && pmsignal -a -s HUP pmcd + + if [ ! -z "$verbose" ] && $haveroot + then + _trace "+ PMNS differences ..." + diff -c $tmp/list.old $tmp/list.new >$tmp/diff + _trace_file $tmp/diff + _trace + _trace "+ root differences ..." + diff -c root.prev root >$tmp/diff + _trace_file $tmp/diff + fi +fi +rm -f root.new + +# remake stdpmid +# +[ -f Make.stdpmid ] && ./Make.stdpmid + +[ X"$verbose" = X-v -a -f $tmp/trace ] && cat $tmp/trace + +status=0 +exit diff --git a/src/pmns/ReplacePmnsSubtree b/src/pmns/ReplacePmnsSubtree new file mode 100644 index 0000000..8b5a05c --- /dev/null +++ b/src/pmns/ReplacePmnsSubtree @@ -0,0 +1,184 @@ +#!/bin/sh +# +# Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Replace a subtree in a performance metrics namespace (PMNS) with a new +# subtree read from a file. The file is moved (note: not copied) into the +# PMNS and given the same name as the subtree. +# +# Usage: ReplacePmnsSubtree [-n namespace] pmns-subtree replacement-file +# +# Refer to the NOTE at the bottom of the file for important locking details. +# + +. $PCP_DIR/etc/pcp.env + +namespace=$PCP_VAR_DIR/pmns/root + +# Print usage message to stderr and exit with status provided (default 1) + +usageExit() +{ + echo "Usage: $prog [-n namespace] pmns-subtree replacement-file" 1>&2 + exit ${1:-1} +} + +# Sanity check options, parameters, namespace, etc. + +prog=`basename $0` +while getopts n:\? c +do + case "$c" in + n) + if [ "x$OPTARG" = x ] + then + echo "$prog: -n requires a namespace" 1>&2 + exit 1 + else + namespace="$OPTARG" + fi + ;; + \?) + usageExit 0 + ;; + esac +done + +if [ ! -f $namespace ] +then + echo "$prog: namespace doesn't exist: $namespace" 1>&2 + exit 1 +fi + +[ $# != 2 ] && usageExit + +subtree=$1 +newSubtreeFile=$2 +namespaceDir=`dirname $namespace` + +if [ ! -w $namespaceDir ] +then + echo "$prog: can't write namespace directory $namespaceDir" 1>&2 + exit 1 +fi + +if [ ! -f $newSubtreeFile ] +then + echo "$prog: can't read replacement namespace subtree file for $subtree:" \ + "$newSubtreeFile" 1>&2 + exit 1 +fi + +# variables for back-up/restore of namespace files affected by this script + +backups="root" +[ -f "$namespaceDir/$subtree" ] && backups="$backups $subtree" +backSuffix="$prog-$$-backup" +restore=false # restore backup namespace files in cleanup() + +# Signal and exit handler to clean/restore namespace (lock and backups). + +haveLock=false + +# signals we need to be careful of ... HUP, INT, QUIT, PIPE, ALRM, TERM +# +STD_SIGNALS="1 2 3 13 14 15" + +cleanup() +{ + # Release namespace lock as early as possible. Ignore signals to avoid + # releasing a lock already released. + trap "" $STD_SIGNALS + + if $restore + then + for f in $backups + do + [ -f "$namespaceDir/.$f-$backSuffix" ] && \ + mv "$namespaceDir/.$f-$backSuffix" "$namespaceDir/$f" + done + $haveLock && unlockpmns $namespace + haveLock=false + else + $haveLock && unlockpmns $namespace + haveLock=false + for f in $backups + do + rm -f "$namespaceDir/.$f-$backSuffix" + done + fi +} + +trap "cleanup; exit" 0 $STD_SIGNALS + +# "haveLock=true" is duplicated in both "if" and "else" to minimise the window +# for a signal leaving an orphaned lock if the "else" condition fires (we +# stole an existing lock). See note at bottom of script for details. + +if lockpmns $namespace +then + haveLock=true # duplicate: minimise race condition (see note above) +else + haveLock=true # duplicate: minimise race condition (see note above) + $PCP_BINADM_DIR/pmpost "PCP: PMNS lock stolen by: $*" +fi + +# Namespace is locked, back up affected files. Once backup completes, enable +# namespace restore during error handling. + +backupErr=false +for f in $backups +do + dest="$namespaceDir/.$f-$backSuffix" + if cp "$namespaceDir/$f" "$dest" + then + : + else + echo "error creating namespace backup for $f" 1>&2 + backupErr=true + fi +done +$backupErr && exit 1 +restore=true + +# pmnsdel leaves any file corresponding to the deleted subtree in place after +# it runs, regardless of whether it succeeds or fails. Allow pmnsdel to fail +# (there may be no existing subtree). Return 0 only if the entire replacement +# succeeds. + +sts=0 +pmnsdel -n $namespace $subtree >/dev/null 2>&1 +if pmnsadd -n $namespace $newSubtreeFile >/dev/null 2>&1 +then + mv -f $newSubtreeFile $namespaceDir/$subtree + sts=$? +else + sts=1 +fi +[ $sts = 0 ] && restore=false +exit $sts + +############################################################################## + +# NOTE +# +# If a signal occurs in the very short window between pmnslock returning and +# setting haveLock, the lock is not released by cleanup(). Any subsequent +# process calling pmnslock will block until its pmnslock steals the lock +# (currently after 120 secs). That window is carefully minimised. +# +# Past versions of similar scripts (e.g. Rebuild) unconditionally unlocked the +# namespace when a signal was caught. This could potentially happen while +# still waiting to acquire the lock, breaking a lock held by another process! +# +# Consider locking and backup/restore implications carefully if making changes. diff --git a/src/pmns/lockpmns b/src/pmns/lockpmns new file mode 100644 index 0000000..9e670cc --- /dev/null +++ b/src/pmns/lockpmns @@ -0,0 +1,46 @@ +#!/bin/sh +# +# Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Lock the PMNS against concurrent transactional updates +# + +. $PCP_DIR/etc/pcp.env + +lock=${1-$PCP_VAR_DIR/pmns/root}.lock + +i=0 +while true +do + if pmlock $lock + then + # lock acquired + # + #DEBUG# echo "pmnslock: `date; ls -li $lock`" + break + fi + if [ $i -eq 20 ] + then + echo "lockpmns: Warning: Unable to acquire lock ($lock)" + echo " after 120 seconds ... continuing anyway" + exit 1 + fi + sleep 5 + i=`expr $i + 1` +done + +exit 0 diff --git a/src/pmns/pmnsadd b/src/pmns/pmnsadd new file mode 100755 index 0000000..a14e4ad --- /dev/null +++ b/src/pmns/pmnsadd @@ -0,0 +1,125 @@ +#!/bin/sh +# +# Copyright (c) 1997-2001 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Add a subtree of new names into the namespace in the current directory +# + +# source the PCP configuration environment variables +. $PCP_DIR/etc/pcp.env + +umask 22 # anything else is pretty silly +exitsts=1 +tmp=`mktemp -d $PCP_TMPFILE_DIR/pcp.XXXXXXXXX` || exit 1 +prog=`basename $0` +trap "rm -rf $tmp; exit \$exitsts" 0 1 2 3 15 + +_usage() +{ + echo "Usage: pmnsadd [-d] [-n namespace] file" +} + +namespace=${PMNS_DEFAULT-$PCP_VAR_DIR/pmns/root} +dupok="" + +while getopts dn:\? c +do + case $c + in + d) dupok="-d" + ;; + n) namespace=$OPTARG + ;; + \?) _usage + exitsts=0 + exit + ;; + esac +done +shift `expr $OPTIND - 1` + +if [ $# -ne 1 ] +then + _usage + exit +fi + +if [ ! -f $namespace ] +then + echo "$prog: cannot find PMNS file \"$root\"" + exit +fi + +if [ ! -w $namespace ] +then + echo "$prog: cannot open PMNS file \"$root\" for writing" + exit +fi + +if [ ! -f "$1" ] +then + echo "$prog: cannot find input file \"$1\"" + exit +fi + +if grep '^root {' "$1" >/dev/null +then + # Special case ... if the PMDA only supplies metrics at the root of + # the PMNS, e.g. the MMV PMDA with all dynamic metrics, the input + # PMNS contains 'root {' already, so just use that without any need + # to construct the upper levels of the PMNS + # + cp "$1" $tmp/tmp +else + # Normal case ... find PMNS pathname for base of new subtree + # (subroot), construct upper levels of PMNS as required and hand-off + # to pmnsmerge + # + subroot=`$PCP_AWK_PROG <"$1" 'NF >= 2 && $2 == "{" { print $1 ; exit }'` + echo 'root {' >$tmp/tmp + path="" + for name in `echo "$subroot" | tr '.' ' '` + do + [ ! -z "$path" ] && echo "$path {" >>$tmp/tmp + echo " $name" >>$tmp/tmp + echo "}" >>$tmp/tmp + if [ -z "$path" ] + then + path="$name" + else + path="$path.$name" + fi + done + cat "$1" >>$tmp/tmp +fi + +# try to preserve mode, owner and group for the new output files +# +rm -f $namespace.new +[ -f $namespace ] && cp -p $namespace $namespace.new + +$PCP_BINADM_DIR/pmnsmerge -f $dupok $namespace $tmp/tmp $namespace.new +exitsts=$? + +# from here on, ignore SIGINT, SIGHUP and SIGTERM to protect +# the integrity of the new ouput files +# +trap "" 1 2 15 + +if [ $exitsts = 0 ] +then + mv $namespace.new $namespace +else + echo "$prog: No changes have been made to the PMNS file \"$namespace\"" + rm -f $namespace.new +fi diff --git a/src/pmns/pmnsdel.c b/src/pmns/pmnsdel.c new file mode 100644 index 0000000..01a0150 --- /dev/null +++ b/src/pmns/pmnsdel.c @@ -0,0 +1,216 @@ +/* + * Cull subtree(s) from a PCP PMNS + * + * Copyright (c) 2014 Red Hat. + * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <ctype.h> +#include <sys/stat.h> +#include "pmapi.h" +#include "impl.h" +#include "pmnsutil.h" + +static FILE *outf; /* output */ +static __pmnsNode *root; /* result so far */ +static char *fullname; /* full PMNS pathname for newbie */ + +static pmLongOptions longopts[] = { + PMAPI_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, + { "duplicates", 0, 'd', 0, "duplicate PMIDs are allowed" }, + PMOPT_NAMESPACE, + PMOPT_HELP, + PMAPI_OPTIONS_END +}; + +static pmOptions opts = { + .short_options = "dD:n:?", + .long_options = longopts, + .short_usage = "[options] metricpath [...]", +}; + +static void +delpmns(__pmnsNode *base, char *name) +{ + char *tail; + ptrdiff_t nch; + __pmnsNode *np; + __pmnsNode *lastp = NULL; + + for (tail = name; *tail && *tail != '.'; tail++) + ; + nch = tail - name; + + for (np = base->first; np != NULL; np = np->next) { + if (strlen(np->name) == nch && strncmp(name, np->name, (int)nch) == 0) + break; + lastp = np; + } + + if (np == NULL) { + /* no match ... */ + fprintf(stderr, "%s: Error: metricpath \"%s\" not defined in the PMNS\n", + pmProgname, fullname); + exit(1); + } + else if (*tail == '\0') { + /* complete match */ + if (np == base->first) { + /* deleted node is first at this level */ + base->first = np->next; + /* + * remove predecessors that only exist to connect + * deleted node to the rest of the PMNS + */ + np = base; + while (np->first == NULL && np->parent != NULL) { + if (np->parent->first == np) { + /* victim is the only one at this level ... */ + np->parent->first = np->next; + np = np->parent; + } + else { + /* victim has at least one sibling at this level */ + lastp = np->parent->first; + while (lastp->next != np) + lastp = lastp->next; + lastp->next = np->next; + break; + } + } + } + else + /* link around deleted node */ + lastp->next = np->next; + return; + } + + /* descend */ + delpmns(np, tail+1); +} + +int +main(int argc, char **argv) +{ + int sep = __pmPathSeparator(); + int sts; + int c; + int dupok = 0; + char *p; + char pmnsfile[MAXPATHLEN]; + char outfname[MAXPATHLEN]; + struct stat sbuf; + + if ((p = getenv("PMNS_DEFAULT")) != NULL) + strcpy(pmnsfile, p); + else + snprintf(pmnsfile, sizeof(pmnsfile), "%s%c" "pmns" "%c" "root", + pmGetConfig("PCP_VAR_DIR"), sep, sep); + + while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) { + switch (c) { + + case 'd': /* duplicate PMIDs are OK */ + dupok = 1; + break; + + case 'D': /* debug flag */ + if ((sts = __pmParseDebug(opts.optarg)) < 0) { + pmprintf("%s: unrecognized debug flag specification (%s)\n", + pmProgname, opts.optarg); + opts.errors++; + } else { + pmDebug |= sts; + } + break; + + case 'n': /* alternative name space file */ + strcpy(pmnsfile, opts.optarg); + break; + + case '?': + default: + opts.errors++; + break; + } + } + + if (opts.errors || opts.optind > argc - 1) { + pmUsageMessage(&opts); + exit(1); + } + + if ((sts = pmLoadASCIINameSpace(pmnsfile, dupok)) < 0) { + fprintf(stderr, "%s: Error: pmLoadNameSpace(%s): %s\n", + pmProgname, pmnsfile, pmErrStr(sts)); + exit(1); + } + + { + __pmnsTree *t; + t = __pmExportPMNS(); + if (t == NULL) { + /* sanity check - shouldn't ever happen */ + fprintf(stderr, "Exported PMNS is NULL !"); + exit(1); + } + root = t->root; + } + + + while (opts.optind < argc) { + delpmns(root, fullname = argv[opts.optind]); + opts.optind++; + } + + /* + * from here on, ignore SIGHUP, SIGINT and SIGTERM to protect + * the integrity of the new ouput file + */ + __pmSetSignalHandler(SIGHUP, SIG_IGN); + __pmSetSignalHandler(SIGINT, SIG_IGN); + __pmSetSignalHandler(SIGTERM, SIG_IGN); + + snprintf(outfname, sizeof(outfname), "%s.new", pmnsfile); + if ((outf = fopen(outfname, "w")) == NULL) { + fprintf(stderr, "%s: Error: cannot open PMNS file \"%s\" for writing: %s\n", + pmProgname, outfname, osstrerror()); + exit(1); + } + if (stat(pmnsfile, &sbuf) == 0) { + /* + * preserve the mode and ownership of any existing PMNS file + */ + chmod(outfname, sbuf.st_mode & ~S_IFMT); +#if defined(HAVE_CHOWN) + if (chown(outfname, sbuf.st_uid, sbuf.st_gid) < 0) + fprintf(stderr, "%s: chown(%s, ...) failed: %s\n", + pmProgname, outfname, osstrerror()); +#endif + } + + pmns_output(root, outf); + fclose(outf); + + /* rename the PMNS */ + if (rename2(outfname, pmnsfile) == -1) { + fprintf(stderr, "%s: cannot rename \"%s\" to \"%s\": %s\n", + pmProgname, outfname, pmnsfile, osstrerror()); + /* remove the new PMNS */ + unlink(outfname); + exit(1); + } + + exit(0); +} diff --git a/src/pmns/pmnsmerge.c b/src/pmns/pmnsmerge.c new file mode 100644 index 0000000..39316a1 --- /dev/null +++ b/src/pmns/pmnsmerge.c @@ -0,0 +1,322 @@ +/* + * pmnsmerge [-adfv] infile [...] outfile + * + * Merge PCP PMNS files + * + * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <ctype.h> +#include <sys/stat.h> +#include "pmapi.h" +#include "impl.h" +#include "pmnsutil.h" + +static FILE *outf; /* output */ +static __pmnsNode *root; /* result so far */ +static char *fullname; /* full PMNS pathname for newbie */ +static int verbose; + +static pmLongOptions longopts[] = { + PMAPI_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, + { "", 0, 'a', 0, "process files in order, ignoring embedded _DATESTAMP control lines" }, + { "duplicates", 0, 'd', 0, "duplicate PMIDs are allowed" }, + { "force", 0, 'f', 0, "force overwriting of the output file if it exists" }, + { "verbose", 0, 'v', 0, "verbose, echo input file names as processed" }, + PMOPT_HELP, + PMAPI_OPTIONS_END +}; + +static pmOptions opts = { + .short_options = "aD:dfv?", + .long_options = longopts, + .short_usage = "[options] infile [...] outfile", +}; + +typedef struct { + char *fname; + char *date; +} datestamp_t; + +#define STAMP "_DATESTAMP" + +static int +sortcmp(const void *a, const void *b) +{ + datestamp_t *pa = (datestamp_t *)a; + datestamp_t *pb = (datestamp_t *)b; + + if (pa->date == NULL) return -1; + if (pb->date == NULL) return 1; + return strcmp(pa->date, pb->date); +} + +/* + * scan for #define _DATESTAMP and re-order args accordingly + */ +static void +sortargs(char **argv, int argc) +{ + FILE *f; + datestamp_t *tab; + char *p; + char *q; + int i; + char lbuf[40]; + + tab = (datestamp_t *)malloc(argc * sizeof(datestamp_t)); + + for (i = 0; i <argc; i++) { + if ((f = fopen(argv[i], "r")) == NULL) { + fprintf(stderr, "%s: Error: cannot open input PMNS file \"%s\"\n", + pmProgname, argv[i]); + exit(1); + } + tab[i].fname = strdup(argv[i]); + tab[i].date = NULL; + while (fgets(lbuf, sizeof(lbuf), f) != NULL) { + if (strncmp(lbuf, "#define", 7) != 0) + continue; + p = &lbuf[7]; + while (*p && isspace((int)*p)) + p++; + if (*p == '\0' || strncmp(p, STAMP, strlen(STAMP)) != 0) + continue; + p += strlen(STAMP); + while (*p && isspace((int)*p)) + p++; + q = p; + while (*p && !isspace((int)*p)) + p++; + *p = '\0'; + tab[i].date = strdup(q); + break; + } + fclose(f); + } + + qsort(tab, argc, sizeof(tab[0]), sortcmp); + for (i = 0; i <argc; i++) { + argv[i] = tab[i].fname; + if (verbose > 1) + printf("arg[%d] %s _DATESTAMP=%s\n", i, tab[i].fname, tab[i].date); + } + + free(tab); +} + +static void +addpmns(__pmnsNode *base, char *name, __pmnsNode *p) +{ + char *tail; + ptrdiff_t nch; + __pmnsNode *np; + __pmnsNode *lastp = NULL; + + for (tail = name; *tail && *tail != '.'; tail++) + ; + nch = tail - name; + + for (np = base->first; np != NULL; np = np->next) { + if (strlen(np->name) == nch && strncmp(name, np->name, (int)nch) == 0) + break; + lastp = np; + } + + if (np == NULL) { + /* no match ... add here */ + np = (__pmnsNode *)malloc(sizeof(__pmnsNode)); + if (base->first) { + lastp->next = np; + np->parent = lastp->parent; + } + else { + base->first = np; + np->parent = base; + } + np->first = np->next = NULL; + np->hash = NULL; /* we do not need this here */ + np->name = (char *)malloc(nch+1); + strncpy(np->name, name, nch); + np->name[nch] = '\0'; + if (*tail == '\0') { + np->pmid = p->pmid; + return; + } + np->pmid = PM_ID_NULL; + } + else if (*tail == '\0') { + /* complete match */ + if (np->pmid != p->pmid) { + fprintf(stderr, "%s: Warning: performance metric \"%s\" has multiple PMIDs.\n... using PMID %s and ignoring PMID", + pmProgname, fullname, pmIDStr(np->pmid)); + fprintf(stderr, " %s\n", + pmIDStr(p->pmid)); + } + return; + } + + /* descend */ + addpmns(np, tail+1, p); +} + + +/* + * merge, adding new nodes if required + */ +static void +merge(__pmnsNode *p, int depth, char *path) +{ + char *name; + + if (depth < 1 || p->pmid == PM_ID_NULL || p->first != NULL) + return; + name = (char *)malloc(strlen(path)+strlen(p->name)+2); + if (*path == '\0') + strcpy(name, p->name); + else { + strcpy(name, path); + strcat(name, "."); + strcat(name, p->name); + } + fullname = name; + addpmns(root, name, p); + free(name); +} + +int +main(int argc, char **argv) +{ + int sts; + int first = 1; + int c; + int j; + int force = 0; + int asis = 0; + int dupok = 0; + __pmnsNode *tmp; + + umask((mode_t)022); /* anything else is pretty silly */ + + while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) { + switch (c) { + + case 'a': + asis = 1; + break; + + case 'd': /* duplicate PMIDs are OK */ + dupok = 1; + break; + + case 'D': /* debug flag */ + if ((sts = __pmParseDebug(opts.optarg)) < 0) { + pmprintf("%s: unrecognized debug flag specification (%s)\n", + pmProgname, opts.optarg); + opts.errors++; + } else { + pmDebug |= sts; + } + break; + + case 'f': /* force ... unlink file first */ + force = 1; + break; + + case 'v': + verbose++; + break; + + case '?': + default: + opts.errors++; + break; + } + } + + if (opts.errors || opts.optind > argc - 2) { + pmUsageMessage(&opts); + exit(1); + } + + if (force) + unlink(argv[argc-1]); + + if (access(argv[argc-1], F_OK) == 0) { + fprintf(stderr, "%s: Error: output PMNS file \"%s\" already exists!\nYou must either remove it first, or use -f\n", + pmProgname, argv[argc-1]); + exit(1); + } + + /* + * from here on, ignore SIGHUP, SIGINT and SIGTERM to protect + * the integrity of the new ouput file + */ + __pmSetSignalHandler(SIGHUP, SIG_IGN); + __pmSetSignalHandler(SIGINT, SIG_IGN); + __pmSetSignalHandler(SIGTERM, SIG_IGN); + + if ((outf = fopen(argv[argc-1], "w+")) == NULL) { + fprintf(stderr, "%s: Error: cannot create output PMNS file \"%s\": %s\n", pmProgname, argv[argc-1], osstrerror()); + exit(1); + } + + if (!asis) + sortargs(&argv[opts.optind], argc - opts.optind - 1); + + j = opts.optind; + while (j < argc-1) { + if (verbose) + printf("%s:\n", argv[j]); + + if ((sts = pmLoadASCIINameSpace(argv[j], dupok)) < 0) { + fprintf(stderr, "%s: Error: pmLoadNameSpace(%s): %s\n", + pmProgname, argv[j], pmErrStr(sts)); + exit(1); + } + { + __pmnsTree *t; + t = __pmExportPMNS(); + if (t == NULL) { + /* sanity check - shouldn't ever happen */ + fprintf(stderr, "Exported PMNS is NULL !"); + exit(1); + } + tmp = t->root; + } + + if (first) { + root = tmp; + first = 0; + } + else { + pmns_traverse(tmp, 0, "", merge); + } + j++; + } + + pmns_output(root, outf); + fclose(outf); + + /* + * now load the merged PMNS to check for errors ... + */ + if ((sts = pmLoadASCIINameSpace(argv[argc-1], dupok)) < 0) { + fprintf(stderr, "%s: Error: pmLoadNameSpace(%s): %s\n", + pmProgname, argv[argc-1], pmErrStr(sts)); + exit(1); + } + + exit(0); +} diff --git a/src/pmns/pmnsutil.c b/src/pmns/pmnsutil.c new file mode 100644 index 0000000..1e0acf9 --- /dev/null +++ b/src/pmns/pmnsutil.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1995 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "pmapi.h" +#include "impl.h" +#include "pmnsutil.h" + +static FILE *outf; + +/* + * breadth-first traversal + */ +void +pmns_traverse(__pmnsNode *p, int depth, char *path, void(*func)(__pmnsNode *, int, char *)) +{ + char *newpath; + __pmnsNode *q; + + if (p != NULL) { + /* breadth */ + for (q = p; q != NULL; q = q->next) + (*func)(q, depth, path); + if (depth > 0) + (*func)(NULL, -1, NULL); /* end of level */ + /* descend */ + for (q = p; q != NULL; q = q->next) { + if (q->first != NULL) { + newpath = (char *)malloc(strlen(path)+strlen(q->name)+2); + if (depth == 0) + *newpath = '\0'; + else if (depth == 1) + strcpy(newpath, q->name); + else { + strcpy(newpath, path); + strcat(newpath, "."); + strcat(newpath, q->name); + } + pmns_traverse(q->first, depth+1, newpath, func); + free(newpath); + } + } + } +} + +/* + * generate an ASCII PMNS from the internal format produced by + * pmLoadNameSpace and friends + */ +static void +output(__pmnsNode *p, int depth, char *path) +{ + static int lastdepth = -1; + + if (depth == 0) { + fprintf(outf, "root {\n"); + lastdepth = 1; + return; + } + else if (depth < 0) { + if (lastdepth > 0) + fprintf(outf, "}\n"); + lastdepth = -1; + return; + } + else if (depth != lastdepth) + fprintf(outf, "\n%s {\n", path); + lastdepth = depth; + if (p->first != NULL) + fprintf(outf, "\t%s\n", p->name); + else { + if (pmid_domain(p->pmid) == DYNAMIC_PMID && pmid_item(p->pmid) == 0) + fprintf(outf, "\t%s\t%d:*:*\n", p->name, pmid_cluster(p->pmid)); + else + fprintf(outf, "\t%s\t%d:%d:%d\n", p->name, pmid_domain(p->pmid), pmid_cluster(p->pmid), pmid_item(p->pmid)); + } +} + +void +pmns_output(__pmnsNode *root, FILE *f) +{ + outf = f; + pmns_traverse(root, 0, "", output); + output(NULL, -2, NULL); /* special hack for null PMNS */ +} diff --git a/src/pmns/pmnsutil.h b/src/pmns/pmnsutil.h new file mode 100644 index 0000000..dd6c536 --- /dev/null +++ b/src/pmns/pmnsutil.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +extern void pmns_traverse(__pmnsNode *, int , char *, void(*)(__pmnsNode *, int, char *)); +extern void pmns_output(__pmnsNode *, FILE *); + diff --git a/src/pmns/stdpmid.local b/src/pmns/stdpmid.local new file mode 100644 index 0000000..6d55daa --- /dev/null +++ b/src/pmns/stdpmid.local @@ -0,0 +1,5 @@ +# Domain numbers for local PMDAs +# +# PMDA Name Domain Number +# +#EXAMPLE 123 diff --git a/src/pmns/stdpmid.pcp b/src/pmns/stdpmid.pcp new file mode 100644 index 0000000..1296c81 --- /dev/null +++ b/src/pmns/stdpmid.pcp @@ -0,0 +1,128 @@ +# Domain numbers for PMDAs in the base PCP product +# +# PMDA Name Domain Number +# +IRIX 1 +PMCD 2 +PROC 3 +ENVIRON 4 +CISCO 5 +HIPPI 6 +HOTPROC 7 +NETPROBE 8 +MAILQ 9 +TRACE 10 +XFS 11 +FSAFE 12 +MPI 13 +DMF 14 +SENDMAIL 15 +XVM 16 +BROCADE 17 +ESPPING 18 +SHPING 19 +HPUX 20 +WEBPING 21 +WEBSERVER 22 +ARRAY0 23 +ARRAY1 24 +ARRAY2 25 +ARRAY3 26 +SYSSUMMARY 27 +NEWS 28 +SAMPLE 29 +SAMPLEDSO 30 +KERN_DEV 31 +ORACLE 32 +SYBASE 40 +INFORMIX 48 +SNMP 56 +LOCKSTAT 59 +LINUX 60 +MYRINET 61 +NFSCLIENT 62 +SNIA 63 +CLUSTER 65 +MYSQL 66 +LOGTAIL 67 +APACHE 68 +ROOMTEMP 69 +MMV 70 +PROCESS 71 +MOUNTS 72 +SNIFF 73 +LMSENSORS 74 +SOLARIS 75 +SAMBA 76 +NFS 77 +DARWIN 78 +WINDOWS 79 +AIX 80 +TG3 81 +CXFS 82 +FCSW 83 +CPUSET 84 +FREEBSD 85 +RPCBIND 86 +ETW 87 +SYSTEMTAP 88 +MEMCACHE 89 +VMWARE 90 +IB 91 +ISCSI 92 +LUSTRECOMM 93 +SDR 94 +KVM 95 +BONDING 96 +NETFILTER 97 +ZIMBRA 98 +UV 99 +NAMED 100 +PDNS 101 +DTSRUN 102 +POSTFIX 103 +IPMI 104 +GPSD 105 +LOGGER 106 +RSYSLOG 107 +ELASTICSEARCH 108 +MSSQL 109 +POSTGRESQL 110 +CTDB 111 /* Clustered Trivial Database (samba.org) */ +BASH 112 +FIBRECHANNEL 113 +SYSTEMD 114 +GFS2 115 +NETBSD 116 +NGINX 117 +GLUSTER 118 +PANASAS 119 +NVML 120 +CIFS 121 +JBD2 122 +RPM 123 +QPID 124 +ZSWAP 125 +PAPI 126 +PERFEVENT 127 +PIPE 128 +DMCACHE 129 +### NEXT FREE SLOT ### +SLOW_PYTHON 242 +SLOW 243 +DBPING 244 +PMI_DOMAIN 245 +LAB 246 +DYNAMIC 247 +TXMON 248 +BROKEN 249 +TRIVIAL 250 +SYBPING 251 +INFMXPING 252 +SIMPLE 253 +ORAPING 254 +### MORE FREE SLOTS ### +# +# 511 is REALLY reserved ... see DYNAMIC_PMID in impl.h +# +RESERVED_DO_NOT_USE 511 diff --git a/src/pmns/unlockpmns b/src/pmns/unlockpmns new file mode 100644 index 0000000..69d094c --- /dev/null +++ b/src/pmns/unlockpmns @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Unlock the PMNS for concurrent transactional updates +# + +. $PCP_DIR/etc/pcp.env + +lock=${1-$PCP_VAR_DIR/pmns/root}.lock + +#DEBUG# echo "pmnsunlock: `date; ls -li $lock`" + +rm -f $lock + +exit 0 |