#!/bin/bash
#
# USAGE: migrate_control [OPTIONS]
#
# OPTIONS:
#   -h|--help            Show this help text
#   -y)                  Answer yes to all questions asked by the script
#
# This script updates the CONTROL database to its latest specification
# as defined by the currently installed TRIPsystem version.
#
# You will need at to have the CONTROL database files (BAF, BIF and VIF) from
# the TRIP version you intend to migrate from copied to the TDBS_CTL directory
# for the current TRIP installation. In this directory you must also have the
# P_CONTROL database files (BAF, BIF and VIF) that were provided with the
# current TRIP installation.
#

AUTO_CONFIRM=0
OSNAME=`uname`

usage()
{
   head -17 $0 | tail -15 | cut -c3-
} 


if [ "$1" != "" ]; then
   case $1 in
      -h|--help)
        usage
        exit 0
        ;;
      -y)
        AUTO_CONFIRM=1
        ;;
     *)
        ;;
   esac
fi


if [ -e /usr/local/trip/sys/lib ]; then
   TDBS_HOME=$(dirname `readlink /usr/local/trip/sys/lib 2>/dev/null` 2> /dev/null)
   TDBS_EXE=$TDBS_HOME/bin
fi

if [ "$TDBS_HOME" = "" ] || [ ! -d "$TDBS_HOME" ]; then
   echo "ERROR: TRIPsystem is not properly installed."
   echo ""
   exit 1
fi


TDBS_CTL=`$TDBS_EXE/queryrcs -q TDBS_CTL`
if [ "$TDBS_CTL" = "<nil>" ]; then
   unset TDBS_CTL
fi

if [ "$TDBS_CTL" = "" ] || [ ! -d "$TDBS_CTL" ]; then
   echo "ERROR: TDBS_CTL is not set to a valid directory in tdbs.conf"
   echo ""
   exit 1
fi

if [ ! -w $TDBS_CTL ]; then
   echo "ERROR: No write access to the TDBS_CTL directory."
   echo ""
   exit 1
fi

TDBS_LOG=`$TDBS_EXE/queryrcs -q TDBS_LOG`
if [ "$TDBS_LOG" = "<nil>" ]; then
   unset TDBS_LOG
fi
if [ "$TDBS_LOG" = "" ]; then
   TDBS_LOG=/tmp
fi


echo "The CONTROL files should be in $TDBS_CTL"
printf "Verifying... "
CHECKVAL=0
CHECKMSG=""

if [ ! -f $TDBS_CTL/CONTROL.BAF ]; then
  CHECKVAL=1
  CHECKMSG="   CONTROL.BAF is missing"
fi
if [ ! -f $TDBS_CTL/CONTROL.BIF ]; then
   CHECKVAL=`expr $CHECKVAL + 1`
   if [ "$CHECKMSG" != "" ]; then
      CHECKMSG="$CHECKMSG\n   CONTROL.BIF is missing"  
   else
      CHECKMSG="   CONTROL.BIF is missing" 
   fi
fi
if [ ! -f $TDBS_CTL/CONTROL.BAF ]; then
   CHECKVAL=`expr $CHECKVAL + 1`
   if [ "$CHECKMSG" != "" ]; then
      CHECKMSG="$CHECKMSG\n   CONTROL.VIF is missing"  
   else
      CHECKMSG="   CONTROL.VIF is missing" 
   fi
fi

if [ $CHECKVAL -gt 0 ]; then
   echo "failed"
   printf "$CHECKMSG"
   echo ""
   echo "Unable to migrate the CONTROL database."
   echo "Please check your environment and try again."
   echo ""
   exit 1
else
   echo "ok"
   echo ""
fi


echo "The P_CONTROL files should be in $TDBS_CTL"
printf "Verifying... "
CHECKVAL=0
CHECKMSG=""

if [ ! -f $TDBS_CTL/P_CONTROL.BAF ]; then
  CHECKVAL=1
  CHECKMSG="   P_CONTROL.BAF is missing"
fi
if [ ! -f $TDBS_CTL/P_CONTROL.BIF ]; then
   CHECKVAL=`expr $CHECKVAL + 1`
   if [ "$CHECKMSG" != "" ]; then
      CHECKMSG="$CHECKMSG\n   P_CONTROL.BIF is missing"
   else
      CHECKMSG="   P_CONTROL.BIF is missing"
   fi
