Index: devpcp/src/pmie/src/pmie.c =================================================================== --- devpcp.orig/src/pmie/src/pmie.c 2007-03-16 17:19:39.709133250 +1100 +++ devpcp/src/pmie/src/pmie.c 2007-03-20 13:45:07.183300750 +1100 @@ -71,6 +71,7 @@ static char *prompt = "pmie> "; static char *intro = "Performance Co-Pilot Inference Engine (pmie), " "Version %s\n\n%s%s"; +static FILE *logfp; static char logfile[MAXPATHLEN+1]; static char perffile[PMIE_PATHSIZE]; /* /var/tmp/ file name */ @@ -396,6 +397,42 @@ sigbye(int sig) static void +remap_stdout_stderr(void) +{ + int i, j; + + fflush(stderr); + fflush(stdout); + setlinebuf(stderr); + setlinebuf(stdout); + i = fileno(stdout); + close(i); + if ((j = dup(fileno(stderr))) != i) + fprintf(stderr, "%s: Warning: failed to link stdout ... " + "dup() returns %d, expected %d (stderr=%d)\n", + pmProgname, j, i, fileno(stderr)); +} + +/*ARGSUSED*/ +static void +sighupproc(int sig) +{ + FILE *fp; + int sts; + + fp = __pmRotateLog(pmProgname, logfile, logfp, &sts); + if (sts != 0) { + fprintf(stderr, "pmie: PID = %d, default host = %s\n\n", + (int)getpid(), dfltHost); + remap_stdout_stderr(); + logfp = fp; + } else { + __pmNotifyErr(LOG_ERR, "pmie: log rotation failed\n"); + } +} + + +static void dotraceback(void) { #if HAVE_TRACE_BACK_STACK @@ -653,7 +690,6 @@ getargs(int argc, char *argv[]) perf = &instrument; if (isdaemon) { /* daemon mode */ - signal(SIGHUP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTSTP, SIG_IGN); @@ -669,30 +705,22 @@ getargs(int argc, char *argv[]) } if (commandlog != NULL) { - __pmOpenLog(pmProgname, commandlog, stderr, &sts); + logfp = __pmOpenLog(pmProgname, commandlog, stderr, &sts); if (realpath(commandlog, logfile) == NULL) { fprintf(stderr, "%s: cannot find realpath for log %s: %s\n", pmProgname, commandlog, strerror(oserror())); exit(1); } + signal(SIGHUP, isdaemon ? sighupproc : SIG_IGN); + } else { + signal(SIGHUP, SIG_IGN); } - if (bflag) { - /* - * -b ... force line buffering and stdout onto stderr - */ - int i, j; - - fflush(stderr); - fflush(stdout); - setlinebuf(stderr); - setlinebuf(stdout); - i = fileno(stdout); - close(i); - if ((j = dup(fileno(stderr))) != i) - fprintf(stderr, "%s: Warning: failed to link stdout (-b option) " - "... dup() returns %d, expected %d\n", pmProgname, j, i); - } + /* + * -b ... force line buffering and stdout onto stderr + */ + if (bflag || isdaemon) + remap_stdout_stderr(); if (__pmGetLicense(PM_LIC_MON, pmProgname, GET_LICENSE_SHOW_EXP) == PM_LIC_MON || @@ -771,7 +799,9 @@ getargs(int argc, char *argv[]) */ if (isdaemon) { /* daemon mode */ - close(fileno(stdin)); /* ensure stdin closed for daemon */ + /* Note: we can no longer close stdin here, as it can really + * confuse remap_stdout_stderr() during log rotation! + */ setsid(); /* not process group leader, lose controlling tty */ } Index: devpcp/src/pmie/GNUmakefile =================================================================== --- devpcp.orig/src/pmie/GNUmakefile 2007-03-16 17:19:39.769137000 +1100 +++ devpcp/src/pmie/GNUmakefile 2007-03-16 17:19:46.001526500 +1100 @@ -28,7 +28,7 @@ include $(TOPDIR)/src/include/builddefs SUBDIRS = src examples LSRCFILES = control etc_init.d_pmie pmie_check.sh crontab config.default \ - pmie2col stomp.install + pmie2col stomp.install pmie_daily.sh LDIRT = control.install config.default.install CFG_DIR = $(PCP_VAR_DIR)/config/pmie @@ -49,6 +49,7 @@ install:: default $(INSTALL) -m 644 stomp.install $(CFG_DIR)/stomp $(INSTALL) -m 755 etc_init.d_pmie $(PCP_RC_DIR)/pmie $(INSTALL) -m 755 pmie_check.sh $(PCP_BINADM_DIR)/pmie_check + $(INSTALL) -m 755 pmie_daily.sh $(PCP_BINADM_DIR)/pmie_daily $(INSTALL) -m 755 pmie2col $(PCP_BIN_DIR)/pmie2col include $(BUILDRULES) Index: devpcp/src/pmie/pmie_daily.sh =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ devpcp/src/pmie/pmie_daily.sh 2007-03-21 08:49:21.945955250 +1100 @@ -0,0 +1,477 @@ +#! /bin/sh +#Tag 0x00010D13 +# +# Copyright (c) 1995-2000,2003 Silicon Graphics, Inc. All Rights Reserved. +# Portions Copyright (c) 2007 Aconex. 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., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, +# Mountain View, CA 94043, USA, or: http://www.sgi.com +# +# Example daily administrative script for pmie logfiles +# + +# Get standard environment +. /etc/pcp.env + +# Get the portable PCP rc script functions +if [ -f $PCP_SHARE_DIR/lib/rc-proc.sh ] ; then + . $PCP_SHARE_DIR/lib/rc-proc.sh +fi + +# added to handle problem when /var/log/pcp is a symlink, as first +# reported by Micah_Altman@xxxxxxxxxxx in Nov 2001 +# +_unsymlink_path() +{ + [ -z "$1" ] && return + __d=`dirname $1` + __real_d=`cd $__d 2>/dev/null && /bin/pwd` + if [ -z "$__real_d" ] + then + echo $1 + else + echo $__real_d/`basename $1` + fi +} + +# error messages should go to stderr, not the GUI notifiers +# +unset PCP_STDERR + +# constant setup +# +tmp=/tmp/$$ +status=0 +echo >$tmp.lock +trap "rm -f \`[ -f $tmp.lock ] && cat $tmp.lock\` $tmp.*; exit \$status" 0 1 2 3 15 +prog=`basename $0` + +# control file for pmie administration ... edit the entries in this +# file to reflect your local configuration (see also -c option below) +# +CONTROL=$PCP_VAR_DIR/config/pmie/control + +# default number of days to keep pmie logfiles +# +CULLAFTER=14 + +# default compression program +# +COMPRESS=bzip2 +COMPRESSAFTER="" +COMPRESSREGEX=".meta$|.index$|.Z$|.gz$|.bz2$|.zip$" + +# determine real name for localhost +LOCALHOSTNAME=`hostname | sed -e 's/\..*//'` +[ -z "$LOCALHOSTNAME" ] && LOCALHOSTNAME=localhost + +# determine path for pwd command to override shell built-in +# (see BugWorks ID #595416). +PWDCMND=`which pwd 2>/dev/null | $PCP_AWK_PROG ' +BEGIN { i = 0 } +/ not in / { i = 1 } +/ aliased to / { i = 1 } + { if ( i == 0 ) print } +'` +if [ -z "$PWDCMND" ] +then + # Looks like we have no choice here... + # force it to a known IRIX location + PWDCMND=/bin/pwd +fi + +_usage() +{ + cat - <$tmp.lock +} + +# filter for pmie log files in working directory - +# pass in the number of days to skip over (backwards) from today +# +# pv:821339 too many sed commands for IRIX ... split into groups +# of at most 200 days +# +_date_filter() +{ + # start with all files whose names match the patterns used by + # the PCP pmie log file management scripts ... this list may be + # reduced by the sed filtering later on + # + ls | sed -n >$tmp.in -e '/[-.][12][0-9][0-9][0-9][0-1][0-9][0-3][0-9]$/p' + + i=0 + while [ $i -le $1 ] + do + dmax=`expr $i + 200` + [ $dmax -gt $1 ] && dmax=$1 + echo "/[-.][12][0-9][0-9][0-9][0-1][0-9][0-3][0-9]$/{" >$tmp.sed1 + while [ $i -le $dmax ] + do + x=`pmdate -${i}d %Y%m%d` + echo "/[-.]$x\$/d" >>$tmp.sed1 + i=`expr $i + 1` + done + echo "p" >>$tmp.sed1 + echo "}" >>$tmp.sed1 + + # cull file names with matching dates, keep other file names + # + sed -n -f $tmp.sed1 <$tmp.in >$tmp.tmp + mv $tmp.tmp $tmp.in + done + + cat $tmp.in +} + + +rm -f $tmp.err +line=0 +version='' +cat $CONTROL \ +| sed -e "s/LOCALHOSTNAME/$LOCALHOSTNAME/g" \ + -e "s;PCP_LOG_DIR;$PCP_LOG_DIR;g" \ +| while read host socks logfile args +do + logfile=`_unsymlink_path $logfile` + line=`expr $line + 1` + $VERY_VERBOSE && echo "[control:$line] host=\"$host\" socks=\"$socks\" log=\"$logfile\" args=\"$args\"" + case "$host" + in + \#*|'') # comment or empty + continue + ;; + + \$*) # in-line variable assignment + $SHOWME && echo "# $host $socks $logfile $args" + cmd=`echo "$host $socks $logfile $args" \ + | sed -n \ + -e "/='/s/\(='[^']*'\).*/\1/" \ + -e '/="/s/\(="[^"]*"\).*/\1/' \ + -e '/=[^"'"'"']/s/[;&<>|].*$//' \ + -e '/^\\$[A-Za-z][A-Za-z0-9_]*=/{ +s/^\\$// +s/^\([A-Za-z][A-Za-z0-9_]*\)=/export \1; \1=/p +}'` + if [ -z "$cmd" ] + then + # in-line command, not a variable assignment + _warning "in-line command is not a variable assignment, line ignored" + else + case "$cmd" + in + 'export PATH;'*) + _warning "cannot change \$PATH, line ignored" + ;; + 'export IFS;'*) + _warning "cannot change \$IFS, line ignored" + ;; + *) + $SHOWME && echo "+ $cmd" + eval $cmd + ;; + esac + fi + continue + ;; + esac + + if [ -z "$socks" -o -z "$logfile" -o -z "$args" ] + then + _error "insufficient fields in control file record" + continue + fi + + if $VERY_VERBOSE + then + echo "Check pmie -h $host ... in $dir ..." + fi + + dir=`dirname $logfile` + if [ ! -d "$dir" ] + then + _error "logfile directory ($dir) does not exist" + continue + fi + + cd $dir + dir=`$PWDCMND` + $SHOWME && echo "+ cd $dir" + + if $VERBOSE + then + echo + echo "=== daily maintenance of pmie log files for host $host ===" + echo + fi + + if [ ! -w $dir ] + then + echo "$prog: Warning: no write access in $dir, skip lock file processing" + else + # demand mutual exclusion + # + fail=true + rm -f $tmp.stamp + for try in 1 2 3 4 + do + if pmlock -v lock >$tmp.out + then + echo $dir/lock >$tmp.lock + fail=false + break + else + if [ ! -f $tmp.stamp ] + then + touch -t `pmdate -30M %Y%m%d%H%M` $tmp.stamp + fi + if [ ! -z "`find lock -newer $tmp.stamp -print 2>/dev/null`" ] + then + : + else + echo "$prog: Warning: removing lock file older than 30 minutes" + LC_TIME=POSIX ls -l $dir/lock + rm -f lock + fi + fi + sleep 5 + done + + if $fail + then + # failed to gain mutex lock + # + if [ -f lock ] + then + echo "$prog: Warning: is another PCP cron job running concurrently?" + LC_TIME=POSIX ls -l $dir/lock + else + echo "$prog: `cat $tmp.out`" + fi + _warning "failed to acquire exclusive lock ($dir/lock) ..." + continue + fi + fi + + # match $logfile and $fqdn from control file to running pmies + pid="" + fqdn=`pmhostname $host` + for file in `ls $PCP_TMP_DIR/pmie` + do + p_id=$file + file="$PCP_TMP_DIR/pmie/$file" + p_logfile="" + p_pmcd_host="" + + case "$PCP_PLATFORM" + in + irix) + test -f /proc/pinfo/$p_id + ;; + *) + test -e /proc/$p_id + ;; + esac + if [ $? -eq 0 ] + then + eval `tr '\0' '\012' < $file | sed -e '/^$/d' | sed -e 3q | $PCP_AWK_PROG ' +NR == 2 { printf "p_logfile=\"%s\"\n", $0; next } +NR == 3 { printf "p_pmcd_host=\"%s\"\n", $0; next } + { next }'` + p_logfile=`_unsymlink_path $p_logfile` + if [ "$p_logfile" = $logfile -a "$p_pmcd_host" = "$fqdn" ] + then + pid=$p_id + break + fi + else + # ignore, its not a running process + eval $RM -f $file + fi + done + + if [ -z "$pid" ] + then + _error "no pmie instance running for host \"$host\"" + else + if [ "`echo $pid | wc -w`" -gt 1 ] + then + _error "multiple pmie instances running for host \"$host\", processes: $pid" + _unlock + continue + fi + + # now move current logfile name aside and SIGHUP to "roll the logs" + # creating a new logfile with the old name in the process. + # + $SHOWME && echo "+ mv $logfile ${logfile}.{SUMMARY_LOGNAME}" + if mv $logfile ${logfile}.${SUMMARY_LOGNAME} + then + kill -HUP $pid + else + _error "problems moving logfile \"$logfile\" for host \"$host\"" + touch $tmp.err + fi + fi + + # and cull old logfiles + # + if [ X"$CULLAFTER" != X"forever" ] + then + _date_filter $CULLAFTER >$tmp.list + if [ -s $tmp.list ] + then + if $VERBOSE + then + echo "Log files older than $CULLAFTER days being removed ..." + fmt <$tmp.list | sed -e 's/^/ /' + fi + if $SHOWME + then + cat $tmp.list | xargs echo + rm -f + else + cat $tmp.list | xargs rm -f + fi + fi + fi + + # finally, compress old log files + # (after cull - don't compress unnecessarily) + # + if [ ! -z "$COMPRESSAFTER" ] + then + _date_filter $COMPRESSAFTER | egrep -v "$COMPRESSREGEX" >$tmp.list + if [ -s $tmp.list ] + then + if $VERBOSE + then + echo "Log files older than $COMPRESSAFTER days being compressed ..." + fmt <$tmp.list | sed -e 's/^/ /' + fi + if $SHOWME + then + cat $tmp.list | xargs echo + $COMPRESS + else + cat $tmp.list | xargs $COMPRESS + fi + fi + fi + + _unlock + +done + +[ -f $tmp.err ] && status=1 +exit Index: devpcp/src/pmlogctl/pmlogger_daily.sh =================================================================== --- devpcp.orig/src/pmlogctl/pmlogger_daily.sh 2007-03-16 17:19:39.829140750 +1100 +++ devpcp/src/pmlogctl/pmlogger_daily.sh 2007-03-20 16:01:05.949191750 +1100 @@ -58,9 +58,9 @@ CULLAFTER=14 # default compression program # -COMPRESS=compress +COMPRESS=bzip2 COMPRESSAFTER="" -COMPRESSREGEX=".meta$|.index$|.Z$|.gz$" +COMPRESSREGEX=".meta$|.index$|.Z$|.gz$|.bz2$|.zip$" # threshold size to roll $PCP_LOG_DIR/NOTICES # @@ -417,7 +417,7 @@ s/^\([A-Za-z][A-Za-z0-9_]*\)=/export \1; then pflag='' [ $primary = y ] && pflag=' -P' - echo "Check pmlogger$flag -h $host ... in $dir ..." + echo "Check pmlogger$pflag -h $host ... in $dir ..." fi if [ ! -d $dir ] Index: devpcp/src/pmie/pmie_check.sh =================================================================== --- devpcp.orig/src/pmie/pmie_check.sh 2007-03-16 17:19:39.773137250 +1100 +++ devpcp/src/pmie/pmie_check.sh 2007-03-20 16:01:05.881187500 +1100 @@ -72,7 +72,7 @@ prog=`basename $0` CONTROL=$PCP_VAR_DIR/config/pmie/control # determine real name for localhost -LOCALHOSTNAME=`hostname` +LOCALHOSTNAME=`hostname | sed -e 's/\..*//'` if [ -z "$LOCALHOSTNAME" ] then echo "$prog: Error: cannot determine hostname, giving up" @@ -152,7 +152,7 @@ _message() case $1 in 'restart') - echo -n "Restarting pmie for host \"$host\" ..." + $PCP_ECHO_PROG $PCP_ECHO_N "Restarting pmie for host \"$host\" ..." ;; esac } Index: devpcp/man/man1/pmlogger_daily.1 =================================================================== --- devpcp.orig/man/man1/pmlogger_daily.1 2007-03-16 17:19:39.913146000 +1100 +++ devpcp/man/man1/pmlogger_daily.1 2007-03-20 15:31:50.227466000 +1100 @@ -100,7 +100,7 @@ option specifies the number of days afte files, and the .B \-X option specifies the program to use for compression \- by default this is -.BR compress (1). +.BR bzip2 (1). Use of the .B \-Y option allows a regular expression to be specified causing files in @@ -108,11 +108,10 @@ the set of files matched for compression only the data file to be compressed, and also prevents the program from attempting to compress it more than once. The default .I regex -is ".meta$|.index$|.Z$|.gz$" \- such files are filtered using the +is ".meta$|.index$|.Z$|.gz$|.bz2|.zip$" \- such files are filtered using the .B \-v option to .BR egrep (1). -.B .PP In addition, if the PCP ``notices'' file (\c @@ -341,9 +340,9 @@ for root if automated PCP archive log ma .nf .ft CW # daily processing of archive logs -10 0 * * * $PCP_BINADM_DIR/pmlogger_daily +14 0 * * * $PCP_BINADM_DIR/pmlogger_daily # every 30 minutes, check pmlogger instances are running -25,55 * * * * $PCP_BINADM_DIR/pmlogger_check +28,58 * * * * $PCP_BINADM_DIR/pmlogger_check .ft 1 .fi .PP @@ -444,11 +443,11 @@ other configuration files suited for particular PCP monitoring tools, add-on products and application environments .TP -.BI $PCP_LOG_DIR/pmlogger hostname +.BI $PCP_LOG_DIR/pmlogger/ hostname default location for archives of performance information collected from the host .I hostname .TP -.BI $PCP_LOG_DIR/pmlogger hostname /lock +.BI $PCP_LOG_DIR/pmlogger/ hostname /lock transient lock file to guarantee mutual exclusion during .B pmlogger administration for the host @@ -459,7 +458,7 @@ nor .B pmlogger_check are running .TP -.BI $PCP_LOG_DIR/pmlogger hostname /Latest +.BI $PCP_LOG_DIR/pmlogger/ hostname /Latest PCP archive folio created by .BR mkaf (1) for the most recently launched archive containing performance metrics from @@ -485,7 +484,7 @@ configuration file, as described in .BR pcp.conf (4). .SH SEE ALSO -.BR compress (1), +.BR bzip2 (1), .BR cron (1), .BR egrep (1), .BR PCP (1), Index: devpcp/man/man1/pmie_check.1 =================================================================== --- devpcp.orig/man/man1/pmie_check.1 2007-03-16 17:19:39.969149500 +1100 +++ devpcp/man/man1/pmie_check.1 2007-03-20 15:32:02.180213000 +1100 @@ -33,20 +33,76 @@ .rr X \} .SH NAME -\f3pmie_check\f1 -\- administration of the Performance Co-Pilot inference engine +\f3pmie_check\f1, +\f3pmie_daily\f1 \- administration of the Performance Co-Pilot inference engine .SH SYNOPSIS .B $PCP_BINADM_DIR/pmie_check [\f3\-NsV\f1] [\f3\-c\f1 \f2control\f1] +.br +.B $PCP_BINADM_DIR/pmie_daily +[\f3\-NV\f1] +[\f3\-c\f1 \f2control\f1] +[\f3\-k\f1 \f2discard\f1] +[\f3\-x\f1 \f2compress\f1] +[\f3\-X\f1 \f2program\f1] +[\f3\-Y\f1 \f2regex\f1] +.br .SH DESCRIPTION -This shell script and associated control file may be used to +This series of shell scripts and associated control files may be used to create a customized regime of administration and management for the Performance Co-Pilot (see .BR PCPintro (1)) inference engine, .BR pmie (1). .PP +.B pmie_daily +is intended to be run once per day, preferably in the early morning, as +soon after midnight as practicable. Its task is to rotate the log files +for the running +.B pmie +processes \- these files may grow without bound if the +``print'' action is used, or any other +.B pme +action writes to its stdout/stderr streams. +After some period, old +.B pmie +log files are discarded. +This period is 14 days by default, but may be changed using the +.B \-k +option. Two special values are recognized for the period (\c +.IR discard ), +namely +.B 0 +to keep no log files beyond the current one, and +.B forever +to prevent any log files being discarded. +.PP +Log files can optionally be compressed after some period (\c +.IR compress ), +to conserve disk space. This is particularly useful for large numbers of +.B pmie +processes under the control of +.BR pmie_check . +The +.B \-x +option specifies the number of days after which to compress archive data +files, and the +.B \-X +option specifies the program to use for compression \- by default this is +.BR bzip2 (1). +Use of the +.B \-Y +option allows a regular expression to be specified causing files in +the set of files matched for compression to be omitted \- this allows +only the data file to be compressed, and also prevents the program from +attempting to compress it more than once. The default +.I regex +is ".meta$|.index$|.Z$|.gz$|.bz2|.zip$" \- such files are filtered using the +.B \-v +option to +.BR egrep (1). +.PP .B pmie_check may be run at any time, and is intended to check that the desired set of @@ -58,8 +114,11 @@ option provides the reverse functionalit .B pmie processes to be cleanly shutdown. .PP +Both .B pmie_check -is controlled by a PCP inference engine control file that specifies the +and +.B pmie_daily +are controlled by a PCP inference engine control file that specifies the .B pmie instances to be managed. The default control file is .B $PCP_VAR_DIR/config/pmie/control @@ -184,8 +243,8 @@ and another monitoring performance metri .PP .nf .ft CW -wobbly n $PCP_LOG_DIR/pmie/wobbly -c $PCP_VAR_DIR/config/pmie/config.default -splat n $PCP_LOG_DIR/pmie/splat -c $PCP_LOG_DIR/pmie/splat/cpu.conf +wobbly n PCP_LOG_DIR/pmie/wobbly -c pmie/config.default +splat n PCP_LOG_DIR/pmie/splat -c pmie/splat/cpu.conf .ft 1 .fi .PP @@ -199,8 +258,10 @@ and shown below. .PP .nf .ft CW +# daily processing of pmie logs +14 0 * * * $PCP_BINADM_DIR/pmie_daily # every 30 minutes, check pmie instances are running -25,55 * * * * $PCP_BINADM_DIR/pmie_check +28,58 * * * * $PCP_BINADM_DIR/pmie_check .ft 1 .fi .PP @@ -275,15 +336,20 @@ other than root. .B $PCP_VAR_DIR/config/pmie/crontab sample crontab for automated script execution by root .TP -.BI logfile .lock -transient lock file which is named using the control-specified +.BI $PCP_LOG_DIR/pmie/ hostname +default location for the pmie log file for the host +.I hostname +.TP +.BI $PCP_LOG_DIR/pmie/ hostname /lock +transient lock file to guarantee mutual exclusion during .B pmie -.I logfile -names, and is used to guarantee mutual exclusion during -.B pmie_check -execution \- if present, can be safely removed if +administration for the host +.I hostname +\- if present, can be safely removed if neither +.B pmie_daily +nor .B pmie_check -is not running +are running .TP .B $PCP_LOG_DIR/NOTICES PCP ``notices'' file used by Index: devpcp/src/include/impl.h =================================================================== --- devpcp.orig/src/include/impl.h 2007-03-16 17:19:39.881144000 +1100 +++ devpcp/src/include/impl.h 2007-03-16 17:19:46.045529250 +1100 @@ -202,6 +202,7 @@ extern int __pmHasPMNSFileChanged(const /* standard log file set up */ extern FILE *__pmOpenLog(const char *, const char *, FILE *, int *); +extern FILE *__pmRotateLog(const char *, const char *, FILE *, int *); /* make __pmNotifyErr also add entries to syslog */ extern void __pmSyslog(int); /* standard error, warning and info wrapper for syslog(3C) */ Index: devpcp/src/libpcp/src/util.c =================================================================== --- devpcp.orig/src/libpcp/src/util.c 2007-03-16 17:19:39.837141250 +1100 +++ devpcp/src/libpcp/src/util.c 2007-03-19 15:51:15.064601250 +1100 @@ -57,32 +57,6 @@ char *pmProgname = "pcp"; /* the real static int vpmprintf(const char *, va_list); -static void -onexit(void) -{ - int i; - time_t now; - - /* - * there is a race condition here ... but the worse that can happen - * is (a) no "Log finished" message, or (b) _two_ "Log finished" - * messages ... neither case is serious enough to warrant a mutex guard - */ - if (++done_exit != 1) - return; -#if defined(IRIX5_3) - if (lucky_pid != getpid()) { - done_exit--; - return; - } -#endif - - (void)time(&now); - for (i = 0; i < nfilelog; i++) { - fprintf(filelog[i], "\nLog finished %s", ctime(&now)); - } -} - /* * if onoff == 1, logging is to syslog and stderr, else logging is * just to stderr (this is the default) @@ -167,12 +141,56 @@ __pmNotifyErr(int priority, const char * pmflush(); } -FILE * -__pmOpenLog(const char *progname, const char *logname, FILE *oldstream, - int *status) +static void +logheader(const char *progname, FILE *log, const char *act) { time_t now; char host[MAXHOSTNAMELEN]; + + setlinebuf(log); /* line buffering for log files */ + gethostname(host, MAXHOSTNAMELEN); + host[MAXHOSTNAMELEN-1] = '\0'; + time(&now); + fprintf(log, "Log for %s on %s %s %s\n", progname, host, act, ctime(&now)); +} + +static void +logfooter(FILE *log, const char *act) +{ + time_t now; + + time(&now); + fprintf(log, "\nLog %s %s", act, ctime(&now)); +} + +static void +logonexit(void) +{ + int i; + + /* + * there is a race condition here ... but the worse that can happen + * is (a) no "Log finished" message, or (b) _two_ "Log finished" + * messages ... neither case is serious enough to warrant a mutex guard + */ + if (++done_exit != 1) + return; +#if defined(IRIX5_3) + if (lucky_pid != getpid()) { + done_exit--; + return; + } +#endif + + for (i = 0; i < nfilelog; i++) + logfooter(filelog[i], "finished"); +} + +/* common code shared by __pmRotateLog and __pmOpenLog */ +static FILE * +logreopen(const char *progname, const char *logname, FILE *oldstream, + int *status) +{ int oldfd; int dupoldfd; FILE *dupoldstream = oldstream; @@ -223,13 +241,15 @@ __pmOpenLog(const char *progname, const *status = 1; } close(dupoldfd); - setlinebuf(oldstream); /* line buffering for log files */ - (void)gethostname(host, MAXHOSTNAMELEN); - host[MAXHOSTNAMELEN-1] = '\0'; - time(&now); - fprintf(oldstream, "Log for %s on %s started %s\n", - progname, host, ctime(&now)); + return oldstream; +} +FILE * +__pmOpenLog(const char *progname, const char *logname, FILE *oldstream, + int *status) +{ + oldstream = logreopen(progname, logname, oldstream, status); + logheader(progname, oldstream, "started"); /* * atexit() race condition in IRIX 5.3 measn we have to be very careful @@ -237,18 +257,36 @@ __pmOpenLog(const char *progname, const */ nfilelog++; if (nfilelog == 1) { - atexit(onexit); + atexit(logonexit); #if defined(IRIX5_3) lucky_pid = getpid(); #endif } - if ((filelog = (FILE **)realloc(filelog, nfilelog * sizeof(FILE *))) == NULL) { + filelog = (FILE **)realloc(filelog, nfilelog * sizeof(FILE *)); + if (filelog == NULL) { __pmNoMem("__pmOpenLog", nfilelog * sizeof(FILE *), PM_FATAL_ERR); /*NOTREACHED*/ } filelog[nfilelog-1] = oldstream; + return oldstream; +} +FILE * +__pmRotateLog(const char *progname, const char *logname, FILE *oldstream, + int *status) +{ + int i; + + for (i = 0; i < nfilelog; i++) { + if (oldstream == filelog[i]) { + logfooter(oldstream, "rotated"); /* old */ + oldstream = logreopen(progname, logname, oldstream, status); + logheader(progname, oldstream, "rotated"); /* new */ + filelog[i] = oldstream; + break; + } + } return oldstream; } Index: devpcp/man/man3/pmopenlog.3 =================================================================== --- devpcp.orig/man/man3/pmopenlog.3 2007-03-16 17:32:06.783822500 +1100 +++ devpcp/man/man3/pmopenlog.3 2007-03-16 17:32:30.753320500 +1100 @@ -60,11 +60,11 @@ event of an error, this will be .I oldstream unchanged and .I status -will be 1. +will be 0. .PP For success, .I status -is 0, a standard preamble is written to +is 1, a standard preamble is written to .I logname .ti +0.5i .ft B