#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos720 src/bos/usr/samples/odm/odmclean.sh 1.5 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 2001,2007 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)75 1.5 src/bos/usr/samples/odm/odmclean.sh, cmdodm, bos720 4/19/07 14:05:00 # # This utility should be used to cleanup odm databases. # Normally, when we delete a object from a odm database, we may or may # not use this deleted object space. If a database is heavily # updated, me may have considerable amount of unused space, causing # the file sizes to be too big. # Algorithm: # Usage: odmclean -d # # 1. Make sure we have enough space in /tmp and in database directory. # 2. Make a backup copy of the database being cleaned up. # 3. Read all the objects from the mentioned database in to a "temp" file. # 4. Remove all the objects from the database, this should cause the database # size to be about 4096 bytes. # 5. Add all objects saved in "temp" file. # 6. Read all the objects from the new database in to another "temp" file. # 7. Make sure data is identical by doing a diff on two temp files. # 8. Make sure object count is the same. # #Global Variables dirname="/tmp" #temporary working directory vc_sz=0 #.vc file size db_sz=0 #databe file size db_name="" #database name db_fname="" #database full path name vc_fname="" #.vc full path mame odm_path="" #ODMDIR total_sz=0 #Min. space required in /tmp tmp_fname="" #Temporary data file name format is (/tmp/odmclean.$db_name) obj_cnt_old=0 #no. of objects before cleanup obj_cnt_new=0 #no. of object after cleanup time_stamp=0 r_err=0 #error during restoration vc_exists=0 #database has .vc file update_flag=0 #update in progress flag my_args=0 # for getopt # Get all the objects on database and save it in $tmp_fname file using # odmget command. # odm_read() { echo "\tReading odm data .. \n" >&2 tmp_fname="/tmp/odmclean.$db_name" `/usr/bin/odmget $db_name > $tmp_fname` if [ $? != 0 ] then echo " Could not read objects from $db_name database\n" >&2 exit 22; fi echo "\tDone reading.\n" >&2 } # Remove all the objects from database using odmdelete command # odm_remove() { echo "\tDeleting objects ..\n" >&2 update_flag=1 #update in progress /usr/bin/odmdelete -o $db_name > /dev/null if [ $? != 0 ] then echo " Could not remove objects from $db_name database.\n" >&2 Restore Cleanup exit 23; fi echo "\tAll objects deleted successfully.\n" >&2 } # Add all the objects saved in "temp" file using odmadd command odm_add() { echo "\tAdding objects to database ...\n" >&2 /usr/bin/odmadd /tmp/odmclean.$db_name if [ $? != 0 ] then echo " Could not add objects to $db_name database.\n" >&2 Restore Cleanup exit 24; fi update_flag=0 #update done echo "\tDone adding objects to the database.\n" >&2 } # Restore the original database Restore() { #Restore the database file echo "Restoring the database ...\n" >&2 /usr/bin/cp $db_fname.$time_stamp $db_fname rc=$? if [ $rc != 0 ] then echo "Error occured while trying to restore $db_fname.\n" >&2 echo "Fix the reported problem and copy $db_fname.$time_stamp to $db_fname.\n" >&2 fi vrc=0 if [ "$vc_fname" != "" ] then /usr/bin/cp $vc_fname.$time_stamp $vc_fname vrc=$? if [ $vrc != 0 ] then echo " Error occured while trying to restore $vc_fname.\n" >&2 echo "Fix the reported problem and copy $vc_fname.$time_stamp to $vc_fname.\n" >&2 fi fi if [ $rc != 0 ] || [ $vrc != 0 ] then r_err=1 #set restore error flag. Cleanup [ $vrc != 0 ] && exit 25 exit 26 fi echo "Database restored successfully.\n" >&2 } #Make sure new database has same contents as old one odm_verify() { echo "\tVerification in progress ..\n" >&2 #Get the object count obj_cnt_new=`/usr/bin/odmshow $db_name | /usr/bin/grep "population:" | /usr/bin/awk '{print $4}'| /usr/bin/cut -c2-` if [ $obj_cnt_new != $obj_cnt_old ] then echo "\t No. old objects=$obj_cnt_old\n" >&2 echo "\t No. new objects=$obj_cnt_new\n" >&2 echo "\t Error occured during cleanup\n" >&2 Restore exit 27; fi #Make sure contents are the same /usr/bin/odmget $db_name | /usr/bin/diff - $tmp_fname if [ $? != 0 ] then echo "\t Contents of old database differs from cleaned database.\n" >&2 echo "\t Error occured during cleanup.\n" >&2 Restore exit 28; fi echo "\tVerification done.\n" >&2 } signal_handler() { echo "Aborting odmclean ....\n" >&2 if [ $update_flag -eq 1 ] then Restore fi Cleanup exit 29; } #remove all temp files Cleanup() { #remove temp data file /usr/bin/rm -f $tmp_fname #remove backup database file if [ $r_err -eq 0 ] then /usr/bin/rm $db_fname.$time_stamp fi if [ "$vc_fname" != "" ] && [ $r_err -eq 0 ] then /usr/bin/rm $vc_fname.$time_stamp fi } #checks for available space in /tmp and database directory check_space() { freespace=`/usr/bin/df -k $dirname` freespace=`echo $freespace | /usr/bin/awk '{print $11}'` exitsw=0 if [ $freespace -lt $total_tmp_sz ] then echo "\t\tAvailable space is $freespace kbytes.\n" >&2 echo "ERROR: Not enough space. Increase the $dirname file system size.\n" >&2 exitsw=1 fi echo "\t\tAvailable space in $dirname is $freespace kbytes\n" >&2 #check for space in database directory freespace=`/usr/bin/df -k $db_fname` freespace=`echo $freespace | /usr/bin/awk '{print $11}'` if [ $freespace -lt $total_sz ] then echo "\t\tAvailable space is $freespace kbytes.\n" >&2 echo "ERROR: Not enough space. Increase the $db_fnamefile system size.\n" >&2 exitsw=1 fi [ $exitsw = 1 ] && exit 5 echo "\t\tAvailable space in $db_fname is $freespace kbytes\n" >&2 } # # pass1(): # 1. Check for space needed for "temp" file in /tmp # This should be at least twice the total filesizes. # 2. Check for enough space in database directory. # This should be atleast total filesizes. # This is needed for backup copy of database. # pass1() { echo "Pass1() in progress .... \n" >&2 #Make sure database is accessible /usr/bin/odmshow $db_name > /dev/null if [ $? != 0 ] then echo "Cannot access database $db_name.\n" >&2 echo "Check ODMDIR environment variable set to a valid path\n" >&2 exit 1 fi #initialize database name db_fname="$odm_path/$db_name" #check if class has "vchar" or "nchar" types. That would # indicate that database has a .vc file /usr/bin/odmshow $db_name | /usr/bin/awk '{print $1}' |/usr/bin/grep vchar > /dev/null if [ $? != 0 ] then /usr/bin/odmshow $db_name | /usr/bin/awk '{print $1}' | /usr/bin/grep nchar > /dev/null fi if [ $? -eq 0 ] then vc_fname=$db_fname.vc fi #get database file size if [ -f $db_fname ] then db_sz=`/usr/bin/ls -lL $db_fname | /usr/bin/awk '{print $5}'` else echo "Error: Specified database does not exist.\n" >&2 Usage exit 2; fi if [ $? != 0 ] then echo "Error while listing file $db_fname. \n" >&2 Usage exit 3; fi #get .vc file size if [ "$vc_fname" != "" ] then vc_sz=`/usr/bin/ls -lL $vc_fname | /usr/bin/awk '{print $5}'` fi if [ $? != 0 ] then echo "Error while listing file $db_fname. \n" >&2 Usage exit 4; fi #total required space in /tmp for temp data let total_sz=$db_sz+$vc_sz let total_tmp_sz=$total_sz+$total_sz # We need twice the amount let total_sz=$total_sz/1024 #size in KB let total_tmp_sz=$total_tmp_sz/1024 #size in KB check_space #check space in /tmp and in databse directory obj_cnt_old=`/usr/bin/odmshow $db_name | /usr/bin/grep "population:" | /usr/bin/awk '{print $4}' | /usr/bin/cut -c2-` echo "Pass1 completed successfully.\n" >&2 } #Do the odmclean pass2() { echo "Pass2 in progress ...\n" >&2 # Make sure no other odmclean operation in progress. # This is done by checking for /tmp/odmclean.$db_name file. if [ -f /tmp/odmclean.$db_name ] then echo "odm clean opeartion is already in progress for this database.\n" >&2 exit 6; fi echo "\tMaking temporary backup copies of the databases ..\n" >&2 #Make a backup copy of database being cleaned /usr/bin/cp $db_fname $db_fname.$time_stamp if [ $? != 0 ] then echo " Error creating a backup copy of the database.\n" >&2 exit $? fi #Make a backup copy of .vc file if [ "$vc_fname" != "" ] then /usr/bin/cp $vc_fname $vc_fname.$time_stamp fi if [ $? != 0 ] then echo " Error creating a backup copy of the databse.\n" >&2 Cleanup exit $? fi echo "\tBacking up done. \n" >&2 #Gather current odm data in to /tmp odm_read #remove all the objects odm_remove #add objects odm_add #verify the databse odm_verify echo "Pass2 completed successfully.\n" >&2 } Usage() { echo "Usage:" >&2 echo "\n\todmclean -d " >&2 } #parse Arguments parseArgs () { # We cannot use the set command with a back quoted getopt directly # as the exit code from the getopt will be overwritten by the exit # code from the set command which is always 0. my_args=`getopt d: $*` if [ $? != 0 ] then Usage exit 1 fi set -- $my_args if [ $1 = -- ] then Usage exit 1 fi while [ $1 != -- ] do case $1 in -d) db_name=$2 shift;; *) echo "Error: Invalid argument" >&2 ; Usage; exit 1; esac shift # next flag done } trap "signal_handler" 1 2 3 15 9 #main #set LANG nvironment export LC_MESSAGES=C #get pid pid=$$ #get time stamp required for backup copy database time_stamp=`/usr/bin/date +\%d\%m\%H\%M\%S` rc=$? if [ $rc != 0 ] then echo "Error while executing date command \n" >&2 exit $rc fi #get ODMDIR odm_path=$ODMDIR #parse arguments and initialization parseArgs $@ #calculate space required pass1 #do odmclean pass2 #do cleanup Cleanup echo "odmclean completed successfully.\n" >&2 exit 0