fi
if [ ! -f $TDBS_CTL/P_CONTROL.BAF ]; then
   CHECKVAL=`expr $CHECKVAL + 1`
   if [ "$CHECKMSG" != "" ]; then
      CHECKMSG="$CHECKMSG\n   P_CONTROL.VIF is missing"
   else
      CHECKMSG="   P_CONTROL.VIF is missing"
   fi
fi

if [ $CHECKVAL -gt 0 ]; then
   echo "failed"
   echo "$CHECKMSG"
   echo ""
   echo "Preconditions for CONTROL database migration not met."
   echo "Please check your environment and try again."
   echo ""
   exit 1
else
   echo "ok"
   echo ""
fi

if [ $AUTO_CONFIRM -eq 0 ]; then
   echo "This script updates the CONTROL database to its latest specification"
   echo "as defined by the currently installed TRIPsystem version. This is"
   echo "normally done as part of an upgrade installation, but can also be run"
   echo "separately, e.g. when migrating from another TRIP server."
   echo ""
   echo "You will need at to have the CONTROL database files (BAF, BIF and VIF) from"
   echo "the TRIP version you intend to migrate from copied to the TDBS_CTL directory"
   echo "for the current TRIP installation. In this directory you must also have the"
   echo "P_CONTROL database files (BAF, BIF and VIF) that were provided with the"
   echo "current TRIP installation."
   echo ""
   $TDBS_EXE/modcon --check --quiet
   if [ $? -ne 0 ]; then
      echo "WARNING: You are about to attempt an unsupported migration path."
      echo "This is will either fail during migration or result in TRIPsystem"
      echo "instability."
   else
      echo "Please note that downgrading the CONTROL is NOT supported."
   fi
   echo ""
   echo "Do you wish to migrate your CONTROL database?"
   while [ "$CONFIRM" = "" ]
   do
      echo -n "[Y|n] "
      read CONFIRM
      if [ "$CONFIRM" = "" ]; then
         CONFIRM=Y
      fi

      case $CONFIRM in
         Y|y|Yes|yes|YES)
            echo "Proceeding..."
            echo ""
            ;;
         N|n|No|no|NO)
            echo ""
            echo "Migration cancelled"
            echo ""
            exit 2
            ;;
         *)
            CONFIRM=""
            ;;
      esac
   done

fi

##
# Remove oldest CONTROL backup if there are at least ten present
#
prune_backups()
{
   CTL_FILE=$1
   CTL_BKPFILES=`find $TDBS_CTL -maxdepth 1 -name "$CTL_FILE-*" -printf "%T@ %p\n" | sort -n | awk '{print $2}'`
   CTL_BKPCOUNT=`echo $CTL_BKPFILES | wc -w`
   if [ $CTL_BKPCOUNT -ge 10 ]; then
      CTL_OLDBKP=`echo $CTL_BKPFILES|tr ' ' '\n'| head -n1`
      rm -fv $CTL_OLDBKP
   fi
}

## 
# Verbose cp wrapper to deal with operating systems for which the cp
# command doesn't have the -v option.
#
cp_verbose()
{
if [ "$OSNAME" != "SunOS" ]; then
   cp -pv $*
   RETVAL=$?
else
   echo "cp -p $*"
   cp -p $*
   RETVAL=$?
fi
   return $RETVAL
}

##
# Back up the CONTROL database files before we begin
#
TSTAMP=`date '+%Y%m%d%H%M%S'`
echo "Backing up the CONTROL database files with suffix $TSTAMP"
cp_verbose $TDBS_CTL/CONTROL.BAF $TDBS_CTL/CONTROL.BAF-$TSTAMP
if [ $? -ne 0 ]; then
   echo "ERROR: Unable to backup the CONTROL.BAF file"
   echo "Migration aborted"
   echo ""
   exit 3
fi
cp_verbose $TDBS_CTL/CONTROL.BIF $TDBS_CTL/CONTROL.BIF-$TSTAMP
if [ $? -ne 0 ]; then
   echo "ERROR: Unable to backup the CONTROL.BIF file"
   echo "Migration aborted"
   echo ""
   exit 3
