diff options
Diffstat (limited to 'src/pmlogger/pmlogmv.sh')
-rwxr-xr-x | src/pmlogger/pmlogmv.sh | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/src/pmlogger/pmlogmv.sh b/src/pmlogger/pmlogmv.sh new file mode 100755 index 0000000..7a07098 --- /dev/null +++ b/src/pmlogger/pmlogmv.sh @@ -0,0 +1,261 @@ +#!/bin/sh +# +# Copyright (c) 1997,2003 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (c) 2013-2014 Red Hat. +# Copyright (c) 2014 Ken McDonell. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Move (rename) a PCP archive. +# +# Operation is atomic across the multiple files of a PCP archive +# + +. $PCP_DIR/etc/pcp.env + +status=1 +tmp=`mktemp -d /tmp/pcp.XXXXXXXXX` || exit 1 +trap "rm -rf $tmp; exit \$status" 0 +trap "_cleanup; rm -rf $tmp; exit \$status" 1 2 3 15 +prog=`basename $0` + +cat > $tmp/usage << EOF +# Usage: [options] oldname newname + +Options: + -N, --showme perform a dry run, showing what would be done + -V, --verbose increase diagnostic verbosity + --help +EOF + +_usage() +{ + pmgetopt --progname=$prog --config=$tmp/usage --usage + exit 1 +} + +verbose=false +showme=false +LN=ln +RM=rm +RMF="rm -f" + +ARGS=`pmgetopt --progname=$prog --config=$tmp/usage -- "$@"` +[ $? != 0 ] && exit 1 + +eval set -- "$ARGS" +while [ $# -gt 0 ] +do + case "$1" + in + -N) # show me + showme=true + LN='echo >&2 + ln' + RM='echo >&2 + rm' + RMF='echo >&2 + rm -f' + ;; + -V) # verbose + verbose=true + ;; + --) + shift + break + ;; + -\?) + _usage + # NOTREACHED + ;; + esac + shift +done + +if [ $# -ne 2 ] +then + _usage + # NOTREACHED +fi + +if [ -f "$1" ] +then + # oldname is an existing file, strip the expected PCP suffix + # + case "$1" + in + *[0-9]) + old=`echo "$1" | sed -e 's/\.[0-9][0-9]*$//'` + ;; + *.index|*.meta) + old=`echo "$1" | sed -e 's/\.[a-z][a-z]*$//'` + ;; + *) + echo >&2 "$prog: Error: oldname argument ($1) is not a PCP archive" + exit + ;; + esac +else + old="$1" +fi +new="$2" + +_cleanup() +{ + if [ -f $tmp/old ] + then + for f in `cat $tmp/old` + do + if [ ! -f "$f" ] + then + part=`echo "$f" | sed -e 's/.*\.\([^.][^.]*\)$/\1/'` + if [ ! -f "$new.$part" ] + then + echo >&2 "$prog: Fatal: $f and $new.$part lost" + ls -l "$old"* "$new"* + rm -f $tmp/old + return + fi + $verbose && echo >&2 "cleanup: recover $f from $new.$part" + if eval $LN "$new.$part" "$f" + then + : + else + echo >&2 "$prog: Fatal: ln $new.$part $f failed!" + ls -l "$old"* "$new"* + rm -f $tmp/old + return + fi + fi + done + fi + if [ -f $tmp/new ] + then + for f in `cat $tmp/new` + do + $verbose && echo >&2 "cleanup: remove $f" + eval $RMF "$f" + done + rm -f $tmp/new + fi + exit +} + +# get oldnames inventory check required files are present +# +ls "$old".* 2>&1 | egrep '\.(index|meta|[0-9][0-9]*)$' >$tmp/old +if [ -s $tmp/old ] +then + # $old may be an ambiguous suffix, e.g. 20140417.00 (with more than + # one .HH archives) ... pick the suffixes and make sure there are + # no duplicates + # + touch $tmp/ok + sed <$tmp/old \ + -e 's/.*\.index$/index/' \ + -e 's/.*\.meta$/meta/' \ + -e 's/.*\.\([0-9][0-9]*\)$/\1/' \ + | sort \ + | uniq -c \ + | while read c x + do + case $c + in + 1) + ;; + *) + echo >&2 "$prog: Error: oldname argument ($old) is a prefix for multiple PCP archive files:" + grep "\\.$x\$" $tmp/old | sed -e 's/^/ /' >&2 + rm -f $tmp/ok + ;; + esac + done + [ -f $tmp/ok ] || exit +else + echo >&2 "$prog: Error: cannot find any files for the input archive ($old)" + exit +fi +if grep -q '.[0-9][0-9]*$' $tmp/old +then + : +else + echo >&2 "$prog: Error: cannot find any data files for the input archive ($old)" + ls -l "$old"* + exit +fi +if grep -q '.meta$' $tmp/old +then + : +else + echo >&2 "$prog: Error: cannot find .metadata file for the input archive ($old)" + ls -l "$old"* + exit +fi + +# (hard) link oldnames and newnames +# +for f in `cat $tmp/old` +do + if [ ! -f "$f" ] + then + echo >&2 "$prog: Error: ln-pass: input file vanished: $f" + ls -l "$old"* "$new"* + _cleanup + # NOTREACHED + fi + part=`echo "$f" | sed -e 's/.*\.\([^.][^.]*\)$/\1/'` + if [ -f "$new.$part" ] + then + echo >&2 "$prog: Error: ln-pass: output file already exists: $new.$part" + ls -l "$old"* "$new"* + _cleanup + # NOTREACHED + fi + $verbose && echo >&2 "link $f -> $new.$part" + echo "$new.$part" >>$tmp/new + if eval $LN "$f" "$new.$part" + then + : + else + echo >&2 "$prog: Error: ln $f $new.$part failed!" + ls -l "$old"* "$new"* + _cleanup + # NOTREACHED + fi +done + +# unlink oldnames provided link count is 2 +# +for f in `cat $tmp/old` +do + if [ ! -f "$f" ] + then + echo >&2 "$prog: Error: rm-pass: input file vanished: $f" + ls -l "$old"* "$new"* + _cleanup + # NOTREACHED + fi + links=`stat $f | sed -n -e '/Links:/s/.*Links:[ ]*\([0-9][0-9]*\).*/\1/p'` + xpect=2 + $showme && xpect=1 + if [ -z "$links" -o "$links" != $xpect ] + then + echo >&2 "$prog: Error: rm-pass: link count "$links" (not $xpect): $f" + ls -l "$old"* "$new"* + _cleanup + fi + $verbose && echo >&2 "remove $f" + if eval $RM "$f" + then + : + else + echo >&2 "$prog: Warning: rm $f failed!" + fi +done + +status=0 |