#! /bin/bash

#=========================================================================
# Copyright (C) GemStone Systems, Inc. 2008.
#
# Name - installGemstone2.3-Linux.sh
#
# Purpose - Automatically download and install a Linux version of GemStone
#
# $Id: installGemstone-Linux.sh 585 2008-04-28 03:44:02Z monty $
#
# Description:
#    Does a basic install of GemStone 2.3 for a developer on a Linux machine
#    Setup for manual GemStone startup rather than automatic startup upon boot
#    Safe to run multiple times, as it will not overwrite existing data
#    Requires root access (using sudo) to change setings and create directories
#
# Actions:
#    Verify machine is capable of running GemStone 64-bit
#    Add shared memory setup to /etc/sysctl.conf
#    Add GemStone netldi service port to /etc/services
#    Create /opt/gemstone directory tree
#    Download the GemStone product zipfile
#    Uncompress the GemStone zipfile into /opt/gemstone/
#    Soft link the GemStone directory to /opt/gemstone/product
#    Copy the initial Seaside repository to data directory
#    Print build version information and available IPv4 addresses
#    Remind user to source defSeaside
#=========================================================================

gsvers="GemStone64Bit2.3.0-x86_64.Linux"
zipfile=${gsvers}.zip

# Check we're on a 64-bit Linux machine
if [ "`uname -sm`" != "Linux x86_64" ]
    then 
    echo "### This script only works on a 64-bit Linux OS."
    echo "The result from \"uname -sm\" is \"`uname -sm`\" not \"Linux x86_64\""
    exit 1
fi

# We should run this as a normal user, not root.
if [ `id | cut -f2 -d= | cut -f1 -d\(` -eq 0 ]
    then
    echo "This script must be run as a normal user, not root."
    echo "However, some steps require root access using sudo."
    exit 1
fi

# Check for existence of required executable /usr/bin/bc
if [ ! -x /usr/bin/bc ]
    then
    echo "### This script will not run unless /usr/bin/bc is executable."
    exit 1
fi

# Check that the current directory is writable
if [ ! -w "." ]
    then
    echo "### This script requires write permission on your current directory."
    /bin/ls -ld "`pwd`"
    exit 1
fi

machine_name="`uname -n`"
echo "==> Starting $gsvers installation on $machine_name"

# Do a trivial sudo to test we can and get the password prompt out of the way
sudo date

echo "==> Setting up shared memory"
# Ref: http://developer.postgresql.org/pgdocs/postgres/kernel-resources.html
# Ref: http://www.idevelopment.info/data/Oracle/DBA_tips/Linux/LINUX_8.shtml

# Figure out how much total memory in installed
# use TotalMem: kB because Ubuntu doesn't have Mem: in Bytes
totalMemKB=`awk '/MemTotal:/{print($2);}' /proc/meminfo`
totalMem=$(echo "$totalMemKB * 1024" | bc)
totalMemMB=$(echo "$totalMem / 1048576" | bc)

# Figure out the max shared memory segment currently allowed
shmmax=`cat /proc/sys/kernel/shmmax`
shmmaxMB=$(echo "$shmmax / 1048576" | bc)

# Figure out the max shared memory currently allowed
shmall=`cat /proc/sys/kernel/shmall`
shmallMB=$(echo "$shmall / 256" | bc)

# Print current values
echo "  Total memory available is $totalMemMB MB"
echo "  Max shared memory segment size is $shmmaxMB MB"
echo "  Max shared memory allowed is $shmallMB MB"

# Figure out the max shared memory segment size we want
# Use 75% of available memory but not more than 1GB
testVal=$(echo "$totalMem * 3/4" | bc)
shmmaxNew=$(echo "if ($testVal < 1073741824) $testVal else 1073741824" | bc)
shmmaxNewMB=$(echo "$shmmaxNew / 1048576" | bc)

# Figure out the max shared memory allowed we want
# the Linux default is 2097152 or 8GB, so we should never need this
# but things will certainly break if it's been reset too small
# so ensure it's at least big enough to hold two shared memory segments
testVal=$(echo "$shmmaxNew * 2 / 4096" | bc)
shmallNew=$(echo "if ($testVal > $shmall) $testVal else $shmall" | bc)
shmallNewMB=$(echo "$shmallNew / 256" | bc)

# Increase shmmax if appropriate
if [ $shmmaxNew -gt $shmmax ]
    then
    echo "  Increasing max shared memory segment size to $shmmaxNewMB MB"
    sudo bash -c "echo $shmmaxNew > /proc/sys/kernel/shmmax"
else
    echo "  No need to increase max shared memory segment size"
fi

# Increase shmall if appropriate
if [ $shmallNew -gt $shmall ]
    then
    echo "  Increasing max shared memory allowed to $shmallNewMB MB"
    sudo bash -c "echo $shmallNew > /proc/sys/kernel/shmall"
else
    echo "  No need to increase max shared memory allowed"
fi

