#!/bin/sh
# BLURB gpl
#
#			    Coda File System
#				Release 6
#
#		Copyright (c) 1987-2003 Carnegie Mellon University
#			Additional copyrights listed below
#
# This  code  is  distributed "AS IS" without warranty of any kind under
# the terms of the GNU General Public Licence Version 2, as shown in the
# file  LICENSE.  The  technical and financial  contributors to Coda are
# listed in the file CREDITS.
#
#			  Additional copyrights
#			     none currently
#
#*/

echon() {
    if [ "$(echo -n)" = "-n" ] ; then
	echo "$@"'\c'
    else
	echo -n "$@"
    fi
}

fullname() {
    ( cd "$(dirname "$1")" ; echo "$(pwd)/$(basename "$1")" )
}

# exit if errors
set -e

# do the unlimit in case needed
if ulimit -d unlimited ; then
  echon
fi

#
# Configuration
#

# defaults, will be overridden by settings in the server.conf file
vicedir=/vice

prefix=/usr
exec_prefix=${prefix}
conf="$("${exec_prefix}/sbin/codaconfedit" server.conf)"
if [ "$conf" != /dev/null ] ; then
  . "$conf"
  haveconf=1
else
  haveconf=0
fi

if [ -f "$vicedir/srv.conf" ]; then
   grep '^\-rvm ' "$vicedir/srv.conf"
   if [ $? = 0 ]; then
       echo "You already have rvm parameters in srv.conf."
       echo "Remove these first."
       exit 1
   fi
fi

echo
echo A server needs a small log file or disk partition, preferably on a
echo disk by itself. It also needs a metadata file or partition of approx
echo 4% of your filespace.
echo
echo Raw partitions have advantages because we can write to the disk
echo faster, but we have to load a copy of the complete RVM data
echo partition into memory. With files we can use a private mmap, which
echo reduces memory pressure and speeds up server startup by several
echo orders of magnitude.
echo
echo Servers with a smaller dataset but heavy write activity will
echo probably benefit from partitions. Mostly read-only servers with a
echo large dataset will definitely benefit from an RVM data file. Nobody
echo has really measured where the breakeven point is, so I cannot
echo really give any hard numbers.
echo
echo     -------------------------------------------------------
echo     WARNING: you are going to play with your partitions now.
echo     verify all answers you give.
echo     -------------------------------------------------------
echo
echo WARNING: these choices are not easy to change once you are up and running.
echo

yesno=""
while [ "$yesno" = "" ]; do
    echon "Are you ready to set up RVM? [yes/no] "
    read -r yesno

    case "$(echo "$yesno" | tr '[:upper:]' '[:lower:]')" in
    y|yes) ;;
    n|no) echo "Run vice-setup-rvm when you are ready!" ; exit 1 ;;
    *) yesno="" ; echo "Please answer yes or no." ;;
    esac
done

#
# we need a size and partition for the log.
#
log=""
until [ "$log" != "" ]; do
    echon "What will be your log file (or partition)? "
    read -r log
done

logsize=""
until [ "$logsize" != "" ]; do
    echo
    echo "The log size must be smaller than the available space in the log"
    echo "partition. A smaller log will be quicker to commit, but the log"
    echo "needs to be large enough to handle the largest transaction. A"
    echo "larger log also allows for better optimizations. We recommend"
    echo "to keep the log under 30M log size, many people have successfully"
    echo "used as little as 2M, and 20M has worked well with our servers."
    echon "What is your log size? (enter as e.g. '20M') "
    read -r logsize
    echo
done

data=""
until [ "$data" != "" ]; do
    echon "Where is your data file (or partition)? "
    read -r data
done

