#!/bin/sh
#-----------------------------------------------------------------------------
# /var/install/bin/postgresql-calc-shmmax - calculate required shmmax-segment
#
# Copyright (c) 2009 Daniel Vogel <daniel_vogel(at)t-online(dot)de>
#
# Creation:     2009-04-10 dv
# Last Update:  $Id$
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#-----------------------------------------------------------------------------

. /etc/config.d/postgresql
 
#-----------------------------------------------------------------------------
# this is a helper script to automatically adjust shmmax kernel configuration
# if required. The formula was taken from the postgresql 8.3 documentation.
#
# Approximate multiplier (bytes per increment) as of 8.3:
#
# max_connections              1800 + 270 * max_locks_per_transaction
# autovacuum_max_workers       1800 + 270 * max_locks_per_transaction
# max_prepared_transactions    770 + 270 * max_locks_per_transaction
# shared_buffers               8400 (assuming 8 kB BLCKSZ)
# wal_buffers                  8200 (assuming 8 kB XLOG_BLCKSZ)
# max_fsm_relations            70
# max_fsm_pages                6
# Fixed space requirements     770 kB
#-----------------------------------------------------------------------------

# here are some defaults from postgresql.conf
MAX_LOCKS_PER_TRANSACTION=64
AUTOVACUUM_MAX_WORKERS=3
SHARED_MEM_DEFAULT=16MB
WAL_BUFFERS_DEFAULT=64kB
MAX_FSM_RELATIONS=1000
MAX_FSM_PAGES=153600

#-----------------------------------------------------------------------------
# convert memory size value to unified value in kB
#-----------------------------------------------------------------------------

function getMemSize()
{
    local a=$1
    local multiply=$2

    pos=$[${#a} - 2]

    case "${a:$pos}" in
        kB)   
            a=${a:0:$pos}
            ;;

        MB)
            a=$[${a:0:$pos} * 1024]
            ;;

        GB)
            a=$[${a:0:$pos} * 1024 * 1024]
            ;;

        *)
            a=$[$a * multiply]
    esac

    echo $a
}
 
# collect all required values
mem_max_locks=$[270 * ${MAX_LOCKS_PER_TRANSACTION}]
mem_connect=$[(${POSTGRESQL_MAX_CONNECTS} * (1800 + ${mem_max_locks})) / 1024 + 1]
mem_autovac=$[(${AUTOVACUUM_MAX_WORKERS}  * (1800 + ${mem_max_locks})) / 1024 + 1]
mem_transac=$[(${POSTGRESQL_PREP_TRANSACTIONS} * (770 + ${mem_max_locks})) / 1024 + 1]

if [ "${POSTGRESQL_RESOURCE_TUNING}" == 'yes' ]
then
    mem_sharedb=$(getMemSize "${POSTGRESQL_SHARED_MEM}" "8")
else
    mem_sharedb=$(getMemSize "${SHARED_MEM_DEFAULT}" "8")
fi
  
if [ "${POSTGRESQL_WAL_TUNING}" == 'yes' ]
then
    mem_buffers=$(getMemSize "${POSTGRESQL_WAL_DATA_MEM}" "8")
else
    mem_buffers=$(getMemSize "${WAL_BUFFERS_DEFAULT}" "8")
fi

mem_fsmrel=$[(${MAX_FSM_RELATIONS} * 70) / 1024 + 1]
mem_fsmpag=$[(${MAX_FSM_PAGES} * 6) / 1024 + 1]

# sum everything up
mem_total=$[ 770 + \
    $mem_connect + \
    $mem_autovac + \
    $mem_transac + \
    $mem_sharedb + \
    $mem_buffers + \
    $mem_fsmrel + \
    $mem_fsmpag ]
                    
#echo result (plus extra space)
echo $[$mem_total + 1024]

exit 0