diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
commit | 47e6e7c84f008a53061e661f31ae96629bc694ef (patch) | |
tree | 648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmview/front-ends/pmview-args | |
download | pcp-debian.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmview/front-ends/pmview-args')
-rw-r--r-- | src/pmview/front-ends/pmview-args | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/src/pmview/front-ends/pmview-args b/src/pmview/front-ends/pmview-args new file mode 100644 index 0000000..31a7008 --- /dev/null +++ b/src/pmview/front-ends/pmview-args @@ -0,0 +1,625 @@ +# Copyright (c) 1995-2005 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. +# + +prog=`basename $0` + +PMVIEW=pmview +PMPROBE=pmprobe +CONFIRM="$PCP_XCONFIRM_PROG" +ECHONL="echo -n" +_multiple_sources=false + +# +# Standard usage and command-line argument parsing for pmview front ends. +# This file should be included by pmview front end scripts to present a +# consistent interface. See pmview(1), dkvis(1), mpvis(1) and nfsvis(1) +# for more information on their respective interfaces. +# + +# +# The front end scripts should call _pmview_usage after their own usage +# information in a subroutine called _usage. The _usage subroutine may be +# called by either _pmview_note or _pmview_args. +# +_pmview_usage() +{ + if $_multiple_sources + then + echo -n ' + -A align align sample times on natural boundaries + -a archive[,archive...] + metrics source is one or more PCP archive logs + -C check configuration file and exit + -h host[,host...] metrics source is PMCD on one or more hosts' + + else + + echo -n ' + -A align align sample times on natural boundaries + -a archive metrics source is a PCP archive log + -C check configuration file and exit + -h host metrics source is PMCD on host' + + fi + + echo ' + -n pmnsfile use an alternative PMNS + -O offset initial offset into the time window + -p port port name for connection to existing time control + -S starttime start of the time window + -T endtime end of the time window + -t interval sample interval [default 2.0 seconds] + -x version use pmlaunch(5) version [default version 2.0] + -z set reporting timezone to local time of metrics source + -Z timezone set reporting timezone + + -display display-string + -geometry geometry-string + -name name-string + -title title-string + -xrm resource' +} + +# Most front-end scripts can handle input from only one source, and +# hence only one -h or -a option. +# +# For those than can handle multiple sources, they should call +# _pmview_multiple_sources_are_ok before calling _pmview_args to +# enable the following extensions to the -a and -h options: +# -a a1 -a a2 ... multiple -a options +# -h h1 -h h2 ... multiple -h options +# -a a1,a2,... multiple archives with the -a option +# -h h1,h2,... multiple hosts with the -h option +# +_pmview_multiple_sources_are_ok() +{ + _multiple_sources=true +} + +# check for magic numbers in a file that indicate it is a PCP archive +# +# if file(1) was reliable, this would be much easier, ... sigh +# +# if you need to change this, make consistent changes in all these +# places: +# _check_file() in src/pmafm/mkaf +# _is_archive() in src/pmafm/pmafm +# _is_archive() in src/pmview/front-ends/pmview-args +# +_is_archive() +{ + case "$PCP_PLATFORM" in + irix) + dd ibs=1 count=7 if="$1" 2>/dev/null | od -X | $PCP_AWK_PROG ' +NR == 1 && $2 == "00000084" && $3 == "50052600" { exit 0 } + { exit 1 }' + ;; + linux) + dd ibs=1 count=7 if="$1" 2>/dev/null | od -x | $PCP_AWK_PROG ' +NR == 1 && NF == 5 && $2 == "0000" && $3 == "0084" && $4 == "5005" && $5 == "2600" { exit 0 } +NR == 1 && NF == 5 && $2 == "0000" && $3 == "8400" && $4 == "0550" && $5 == "0026" { exit 0 } + + { exit 1 }' + ;; + esac + return $? +} + +# One of the first actions of a front end script should be to call +# _pmview_args. It sets the following variables: +# +# host the first host specified with -h (if any) in the format +# hostname +# else the host from the first archive in the format +# hostname (Archive archivename) +# arch the first archive specified with -a (if any). +# All archives are passed on to pmview with one -a +# argument per archive via $args +# numsource Number of metrics sources (hosts or archives) +# args The list of args that pmview will comprehend and use. +# otherArgs The arguments pmview will not understand and should be +# handled by the front end script. +# titleArg The title the user prefers. If empty, the title should be +# provided by the front end script. +# prog The name of the program. +# namespace The namespace (including the flag) if specified, else empty +# eg "-n foo" +# msource The default metrics source, whether live or an archive, +# including the flag. e.g. "-h blah" or "-a first_archive". +# Taken from the first encountered -a or -h option. +# +# sourcelist space separated list of hosts or archives +# +_pmview_args() +{ + +_seen_host=false +_seen_arch=false +host="" +arch="" +numsource=0 +args="" +otherArgs="" +titleArg="" +namespace="" +msource="" + +if [ $# -eq 1 -a '$1' = '-\?' ] +then + _usage + exit 0 +fi + +while [ $# -gt 0 ] +do + case $1 + in + -g*|-di*|-name|-xrm) + # assume an X11 argument + if [ $# -lt 2 ] + then + _pmview_note Usage-Error error "$prog: X-11 option $1 requires one argument" + #NOTREACHED + fi + args="$args $1 '$2'" + shift + ;; + + -title) + # assume an X11 argument + if [ $# -lt 2 ] + then + _pmview_note Usage-Error error "$prog: Option $1 requires one argument" + #NOTREACHED + exit 1 + fi + titleArg="$2" + shift + ;; + + -A|-D|-O|-p|-S|-T|-t|-x|-Z) + if [ $# -lt 2 ] + then + _pmview_note Usage-Error error "$prog: Option $1 requires one argument" + #NOTREACHED + fi + args="$args $1 '$2'" + shift + ;; + + -A*|-D*|-O*|-p*|-S*|-T*|-t*|-Z*|-C|-z) + args="$args $1" + ;; + + -a) + if $_seen_host + then + _pmview_note Usage-Error error "$prog: Only one of the -h or -a options may be specified" + #NOTREACHED + fi + if [ $# -lt 2 ] + then + _pmview_note Usage-Error error "$prog: Option $1 requires one argument" + #NOTREACHED + fi + for _archbase in `echo "$2" | sed -e 's/,/ /g'` + do + if [ $numsource -gt 0 -a $_multiple_sources = false ] + then + _pmview_note Usage-Error error "$prog: Only one -a option may be specified" + # NOTREACHED + fi + if _is_archive $_archbase 2>&1 + then + _archbase=`echo $_archbase | sed -e 's/\.[^.]*$//'` + fi + # at least $_archbase.0 and $_archbase.meta have to be here + # + if _is_archive $_archbase.0 && _is_archive $_archbase.meta + then + : + else + _pmview_note Error error "$prog: \"$_archbase\" is not the basename of a valid PCP archive" + #NOTREACHED + fi + if [ -z "$arch" ] + then + # first archive seen + # + arch=$_archbase + msource="-a $_archbase" + host=`pmdumplog -l $arch \ + | $PCP_AWK_PROG '/^Performance/ {print $5}' \ + | sed -e 's/,//g'` + [ "X$host" = X ] && host="unknown host" + host="$host (Archive $arch)" + fi + + # pmview(1) can handle multiple -a options, so + # pass _all_ archive names back to the caller both as + # -a options via $args and in $sourcelist (counted by + # $numsource). + # + # Note: multiple -h options are handled slightly + # differently, see also the comments for -h below. + # + + args="$args -a $_archbase" + if [ -z "$sourcelist" ]; then + sourcelist=$_archbase + else + sourcelist="$sourcelist $_archbase" + fi + numsource=`expr $numsource + 1` + done + _seen_arch=true + shift + ;; + + -h) + if $_seen_arch + then + _pmview_note Usage-Error error "$prog: Only one of the -h or -a options may be specified" + #NOTREACHED + fi + if [ $# -lt 2 ] + then + _pmview_note Usage-Error error "$prog: Option $1 requires one argument" + #NOTREACHED + fi + for _host in `echo "$2" | sed -e 's/,/ /g'` + do + if [ $numsource -gt 0 -a $_multiple_sources = false ] + then + _pmview_note Usage-Error error "$prog: Only one -h option may be specified" + # NOTREACHED + fi + if [ -z "$host" ] + then + host=$_host + msource="-h $_host" + + # pmview(1) can handle only one -h options, so + # pass the _first_ host name back to the caller as a + # -h option via $args and _all_ hostnames via + # $sourcelist (counted by $numsource). + # + # Note: multiple -a options are handled slightly + # differently, see also the comments for -a above. + # + + args="$args -h $_host" + fi + if [ -z "$sourcelist" ]; then + sourcelist=$_host + else + sourcelist="$sourcelist $_host" + fi + numsource=`expr $numsource + 1` + done + _seen_host=true + shift + ;; + + -n) + if [ $# -lt 2 ] + then + _pmview_note Usage-Error error "$prog: Option $1 requires one argument" + #NOTREACHED + fi + namespace="-n $2" + args="$args -n $2" + shift + ;; + + *) + otherArgs="$otherArgs $1" + ;; + + esac + shift + +done + +if [ -z "$host" ] +then + host=`pmhostname` + msource="-h $host" +fi +} + +# standard fatal error reporting +# Usage: _pmview_error message goes in here +# _pmview_error -f file +# +_pmview_error() +{ + _pmview_note Error error $* +} + +# standard warning +# Usage: _pmview_warning message goes in here +# _pmview_warning -f file +# +_pmview_warning() +{ + _pmview_note Warning warning $* +} + +# standard info +# Usage: _pmview_info message goes in here +# _pmview_info -f file +# +_pmview_info() +{ + _pmview_note Info info $* +} + +# generic notifier +# Usage: _pmview_note tag icon args ... +# +_pmview_note() +{ + tag=$1; shift + icon=$1; shift + button="" + [ $tag = Error ] && button="-B Quit" + [ $tag = Usage-Error ] && button="-B Quit -b Usage" + + [ X"$PCP_STDERR" = XDISPLAY -a -z "$DISPLAY" ] && unset PCP_STDERR + + if [ $# -eq 2 -a "X$1" = X-f ] + then + case "$PCP_STDERR" + in + DISPLAY) + ans=`$CONFIRM -icon $icon -file $2 -useslider -header "$tag $prog" $button 2>&1` + ;; + '') + echo "$tag:" >&2 + cat $2 >&2 + ans=Quit + ;; + *) + echo "$tag:" >>$PCP_STDERR + cat $2 >>$PCP_STDERR + ans=Quit + ;; + esac + else + case "$PCP_STDERR" + in + DISPLAY) + ans=`$CONFIRM -icon $icon -t "$*" -noframe -header "$tag $prog" $button 2>&1` + ;; + '') + echo "$tag: $*" >&2 + ans=Quit + ;; + *) + echo "$tag: $*" >>$PCP_STDERR + ans=Quit + ;; + esac + fi + + if [ $tag = Usage-Error ] + then + [ $ans = Usage ] && _usage + tag=Error + fi + + [ $tag = Error ] && exit 1 +} + +# used internally by _pmview_cache_fetch() and _pmview_fetch() +# +_pmview_probe() +{ + flag=$1 + shift + ( echo $* \ + ; echo "-----" \ + ; ( $PMPROBE $namespace $msource $flag $* 2>$tmp.pmview_err \ + | tee -a $tmp.pmview_fetch \ + ) \ + ) \ + | tr ' ' '\012' \ + | sed -e 's/"//g' \ + | $PCP_AWK_PROG ' +BEGIN { last = 0 } +$1 == "-----" { state = 1; next } +state == 0 { metric[last] = pat[last] = $1 + # deal with arguments that are non-terminals in the PMNS + # so pmprobe a.b => a.b.c a.b.c.x a.b.d etc + gsub("\\.", "\\.", pat[last]) + pat[last] = "^" pat[last] "\\." + last++ + next + } +state > 0 { for (i = 0; i < last; i++) { + if (metric[i] == $1 || match($1, pat[i]) > 0) { + # new matching metric name + name=$1 + state=2 + next + } + } + } +state == 2 { if ($1 > 0) state = 3 + else state = 1 + next + } +state == 3 { printf("%s%s|%s\n", "'"$flag|$msource|"'",name,$1) }' +} + +# Fetch metrics and cache result +# input +# $1 - pmprobe flag +# $* - 1 or more metrics +# output +# $tmp.pmview_cache - cached values, with this format +# pmprobe flag|metric source|metric name|pmprobe result +# +_pmview_cache_fetch() +{ + flag=$1 + shift + _pmview_probe $flag $* >>$tmp.pmview_cache + + return 0 +} + +# Fetch metrics +# +# input +# $1 - pmprobe flag +# $2 - metric name +# output +# $number - number of values +# $tmp.pmview_result - values +# +_pmview_fetch() +{ + flag=$1 + metric=$2 + rm -f $tmp.pmview_fetch $tmp.pmview_result + if [ -s $tmp.pmview_cache ] + then + $PCP_AWK_PROG -F\| \ + <$tmp.pmview_cache >$tmp.pmview_result \ +' +$1 == "'"$flag"'" && $2 == "'"$msource"'" && $3 == "'"$metric"'" { print $4 }' + fi + + if [ ! -s $tmp.pmview_result ] + then + # cache miss, forced to probe + # + _pmview_probe $flag $metric \ + | $PCP_AWK_PROG -F\| >$tmp.pmview_result '{print $4}' + fi + + if [ -s $tmp.pmview_result ] + then + number=`wc -l <$tmp.pmview_result | sed -e 's/ //g'` + else + if [ -s $tmp.pmview_fetch ] + then + check=`cut -d ' ' -f 2 $tmp.pmview_fetch` + if [ "$check" = "$metric" ] + then + # *.pmview_fetch looks valid, extract numval from 2nd field + # + number=`cut -d ' ' -f 2 $tmp.pmview_fetch` + else + # *.pmview_fetch exists, but does not contain + # pmprobe output, more than likely this is some + # sort of fatal error message ... but _real_ message + # is likely to be in *.pmview_err + # + [ -s $tmp.pmview_err ] && mv $tmp.pmview_err $tmp.pmview_fetch + number=-1 + fi + else + number=-1 + mv $tmp.pmview_err $tmp.pmview_fetch + fi + fi + if [ $number -le 0 ] + then + rm -f $tmp.pmview_result + return 1 + fi + + return 0 +} + +# Fetch the metric values +# +# input +# $1 - metric name +# output +# $number - number of values +# $tmp.pmview_result - values +# +_pmview_fetch_values() +{ + _pmview_fetch -v $1 + return $? +} + +# Fetch the metric instance list +# +# input +# $1 - metric name +# output +# $number - number of instances +# $tmp.pmview_result - instances +# +_pmview_fetch_indom() +{ + _pmview_fetch -I $1 + return $? +} + +# Convert pmprobe/pminfo error message into something useful and +# consistent +# +_pmview_fetch_mesg() +{ + $PCP_AWK_PROG ' +$1 == "pmprobe:" { $1 = "'$prog':"; print; exit } +$1 == "pminfo:" { $1 = "'$prog':"; print; exit } +$1 == "Error:" { $1 = ":"; + printf("%s: %s%s\n", "'$prog'", metric, $0); exit } +$1 == "inst" { exit } +NF == 1 { metric = $1; next } +NF == 0 { next } +NF == 2 && $2 == "0" { printf("%s: %s: No values available\n", "'$prog'", $1); exit} + { $2 = ":"; print "'$prog': " $0; exit}' \ + | sed "s/ : /: /" \ + | fmt +} + +# Generate error metric for failed fetch +# +_pmview_fetch_fail() +{ + cat $tmp.pmview_fetch | _pmview_fetch_mesg >> $tmp.msg + echo "$prog: Failed to $1 from host \"$host\"" | fmt >> $tmp.msg + _pmview_error -f $tmp.msg + # NOTREACHED +} + +# Generate warning message for failed fetch +# +_pmview_fetch_warn() +{ + cat $tmp.pmview_fetch | _pmview_fetch_mesg >> $tmp.msg + echo "$prog: Failed to $1 from host \"$host\"" | fmt >> $tmp.msg + _pmview_warning -f $tmp.msg + rm -f $tmp.msg +} + +# Check that $OPTARG for option $1 is a positive integer +# ...note the creative use of unary - to prevent leading signs +# +_pmview_unsigned() +{ + if [ "X-$OPTARG" != "X`expr 0 + -$OPTARG 2>/dev/null`" ] + then + _pmview_error "$prog: -$1 option must have a positive integral argument" + # NOTREACHED + fi +} |