datasize=""
until [ "$datasize" != "" ]; do
    echo
    echo  "The amount of RVM we need to store the metadata for a given"
    echo  "amount file space can vary enormously. If your typical data set"
    echo  "consists of many small files, you definitely need more RVM, but"
    echo  "if you tend to store large files (mp3s, videos or image data)"
    echo  "we don't need all that much RVM."
    echo
    echo  "Here are some random samples,"
    echo  "  mp3 files     ~0.08MB RVM per GB."
    echo  "  jpeg images   ~0.50MB RVM per GB."
    echo  "  email folders ~37.8MB RVM per GB (maildir, 1 file per message)"
    echo  "  netbsd-pkgsrc  ~180MB RVM per GB (large tree but not much data)"
    echo
    echo  "To get a more precize number for your dataset there is a small"
    echo  "tool (rvmsizer) which can reasonably predict the amount of RVM"
    echo  "data we need for a file tree."
    echo
    echo  "Remember that RVM data will have to be mmapped or loaded"
    echo  "into memory, so if anything fails with an error like"
    echo  "RVM_EINTERNAL you might have to add more swap space."
    echo
    echo "What is the size of you data file (or partition)"
    echon "[32M, 64M, 128M, 256M, 512M, 768M, 1G]: "
    read -r datasize

    case $datasize in
        32[mM] | 64[mM] | 128[mM] | 256[mM] )
            ;;
        512[mM] | 768[mM] | 1[gG] )
            echo
            echo "!!!!!!!!!!!!!!"
            echo Your size is an experimental size.  Be warned!
            echo You may want to run with private mapping for RVM.
            echo
            ;;
        * )
            yesno=
            while [ "$yesno" = "" ] ; do
                echo
                echo "You have selected an unsupported size and this script"
                echo "will not setup your RVM with this size.  Are you sure"
                echon "you want this size?  (yes/no) "
                read -r yesno

                case "$(echo "$yesno" | tr '[:upper:]' '[:lower:]')" in
                y|yes) ;;
                n|no) datasize="" ;;
                *) yesno="" ; echo "Please answer yes or no." ;;
                esac
            done
            ;;
    esac
done

log=$(fullname "$log")
data=$(fullname "$data")

# strip non-digit characters
datasize="$(echo "$datasize" | sed -n 's/\([0-9]*\).*/\1/p')"
# Assume values <= 4 are in gigabytes, else we assume megabytes
[ "$datasize" -le 4 ] && datasize=$((datasize * 1024))

echo
echo --------------------------------------------------------
echo WARNING: DATA and LOG  partitions are about to be wiped.
echo --------------------------------------------------------
echo
echo "  --- log area: $log, size $logsize."
echo "  --- data area: $data, size $datasize MB."
echo
yesno=""
while [ "$yesno" = "" ]; do
    echon "Proceed, and wipe out old data? [y/n] "
    read -r yesno

    case "$(echo "$yesno" | tr '[:upper:]' '[:lower:]')" in
    y|yes) ;;
    n|no) exit 1 ;;
    *) yesno="" ; echo "Please answer yes or no." ;;
    esac
done

echo
"/usr/sbin/rvmutl" > /dev/null  << EOF
i $log $logsize
q
EOF

echo
if [ $? != 0 ]; then
    echo Error in rvmutl. Exiting.
    exit 1
fi

echo LOG file has been initialized!

echo

# Convert requested RVM data size to bytes
dsparm=$((datasize * 1048576))
staticsize=1048576 # reserve 1MB for a static allocation area
rvmreserve=65536   # reserve 64K for RVM overhead (we need pagesize() bytes)

# Use the remaining space for the dynamic heap
heapsize=$((dsparm - staticsize - rvmreserve))

# various other parameters
rvmstart=0x50000000
nlists=80
chunk=64

if [ $haveconf = 1 ] ; then
    conffile="$(basename "$conf")"
    "${exec_prefix}/sbin/codaconfedit" "$conffile" rvm_log "$log"
    "${exec_prefix}/sbin/codaconfedit" "$conffile" rvm_data "$data"
    "${exec_prefix}/sbin/codaconfedit" "$conffile" rvm_data_length "$dsparm"
else
    echo "\-rvm $log $data $dsparm" >> "$vicedir/srv.conf"
fi

echo
echo "Rdsinit will initialize data and log."
echo "This takes a while."
"/usr/sbin/rdsinit" -f "$log" "$data" $dsparm $rvmstart $heapsize $staticsize $nlists $chunk

if [ $? != 0 ]; then
    echo Error in rdsinit. Exiting.
    exit 1
fi

echo RVM setup is done!
echo