fi
cp_verbose $TDBS_CTL/CONTROL.VIF $TDBS_CTL/CONTROL.VIF-$TSTAMP
if [ $? -ne 0 ]; then
   echo "ERROR: Unable to backup the CONTROL.VIF file"
   echo "Migration aborted"
   echo ""
   exit 3
fi

##
# If and when the migration tasks fail, TRIP backline support will
# typically want to investigate the cause. For this, the possibly
# corrupted CONTROL files must be saved to a separate location prior
# to restoring the backup.
#
copy_broken_control()
{
   SAVE_DIR=""
   if [ "$TDBS_MIGRATION_ERRORS_DIR" != "" ] && [ -d "$TDBS_MIGRATION_ERRORS_DIR" ]; then
      if [ ! -w $TDBS_MIGRATION_ERRORS_DIR ]; then
         echo "WARNING: TDBS_MIGRATION_ERRORS_DIR is not writable. Using defaults."
      else
         SAVE_DIR=$TDBS_MIGRATION_ERRORS_DIR/$TSTAMP
         mkdir -p "$SAVE_DIR"
         if [ $? -ne 0 ]; then
            SAVE_DIR=""
         fi
      fi
   fi
   if [ "$SAVE_DIR" = "" ]; then
      if [ -w "$TDBS_CTL" ]; then
         SAVE_DIR=$TDBS_CTL/migration_errors/$TSTAMP
         mkdir -p "$SAVE_DIR"
         if [ $? -ne 0 ]; then
            SAVE_DIR=""
         fi
      fi
   fi
   if [ "$SAVE_DIR" = "" ]; then
      if [ -w "$TDBS_LOG" ]; then
         SAVE_DIR=$TDBS_LOG/migration_errors/$TSTAMP
         mkdir -p "$SAVE_DIR"
         if [ $? -ne 0 ]; then
            SAVE_DIR=""
         fi
      fi
   fi
   if [ "$SAVE_DIR" = "" ]; then
      SAVE_DIR=/tmp/tripsystem_migration_errors/$TSTAMP
      mkdir -p "$SAVE_DIR"
      if [ $? -ne 0 ]; then
         SAVE_DIR=""
      fi
   fi
   if [ "$SAVE_DIR" = "" ]; then
      echo "ERROR: Unable to create directory $SAVE_DIR"
      echo "       Unable to copy files for post-mortem error analysis"
      return 3
   fi

   echo ""
   echo "Copying CONTROL database files for post-mortem analysis"

   FILES_COPIED=0

   # Copy the broken files
   cp_verbose $TDBS_CTL/CONTROL.BAF $SAVE_DIR/CONTROL.BAF-AFTER
   if [ $? -eq 0 ]; then
      FILES_COPIED=`expr $FILES_COPIED + 1`
   fi
   cp_verbose $TDBS_CTL/CONTROL.BIF $SAVE_DIR/CONTROL.BIF-AFTER
   if [ $? -eq 0 ]; then
      FILES_COPIED=`expr $FILES_COPIED + 1`
   fi
   cp_verbose $TDBS_CTL/CONTROL.VIF $SAVE_DIR/CONTROL.VIF-AFTER
   if [ $? -eq 0 ]; then
      FILES_COPIED=`expr $FILES_COPIED + 1`
   fi

   # Copy the backed up files from before the migration attemopt
   cp_verbose $TDBS_CTL/CONTROL.BAF-$TSTAMP $SAVE_DIR/CONTROL.BAF-BEFORE
   if [ $? -eq 0 ]; then
      FILES_COPIED=`expr $FILES_COPIED + 1`
   fi
   cp_verbose $TDBS_CTL/CONTROL.BIF-$TSTAMP $SAVE_DIR/CONTROL.BIF-BEFORE
   if [ $? -eq 0 ]; then
      FILES_COPIED=`expr $FILES_COPIED + 1`
   fi
   cp_verbose $TDBS_CTL/CONTROL.VIF-$TSTAMP $SAVE_DIR/CONTROL.VIF-BEFORE
   if [ $? -eq 0 ]; then
      FILES_COPIED=`expr $FILES_COPIED + 1`
   fi

   # NB: If the error was caused by low disk space, the above copy
   # operation may fail. If so, there is nothing we can do about it
   # except log a warning.

   if [ $FILES_COPIED -lt 6 ]; then
      echo "WARNING: Not all files could be copied for post-mortem analysis"
   else
      echo "Post-mortem analysis data copied to $SAVE_DIR"
   fi
   echo ""
}