# At this point, shared memory settings contain the values we want, 
# put them in sysctl.conf so they are preserved.
if [[ ! -f /etc/sysctl.conf || `grep -sc "kernel.shm" /etc/sysctl.conf` -eq 0 ]]
    then
    echo "# kernel.shm* settings added by GemStone installation" > /tmp/sysctl.conf.$$
    echo "kernel.shmmax=`cat /proc/sys/kernel/shmmax`" >> /tmp/sysctl.conf.$$
    echo "kernel.shmall=`cat /proc/sys/kernel/shmall`" >> /tmp/sysctl.conf.$$
    echo "  Adding the following section to /etc/sysctl.conf"
    cat /tmp/sysctl.conf.$$
    sudo bash -c "cat /tmp/sysctl.conf.$$ >> /etc/sysctl.conf"
    /bin/rm -f /tmp/sysctl.conf.$$
else
    echo "  Shared memory settings already exist in /etc/sysctl.conf"
    grep "kernel.shm" /etc/sysctl.conf
    echo "  to change them, remove the above lines from /etc/sysctl.conf and rerun this script"
fi

echo "==> Setting up GemStone netldi service port"
if [ `grep -sc "^gs64ldi" /etc/services` -eq 0 ]
    then
    echo '  Adding "gs64ldi  50377/tcp" to /etc/services'
    sudo bash -c 'echo "gs64ldi         50377/tcp        # Gemstone netldi"  >> /etc/services'
else
    echo "  GemStone netldi service port is already set in /etc/services"
    grep "^gs64ldi" /etc/services
    echo "  to change it, remove the above line from /etc/services and rerun this script"
fi

# Create some directories that GemStone expects; make them writable
echo "==> Creating /opt/gemstone directory"
if [ ! -e /opt/gemstone ]
    then
    sudo mkdir -p /opt/gemstone /opt/gemstone/log /opt/gemstone/locks
    sudo chown $USER:${GROUPS[0]} /opt/gemstone /opt/gemstone/log /opt/gemstone/locks
    sudo chmod 770 /opt/gemstone /opt/gemstone/log /opt/gemstone/locks
else
    echo "  /opt/gemstone directory already exists"
    echo "  to replace it, remove or rename it and rerun this script"
fi

# Download GemStone
echo "==> Downloading GemStone archive"
if [ ! -e $zipfile ]
    then
    wget http://glass-downloads.gemstone.com/gss23/$zipfile
else
    echo "  $zipfile already exists"
    echo "  to replace it, remove or rename it and rerun this script"
fi

# Unzip the downloaded archive into /opt/gemstone/
echo "==> Uncompressing GemStone archive into /opt/gemstone/"
if [ ! -e /opt/gemstone/$gsvers ]
    then
    unzip -q -d /opt/gemstone $zipfile
else
    echo "  /opt/gemstone/$gsvers already exists"
    echo "  to replace it, remove or rename it and rerun this script"
fi

# Soft link the new GemStone installation to /opt/gemstone/product
echo "==> Linking /opt/gemstone/$gsvers to /opt/gemstone/product" 
if [ ! -e /opt/gemstone/product ]
    then
    ln -sf /opt/gemstone/$gsvers /opt/gemstone/product
else
    if [ ! -h /opt/gemstone/product ]
        then
        # Stop now if /opt/gemstone/product isn't a symlink
        # it might be a prior installation, so exercise caution
        echo "  /opt/gemstone/product already exists and is not a symbolic link"
        echo "  remove or rename it and rerun this script"
        echo "  WARNING - $gsvers installation not completed"
        exit 1
    fi
    echo "  symbolic link /opt/gemstone/product already exists"
    echo "  to replace it, remove or rename it and rerun this script"
fi

# Copy an initial extent to the Seaside data directory
echo "==> Copying initial Seaside repository to data directory"
if [ ! -e /opt/gemstone/product/seaside/data/extent0.dbf ]
    then
    cp /opt/gemstone/product/bin/extent0.seaside.dbf \
        /opt/gemstone/product/seaside/data/extent0.dbf
    chmod 644 /opt/gemstone/product/seaside/data/extent0.dbf
else
    echo "  /opt/gemstone/product/seaside/data/extent0.dbf already exists"
    echo "  to replace it, remove or rename it and rerun this script"
fi

echo "==> Finished $gsvers installation on $machine_name"
echo ""
echo "### GemStone version information:"
cat /opt/gemstone/product/version.txt

# If we can determine any IPv4 addresses, print them out. Otherwise be silent.
if [[ -x /sbin/ifconfig && `/sbin/ifconfig -a | grep -sc " inet addr:.*Bcast"` -gt 0 ]]
    then
    echo ""
    echo "### $machine_name has the following IPv4 addresses:"
    /sbin/ifconfig -a | grep ' inet addr:.*Bcast' | cut -f2 -d: | cut -f1 -d' '
fi

# Reminder to setup environment variables
echo ""
echo "### Remember to set GEMSTONE environment variables by running:"
echo "source /opt/gemstone/product/seaside/defSeaside"

# End of script
exit 0
