#!/bin/sh
#
# @(#)nsrdbmi.sh 1.35 97/02/27 Copyright (c) 1997, Legato Systems, Inc.
#
# All rights reserved.
#
# nsrdbmi
#
# This script is part of the Database Module for Informix.
# Modification of this script should be done with care and only after reading
# the administration manual included with this product.
#
# This script should only be run as part of a scheduled savegroup.
#
# Returns 0 on success; 1 on failure.
#

#
# Configuration variables, modifiable by users.
#

#
# Variable: PRECMD
# Default value: NONE
# Description: This variable can be used to run a command before dbspace and
# log file backups.  This command can be used to run a command to check the
# database for corruption.
#
PRECMD=

#
# Variable: POSTCMD
# Default value: NONE
# Description: This variable can be used to run a command after dbspace and
# log file backups have completed.  It can be used to check the status of
# the logical logs and dbspaces.
#
POSTCMD=

#
# Variable: NSR_DATA_VOLUME_POOL
# Default value: DBMIData
# Description: If this variable is set to name a media pool, then dbspace
# backups will be directed to the named media pool.
#
NSR_DATA_VOLUME_POOL="DBMIData"

#
# Variable: DO_LOGFILE_BACKUPS
# Default value: YES
# Description: If this variable is set to YES, then logfile backups will be
# executed after dbspace backups.
#
DO_LOGFILE_BACKUPS=YES

#
# Variable: NSR_LOG_VOLUME_POOL
# Default value: DBMILogs
# Description: If this variable is set to name a media pool, then logfile
# backups will be directed to the named media pool.
#
NSR_LOG_VOLUME_POOL="DBMILogs"

#
# Variable: NSR_COMPRESSION
# Default value: FALSE
# Description: This environment variable specifies which kind of compression
# is performed on the data.
#
NSR_COMPRESSION=FALSE

#
# Variable: INFORMIXDIR
# Default value: /usr/informix
# Description: Specifies where the Informix RDBMS is installed.
#
INFORMIXDIR=/usr/informix

#
# Variable: ONCONFIG
# Default value: onconfig
# Description: Specifies which Informix RDBMS configuration file to use.
#
ONCONFIG=onconfig.std

#
# Variable: INFORMIXSQLHOSTS
# Default value: $INFORMIXDIR/etc/sqlhosts
# Description: Describes where the sqlhosts file is located.
#
INFORMIXSQLHOSTS=$INFORMIXDIR/etc/sqlhosts

#
# Set up PATH environment variable.  This must be configured to include
# path to the "onbar" executable and the NetWorker program "mminfo".
#
PATH=$INFORMIXDIR/bin:/bin:/usr/sbin:/opt/networker/bin:/usr/bin

#
# Shell and environment variables not configured by user.
#
NSR_BACKUP_LEVEL=0	# Level of backup (passed by savegrp)
NSR_SERVER=""		# Server to backup to (passed by savegrp)
NSR_SAVESET_NAME=""	# Name of save set name
echo=echo		# echo command
Verbose=0		# Are we generating verbose output?
Onbar_level=""		# Translated level given to ON-Bar
DBSPACES=""		# Which dbspaces are going to be backed up
Pid=0			# Which process to kill when we are cancelled

#
# usage(): display correct usage for nsrdbmi
#
usage()
{
	${echo} \
"This command should only be executed by savegroup."
	${echo} \
"usage: $0 [<options>]
    Options:
	[ -BEiLnqvx ] [ -s server ] [ -N name ] [ -e expiration ]
	[  -f dirfile ] [ -b pool ] [ -F file ] [ -g group ]
	[ -l level ] [ -t date ] [ -m masquerade ] [ -W width ] [ path ... ]

For an explanation of all options, see the save(8) man page.
"
	exit 1
}


#
# Run the pre-processing command.  This can be used to shut down
# a database.
#
run_precmd()
{
	if [ "${PRECMD}" = "" ]; then
		return 0
	fi

	vecho
	vecho "Executing pre-processing command '${PRECMD}' at `date`"
	vecho

	${PRECMD}
	return_status=$?

	vecho
	vecho "Pre-processing command '${PRECMD}' finished at `date`"
	vecho

	return $return_status
}

#
# Run the post-processing command.  This can be used to start a database.
#
#
run_postcmd()
{
	if [ "${POSTCMD}" = "" ]; then
		return 0
	fi

	vecho
	vecho "Executing post-processing command '${POSTCMD}' at `date`"
	vecho

	${POSTCMD}
	return_status=$?

	vecho
	vecho "Post-processing command '${POSTCMD}' finished at `date`"
	vecho

	return $return_status
}