##
# If any of the migration tasks fail, the backup must be
# restored so that we don't put the system in an unstable
# or broken state.
#
restore_backup()
{
   # Before removing the backup, save data for a post-mortem
   copy_broken_control

   echo "Restoring backup of the CONTROL database"
   cp_verbose $TDBS_CTL/CONTROL.BAF-$TSTAMP $TDBS_CTL/CONTROL.BAF
   if [ $? -ne 0 ]; then
      echo "ERROR: Unable to restore the backup of the CONTROL.BAF file"
      exit 3
   fi
   cp_verbose $TDBS_CTL/CONTROL.BIF-$TSTAMP $TDBS_CTL/CONTROL.BIF
   if [ $? -ne 0 ]; then
      echo "ERROR: Unable to restore the backup of the CONTROL.BIF file"
      exit 3
   fi
   cp_verbose $TDBS_CTL/CONTROL.VIF-$TSTAMP $TDBS_CTL/CONTROL.VIF
   if [ $? -ne 0 ]; then
      echo "ERROR: Unable to restore the backup of the CONTROL.VIF file"
      exit 3
   fi

   # Remove the backup files as they are no longer needed.
   rm -f $TDBS_CTL/CONTROL.BAF-$TSTAMP
   rm -f $TDBS_CTL/CONTROL.BIF-$TSTAMP
   rm -f $TDBS_CTL/CONTROL.VIF-$TSTAMP
}

# Run PACKIT on the CONTROL.BAF file

if [ -f $TDBS_LOG/__CONTROL_PACKIT__.BAF ]; then
   rm -f $TDBS_LOG/__CONTROL_PACKIT__.BAF
fi
echo ""
echo "Running PACKIT on CONTROL"
$TDBS_EXE/packit -d CONTROL --force -f $TDBS_LOG/__CONTROL_PACKIT__.BAF
RETCODE=$?
if [ $RETCODE -ne 0 ]; then
   echo ""
   echo "ERROR: Packit on the CONTROL database failed with code $RETCODE."
   restore_backup
   echo ""
   exit 3
fi
cp -f $TDBS_LOG/__CONTROL_PACKIT__.BAF $TDBS_CTL/CONTROL.BAF
RETCODE=$?
if [ $RETCODE -ne 0 ]; then
   echo ""
   echo "ERROR: Copy of repackaged CONTROL.BAF failed with code $RETCODE."
   echo "ERROR: Failed to replace CONTROL.BAF with the one produced by Packit."
   restore_backup
   echo ""
   exit 3
fi
rm $TDBS_LOG/__CONTROL_PACKIT__.BAF

# Reindex the CONTROL so that all objects are guaranteed to be searchable

echo "Re-indexing CONTROL"
$TDBS_EXE/index -d CONTROL --reindex
RETCODE=$?
if [ $RETCODE -ne 0 ]; then
   echo ""
   echo "ERROR: CONTROL database re-indexing failed with code $RETCODE."
   restore_backup
   echo ""
   echo "Unable to complete migration of the CONTROL database."
   echo ""
   exit 3
fi

echo ""
echo "The CONTROL database was successfully re-indexed."
echo "Proceeding with the migration proper of the CONTROL database."
echo ""

# Now run modcon to perform the migration proper.

echo "Running MODCON"
TDBS_CHARS=LA1 $TDBS_EXE/modcon 
RETCODE=$?
if [ $RETCODE -ne 1 ]; then
   echo "ERROR: The CONTROL database migration failed with code $RETCODE."
   restore_backup
   echo ""
   exit 3
fi

# Migration succeded. Prune backups if there now are more than 10 present.
# NB: Pruning of old backups not yet supported on Solaris
if [ "$OSNAME" != "SunOS" ]; then
   echo "Pruning old CONTROL database backups if there are more than 10"
   prune_backups CONTROL.BAF
   prune_backups CONTROL.BIF
   prune_backups CONTROL.VIF
   echo ""
fi

echo ""
echo "The CONTROL database migration completed successfully."
echo ""

exit 0

