#!/bin/bash -
#===============================================================================
#
#          FILE:  DBbackup.sh
#
#         USAGE:  ./DBbackup.sh <DB Name> [Username] [Backup path]
#
#   DESCRIPTION:  Postgres DB backup script
#
#  REQUIREMENTS: pg_dump
#         NOTES: origin by Chomay Chou <chomay@x-legend.com.tw>
#      IMPROVED: 1.Speed up progress of DB backup
#                2.Use gzip compress(from pipe)
#                3.Change resolution of backup date from day to minute
#
#        AUTHOR: rickz (Rick Zhang), xlrickz@gmail.com
#       COMPANY: X-LEGEND Entertainment Corp.
#       CREATED: Tue Dec  7 11:43:42 CST 2010
#      REVISION: 2.0
#===============================================================================

#set -o nounset                              # Treat unset variables as an error
#set -m                                      # Enable job control

####################################################################
#                                                                  #
#  If you are using Ctrl, ALL THE SETTINGS BELOW WILL BE OVERRIDE  #
#                                                                  #
####################################################################
# Backup path
BACKUP_PATH="$HOME/DBbackup"

# Psql user
PSQLUSER="postgres"

# Delete DB backup files that total size excced $MAX_DB_BACKUP_TOTAL_SIZE(in MB)
# This setting will keep old backup files generated every Friday
MAX_DB_BACKUP_TOTAL_SIZE="20000"

# Delete DB backup files that total size excced $MAX_DB_BACKUP_TOTAL_SIZE_HARD_LIMIT(in MB)
MAX_DB_BACKUP_TOTAL_SIZE_HARD_LIMIT="30000"

# DBbackup backup custom format only?
DBBACKUP_BACKUP_CUSTOM_FORMAT_ONLY="1"

# Do not backup custom format
DBBACKUP_DO_NOT_BACKUP_CUSTOM_FORMAT="0"

# Try to load settings from ~/gamerc
[ -f ~/.gamerc ] && source ~/.gamerc

# PostgreSQL version
PG_VERSION="$(pg_dump --version|awk '{print $3}')"

# When the backup start?
BACKUP_DATE="$(date +%Y%m%dT%H%M)"

[ "$1" == "" ] && exec echo "Usage: $0 <DB Name> [Username] [Backup path]"
[ "$2" == "" ] || PSQLUSER="$2"
[ "$3" == "" ] || BACKUP_PATH="$3"
DBNAME="$1"

# Colorize
function colorize() {
# Colorize stream editor by Rickz <iamrickz@gmail.com>
#                                       21:50, 2007/10/03.
FG="$1" ; BG="$2" ; EF1="$3" ; EF2="$4" ; EF3="$5"
echo "$3 $4 $5"|grep "1" 2>&1 > /dev/null && FG="39"
OLDFG="$FG";case "$FG" in
        black)  FG="30";;
        red)    FG="31";;
        green)  FG="32";;
        yellow) FG="33";;
        blue)   FG="34";;
        magenta)FG="35";;
        purple) FG="35";;
        cyan)   FG="36";;
        white)  FG="37";;
        default)FG="39";;
esac;[ "$OLDFG" == "$FG" ] && FG="39"
OLDBG="$BG";case "$BG" in
        black)  BG="40";;
        red)    BG="41";;
        green)  BG="42";;
        yellow) BG="43";;
        blue)   BG="44";;
        magenta)BG="45";;
        purple) BG="45";;
        cyan)   BG="46";;
        white)  BG="47";;
        default)BG="49";;
esac;[ "$OLDBG" == "$BG" ] && BG="49"
[ "$EF3" != "" ] && exec sed "s/\(.*\)/\x1b\x5b$BG\x3b$FG\x3b\x31\x6d\x1b\x5b$EF1\x6d\x1b\x5b$EF2\x6d\x1b\x5b$EF3\x6d\1\x1b\x5b\x30\x6d/g" -
[ "$EF2" != "" ] && exec sed "s/\(.*\)/\x1b\x5b$BG\x3b$FG\x3b\x31\x6d\x1b\x5b$EF1\x6d\x1b\x5b$EF2\x6d\1\x1b\x5b\x30\x6d/g" -
[ "$EF1" != "" ] && exec sed "s/\(.*\)/\x1b\x5b$BG\x3b$FG\x3b\x31\x6d\x1b\x5b$EF1\x6d\1\x1b\x5b\x30\x6d/g" -
[ "$BG" != "" ] && exec sed "s/\(.*\)/\x1b\x5b$BG\x3b$FG\x3b\x31\x6d\1\x1b\x5b\x30\x6d/g" -
[ "$FG" != "" ] && exec sed "s/\(.*\)/\x1b\x5b0\x3b$FG\x3b\x31\x6d\1\x1b\x5b\x30\x6d/g" -
}