#
# Process arguments supplied by savegrp.  Must handle any arguments save(8)
# accepts.
#
# Sample list of arguments
# save -s lexus -g Default -n -LL -m lexus -l full -W78 -N /usr /usr
#
processargs()
{
while [ $# -gt 0 ]; do
	case "$1" in
	-s )	# Specify server
		NSR_SERVER="$2"
		shift
		shift
		;;
	-B )	# Force connecting directory information
		Bflag=y
		shift
		;;
	-E )	# Estimate save set size
		Eflag=y
		shift
		;;
	-i )	# Ignore any directives
		iflag=y
		shift
		;;
	-LL )	# Force local backup and cause extra line to be printed
		LLflag=y
		shift
		;;
	-n)	# No save
		nflag=y
		shift
		;;
	-q )	# Quiet
		qflag=y
		shift
		;;
	-v )	# Verbose
		Verbose=1
		shift
		;;
	-N )	# Specify a new save set name
		NSR_SAVESET_NAME="$2"
		shift
		shift
		;;
	-e )	# Specify alternate expiration time
		Expiration=$2
		shift
		shift
		;;
	-f )	# Specify directives
		Directives=$2
		shift
		shift
		;;
	-b )	# Specify pool
		Pool="$2"
		shift
		shift
		;;
	-c )	# Specify the client name
		NSR_CLIENT="$2"
		shift
		shift
		;;
	-F )	# Specify file for modification time comparison (not used)
		Directives=$2
		shift
		shift
		;;
	-g )	# Specify group
		NSR_GROUP="$2"
		shift
		shift
		;;
	-l )	# Specify level
		NSR_BACKUP_LEVEL=$2
		shift
		shift
		;;
	-t )	# Specify time for comparison
		Comparison_time=$2
		shift
		shift
		;;
	-m )	# Masquerade as another program
		Masquerade=$2
		shift
		shift
		;;
	-W )	# Specify width of output
		Output_width=$2
		shift
		shift
		;;
	*)	# Name of the Online Dynamic Server (configured in save sets)
		Dbspace=$1
		shift
		;;
	esac
done
}

#
# Make sure all environment variables are exported.
#
export_environment_variables()
{
	export NSR_BACKUP_LEVEL
	export NSR_CLIENT
	export NSR_COMPRESSION
	export NSR_DATA_VOLUME_POOL
	export NSR_LOG_VOLUME_POOL
	export NSR_SAVESET_NAME
	export NSR_SERVER
	export NSR_GROUP

	export INFORMIXDIR
	export INFORMIXSERVER
	export INFORMIXSQLHOSTS
	export ONCONFIG
	export PATH
}

#
# backup_dbspaces: run onbar to backup specified bspaces
# Which dbspaces are backed up is controlled by the shell variable DBSPACES
# (see above).
#
backup_dbspaces()
{

	#
	# Do any translation from NetWorker arguments to ON-Bar.
	# ON-Bar accepts levels 0-2.  A "full" level backup is the same as a
	# level 0.
	#
	if [ "$NSR_BACKUP_LEVEL" = "full" ]; then
		Onbar_level="0"
	else
		Onbar_level=$NSR_BACKUP_LEVEL
	fi

	#
	# Only allow level 0 (full), 1, or 2 backups.  All other levels
	# are meaningless to ON-Bar.
	#
	if [ $Onbar_level -gt 2 ] || [ $Onbar_level = "incr" ]; then
		echo "Only level 0 (full), 1, or 2 backups allowed."
		exit 1
	fi

	onbar -b -L $Onbar_level $DBSPACES &
 	Pid=$!
 	wait $Pid

	onbar_status=$?
	if [ $onbar_status != 0 ]; then
		echo "onbar returned status of "$onbar_status
		echo $0 "exiting."
		exit 1
	fi
}

#
# backup_logfiles: run onbar to backup logical log files
#
backup_logfiles()
{
	onbar -l -c &
	Pid=$!
	wait $Pid

	onbar_status=$?

	#
	# ON-Bar will exit with 0 if nothing bad happened, and with
	# 152 when another onbar -l command is already running.
	#
	# This can occur when the logs fill up during a backup and the
	# log_full.sh script is executed.  ON-Bar will not perform
	# 2 logical log backups at a time to prevent data corruption.
	#
	if [ $onbar_status != 0 -a $onbar_status != 152 ]; then
		echo "onbar returned status of "$onbar_status
		echo $0 "exiting."
		exit 1
	fi
}

