#!/bin/bash

############################################################################################
# Author : vseva@sipwise.com
#
# Script will make kamailio to dump content of shm memory and produce a memory usage report
#
###############################################################################################
set -e

ME="$(basename "$(readlink -f "$0")")"
KAM=proxy
DATE=$(date +'%Y%m%d%H%M')
TMP_DEF=/run/${ME}
mem_dump=false

function do_mem_dump {
  echo "$(date) - send mem_dump_shm command to ${KAM}"
  DATE_KAM=$(date)
  ngcp-kamcmd "${KAM}" cfg.set_now_int core mem_dump_shm 1
  DATE_KAM_END=$(date)
  echo "$(date) - mem_dump_shm command done"

  # +'%b %e %H:%M' depends on the locate configuration of the server
  # Jun  2 09:06:37
  DATE_REG=$(date +'%b %e %H:%M' --date="${DATE_KAM}")
  DATE_KAM_END=$(date +'%b %e %H:%M' --date="${DATE_KAM_END}")
  if [ "${DATE_REG}" == "${DATE_KAM_END}" ] ; then
    grep "${DATE_REG}.*qm_status" "${KAM_LOG}" > "${TMP_FILE}"
  else
    echo "${DATE_REG}.*qm_status" > "${TMP_DEF}.regex"
    printf "."
    i=1
    while true ; do
      DATE_REG=$(date +'%b %e %H:%M' --date="${DATE_KAM} +$i minutes")
      echo "${DATE_REG}.*qm_status" >> "${TMP_DEF}.regex"
      printf "."
      ((i++))
      [ "${DATE_REG}" == "${DATE_KAM_END}" ] && break
    done
    echo "regex file ${TMP_DEF}.regex created"
    grep -f "${TMP_DEF}.regex" "${KAM_LOG}" > "${TMP_FILE}"
  fi
  # be sure we got everything, this must be the last line
  tail -1 "${TMP_FILE}" | grep -q 'qm_status:.*-----------------------------' || (echo "end of qm_status not detected at ${TMP_FILE}" >&2; exit 1)
  grep alloc "${TMP_FILE}" | sed 's/^.*from //g' | sort | uniq -c | sort -k1n > "${REPORT_FILE}"
  echo "core.shmem in Megabytes" >> "${REPORT_FILE}"
  ngcp-kamcmd "${KAM}" core.shmmem M >> "${REPORT_FILE}"
}

# --- help -----
function usage {
  echo "$ME - generate kamailio shm memory report"
  echo "Usage: $ME [-h] [-k proxy|lb] [-f report_file]"
  echo
  echo "OPTIONS:"
  echo "  -h this help"
  echo "  -x use mem_dump_shm command. Just for devel!! don't use it in prod"
  echo "  -k kamailio instance (proxy|lb), default: proxy"
  echo "  -d directory to store reports, default: ${TMP_DEF}"
  echo "  -f report file, default: ${TMP_DEF}/shm_usage_YYYYmmddHHMM.txt"
}

if [ "$UID" -ne 0 ] ; then
  printf "Error: %s requires root permissions. Exiting.\\n" "${ME}" >&2
  exit 1
fi

while getopts 'hd:k:f:x' opt; do
  case $opt in
    h) usage; exit 0;;
    d) TMP_DIR=$OPTARG;;
    k) KAM=$OPTARG;;
    f) REPORT_FILE=$OPTARG;;
    x) mem_dump=true;;
    *) echo ""; usage >&2; exit 1;;
  esac
done
shift $((OPTIND - 1))

TMP_DIR=${TMP_DIR:-${TMP_DEF}}

case $KAM in
  proxy|lb)
    KAM_LOG=/var/log/ngcp/kamailio-${KAM}.log ;;
  *)
    echo "KAM has to be proxy or lb" >&2
    exit 1 ;;
esac

if [ ! -f "${KAM_LOG}" ] ; then
  echo "there's no ${KAM_LOG} file" >&2
  exit 2
fi

TMP_FILE="${TMP_DIR}/qm_status_${DATE}.txt"
REPORT_FILE=${REPORT_FILE:-${TMP_DIR}/shm_usage_${DATE}.txt}

mkdir -p "${TMP_DIR}"

if ${mem_dump} ; then
  do_mem_dump
else
  ngcp-kamcmd "${KAM}" mod.mem_statsx all shm > "${REPORT_FILE}"
  echo "core.shmem in Megabytes" >> "${REPORT_FILE}"
  ngcp-kamcmd "${KAM}" core.shmmem M >> "${REPORT_FILE}"
fi
echo "report ${REPORT_FILE} generated"