# Dump "plain and compressed" from database
dump_plain_and_compressed () {
   ulogger_echo_no_nl "Start dump '$DBNAME' ... " | colorize yellow
   nice -n 19 pg_dump -U $PSQLUSER $DBNAME | gzip -3 -c > $BACKUP_PATH/$DBNAME-"$BACKUP_DATE".sql.gz \
   && ulogger_echo "Backup '$DBNAME'(Plain and compressed) OK" | colorize green || ulogger_echo "'$DBNAME' dump FAILED" | colorize red
}

# Dump "custom format" from database
dump_custom_format () {
   ulogger_echo_no_nl "Start dump '$DBNAME' ... " | colorize yellow
   nice -n 19 pg_dump -U $PSQLUSER -Fc -f $BACKUP_PATH/$DBNAME-"$BACKUP_DATE".custom-$PG_VERSION.sql $DBNAME \
   && ulogger_echo "Backup '$DBNAME'(Custom format) OK" | colorize green || ulogger_echo "'$DBNAME' dump FAILED" | colorize red
}


# Check DB name
psql $DBNAME $PSQLUSER <<< '' > /dev/null 2>&1 \
&& ulogger_echo "DB '$DBNAME' connection: OK" | colorize green \
|| ulogger_echo "Error: Could not connect to DB '$DBNAME'" | colorize red

# Make the directory
mkdir -p "$BACKUP_PATH" || ulogger_echo "Error: Mkdir failed." | colorize red

# Dump roles
ulogger_echo_no_nl "Start dump roles ... " | colorize yellow
pg_dumpall -r -U $PSQLUSER -f $BACKUP_PATH/global_roles.sql \
&& ulogger_echo "Dump roles OK" | colorize green || ulogger_echo "roles dump FAILED" | colorize red 

# Dump the database
if [ "$DBBACKUP_BACKUP_CUSTOM_FORMAT_ONLY" == "1" ] && [ "$DBBACKUP_DO_NOT_BACKUP_CUSTOM_FORMAT" == "1" ] ; then
   # Fool-proof, force to backup the plain and compressed format
   dump_plain_and_compressed
else
   if ! [ "$DBBACKUP_BACKUP_CUSTOM_FORMAT_ONLY" == "1" ] ; then
	dump_plain_and_compressed
   fi
   if ! [ "$DBBACKUP_DO_NOT_BACKUP_CUSTOM_FORMAT" == "1" ] ; then
	dump_custom_format
   fi
fi

# Delete old backups that total size exceed $MAX_DB_BACKUP_TOTAL_SIZE(In MB)
# and leave old backups that backup at Monday only.
if [ "$DBBACKUP_ROUTINE_DEL" == "1" ]; then
   cd "$BACKUP_PATH"
   if grep -q "^[0-9]\+$" <<< "$MAX_DB_BACKUP_TOTAL_SIZE" ; then
      TOTAL_SIZE=0
      for DB_BACKUP_FILE in `ls -t`;do 
         TOTAL_SIZE=$(($TOTAL_SIZE+$(stat -c %s $DB_BACKUP_FILE)/1048576))
         if [ $TOTAL_SIZE -gt $MAX_DB_BACKUP_TOTAL_SIZE ] ; then
            if [ $TOTAL_SIZE -gt $MAX_DB_BACKUP_TOTAL_SIZE_HARD_LIMIT ] ; then
                rm -fv $DB_BACKUP_FILE
            else
                [ "$(date -d "$(stat -c %z $DB_BACKUP_FILE)" +%w)" == "5" ] \
                || rm -fv $DB_BACKUP_FILE
            fi
         fi
      done
   fi
fi