#
# Back up emergency boot file and server configuration file.
# Send the data to the NSR_DATA_VOLUME_POOL.  If you wish
# to send the data to another pool, change the save command
# below.
#
backup_boot_files()
{
	# Determine which media pool we are going to use.  If you want the
	# server to choose the pool, set this variable to "".
	boot_file_pool="${NSR_DATA_VOLUME_POOL}"

	# Determine if there is a pool for this save
	if [ "${boot_file_pool}" != "" ]; then
		save_pool="-b${boot_file_pool}"
	fi

	# Determine if there is a group for this save
	if [ "${NSR_GROUP}" != "" ]; then
		save_group="-g${NSR_GROUP}"
	fi

	# Determine if there is a client for this save
	if [ "${NSR_CLIENT}" != "" ]; then
		save_client="-c${NSR_CLIENT}"
	fi


	#
	# Determine the server id so the appropriate emergency boot file is
	# backed up.
	#
	server_id=`onstat -c | egrep SERVERNUM | awk '{print $2}'`

	if [ "${server_id}" = "" ]; then
		echo "Could not determine server id to back up emergency boot file."
		return;
	fi

	# Execute the backup command
	save -q -s ${NSR_SERVER} \
		${save_client+"${save_client}"} \
		${save_group+"${save_group}"} \
		${save_pool+"${save_pool}"} \
		${INFORMIXDIR}/etc/ixbar.${server_id} \
		${INFORMIXDIR}/etc/${ONCONFIG} \
		${INFORMIXSQLHOSTS} \
		${INFORMIXDIR}/etc/oncfg_${INFORMIXSERVER}.${server_id} &

	Pid=$!
	wait $Pid

}

#
# Echo the arguments only if in verbose mode.
#
vecho()
{
	if [ $Verbose -gt 0 ]; then
		echo $*
	fi
}

#
# Display output exactly like save does to keep savegroup happy.  Only
# displays size information for dbspace backups.  Logical log backups
# are not included.
#
display_summary()
{
	Hostname=`uname -n`
	first_part=`echo "$Hostname: $NSR_SAVESET_NAME		level=$NSR_BACKUP_LEVEL,	"`
	second_part=`mminfo -s $NSR_SERVER -q"savetime>=$Start_time,savetime<=$End_time" -r "name,totalsize(1),nfiles(1)" | egrep $NSR_SAVESET_NAME | \
awk '\
BEGIN { total_kb = 0; total_mb = 0; total_files = 0; files_str = "file" } \
{ \
        if ( $3 == "KB" ) { \
		total_kb += $2 \
	} else { \
		total_mb += $2 \
	} \
 	total_files += $4 \
} \
END { \
	if (total_files > 1) {  \
		files_str = "files"  \
	} else {  \
		files_str = "file" \
	} \
        if (total_kb > 1000) { \
		total_mb += (total_kb / 1000) \
	} \
        if (total_mb > 0) {  \
printf "%d.%d MB 00:00:00  %d %s\n", total_mb, total_kb % 1000, total_files, files_str \
	} else {  \
printf "%d KB 00:00:00  %d %s\n", total_kb, total_files, files_str \
	} \
}'`

	echo "$first_part$second_part"

	return 0
}

#
# Handle cancel signals sent by savegrp when user stops the group.
#
handle_signal()
{
	if [ $Pid != 0 ]; then
		kill -2 $Pid
	fi
	exit 1
}

#
# The main portion of this shell.
#
# Process arguments, export environment
# Execute a pre-command (if any)
# Execute dbspace backups
# Execute logical log backups
# Execute a post-command
# Display save output

processargs "$@"

#
# Make sure we respond to savegrp cancellations.
#
trap handle_signal 2 15

#
# Translate save set name to ODS name and dbspace name.  The save set
# name is of the form INFORMIX:/ODS_server_name/dbspace_name.
#
INFORMIXSERVER=`echo $Dbspace | awk -F'/' '{print $2}'`
DBSPACES=`echo $Dbspace | awk -F'/' '{print $3}'`

#
# Export all environment variables.
#
export_environment_variables

#
# Handle pre-processing
#
run_precmd
precmd_status=$?
if [ $precmd_status != 0 ]; then
	echo "Pre-processing command failed.  Ending session."
	exit 1
else
	vecho "Pre-processing command succeeded."
fi

#
# Handle dbspace and logfile backups
#
Start_time=`date`
backup_dbspaces
End_time=`date`

if [ ${DO_LOGFILE_BACKUPS} = YES ]; then
	backup_logfiles
fi

#
# Save the emergency boot file and $ONCONFIG files (to aid in disasters).
#
backup_boot_files

#
# handle post-processing
#
run_postcmd
postcmd_status=$?
if [ $postcmd_status != 0 ]; then
	echo "Post-processing command failed.  Ending session."
	exit 1
else
	vecho "Post-processing command succeeded."
fi

#
# Display summary for savegroup
#
display_summary

exit 0
