#!/bin/bash
#
# test_mem
#
# ULS-Agent memory usage
#
# Aufruf: test_mem [-abcCdHipvw] [-d <path>] [-h <ulshostname>] [-s <section>] [-t <teststep>] [-e <num>]
#         -a: Active
#         -b: Buffers
#         -c: Cached
#         -C: Config-dir
#         -d: storepath
#         -D: Dirty
#         -e: show processes with excessive swapping
#         -h: ulshostname
#         -H: HugePages Total, Free, Rsvd, size
#         -i: inactive
#         -p: enable output of percentage of Mem and Cache
#         -s: section
#         -S: SwapCached
#         -t: teststep
#         -v: send all values
#         -w: Writeback
##############################################################################################
#
unset TMP_PATH SETULSHOSTNAME SECTION TESTSTEP FLAGS PFLAG CONFIGDIR SWAPTOPNUM
while getopts abce:SDipvwh:s:t:d:C:T:nqQ? op
 do
  case "$op" in
   a|b|c|S|D|H|i|w) FLAGS=$FLAGS$op;;
   v) FLAGS=abcCdhiw;;
   p) PFLAG=1;;
   C) [[ -n "$OPTARG" ]] && CONFIGDIR="$OPTARG";;
   d) [[ -n "$OPTARG" ]] && TMP_PATH="-d $OPTARG";;
   e) [[ -n "$OPTARG" ]] && SWAPTOPNUM="$OPTARG";;
   h) [[ -n "$OPTARG" ]] && SETULSHOSTNAME="$OPTARG";;
   s) [[ -n "$OPTARG" ]] && SECTION="$OPTARG";;
   t) [[ -n "$OPTARG" ]] && TESTSTEP="$OPTARG";;
   T) ;;
   m) SMPFLAG=1;;
   *) echo "usage: `basename $0` [-abcCDeHipvw?] [-C <path>] [-d <path>] [-h <ulshostname>] [-s <section>] [-t <teststep>]"
      exit 1;;
  esac
done
shift $(( $OPTIND -1))
#
. `dirname $0`/uls_header
#
( awk -v H="${SETULSHOSTNAME:-$ULSHOSTNAME}" -v SECTION="${SECTION:-System}" -v TESTSTEP="${TESTSTEP:-Memory Swap}" -v FLAGS="$FLAGS" -v PFLAG="${PFLAG:-0}" -v DT="$DT" -F '[: ] *' '
function flformat(f)
{ if( f < 0.0000001 )
    d = 0
  else
  { d = 4 - log(f)/2.3
    if( d < 0 )
     d = 0
  }
  return sprintf("%0.*f", d, f)
}

function mb(z, e)
{ if( e == "" || z == 0 )
    return z
  else if( e == "kb" )
    return z/1024
  else if( e == "mb" )
    return z
  else if( e == "gb" )
    return z*1024
}

BEGIN { print "D;" DT ";" H ";" SECTION ";" TESTSTEP ";" }

{ mv[tolower($1)] = mb($2, tolower($3)) }

/Hugepagesize/ { hps = $2 " " $3 }

END { printf("V;;;;;Mem total;%d;MByte;\n", mv["memtotal"] )
      mf = mv["memfree"] + mv["buffers"] + mv["cached"]
      mu = mv["memtotal"] - mf
      printf("V;;;;;Mem used;%d;MByte;\n", mu)
      printf("V;;;;;Mem free;%d;MByte;\n", mf)
      printf("V;;;;;Swap total;%d;MByte;\n", st = mv["swaptotal"])
      su = mv["swaptotal"] - mv["swapfree"]
      printf("V;;;;;Swap used;%d;MByte;\n", su)
      printf("V;;;;;Swap free;%d;MByte;\n", mv["swapfree"])
      if( PFLAG )
      { printf("V;;;;;Mem %%used;%d;%%;\n", 100*mu/mv["memtotal"])
        printf("V;;;;;Swap %%used;%d;%%;\n", 100*su/mv["swaptotal"])
      }
      if( FLAGS ~ "c" )
        printf("V;;;;;Cached;%d;MByte;\n", mv["cached"])
      if( FLAGS ~ "C" )
        printf("V;;;;;SwapCached;%d;MByte;\n", mv["swapcached"])
      if( FLAGS ~ "b" )
        printf("V;;;;;Buffers;%d;MByte;\n", mv["buffers"])
      if( FLAGS ~ "a" )
        printf("V;;;;;Active;%d;MByte;\n", mv["active"])
      if( FLAGS ~ "i" )
        printf("V;;;;;Inactive;%d;MByte;\n", mv["inactive"])
      if( FLAGS ~ "D" )
        printf("V;;;;;Dirty;%s;MByte;\n", flformat(mv["dirty"]))
      if( FLAGS ~ "w" )
        printf("V;;;;;Writeback;%s;MByte;\n", flformat(mv["writeback"]))
      if( FLAGS ~ "h" )
      { printf("V;;;;;Hugepagesize;%s;[E];\n", hps)
        printf("V;;;;;Huge Pages Total;%d;#;\n", mv["hugepages_total"])
        printf("V;;;;;Huge Pages Free;%d;#;\n", mv["hugepages_free"])
        printf("V;;;;;Huge Pages Reserved;%d;#;\n", mv["hugepages_rsvd"])
      }
}' /proc/meminfo
#
if [[ -n "$SWAPTOPNUM" ]]
 then
  find /proc -maxdepth 2 -name statm -mmin +1 | awk -v SNUM="$SWAPTOPNUM" '
BEGIN { for(i = 1; i <= SNUM; i++)
        { m[1] = 0
        }
      }
{ f = $0
  if( (getline < f ) )
  { s = $1 - $2
    if( s > m[SNUM] )
    { for( i = SNUM; i >=1; i-- )
      { m[i+1] = m[i]
        p[i+1] = p[i]
        if( i == 1 || s <= m[i-1] )
        { m[i] = s
          p[i] = gensub("/proc/([0-9]*)/statm", "\\1", 1, f)
          break
        }
      }
    }
    close(f)
  }
}
END { for( i = 1; i <= SNUM; i++ )
      { f = "/proc/" p[i] "/stat"
        if( (getline < f) > 0 )
        { P = gensub("[(](.*)[)]", "\\1", 1, $2)
          if( O !~ P )
          { if( i > 1 )
              O = O ", "
            O = O P
          }
          close(f)
        }
      }
      if( O )
        printf("V;;;;;Swap-Top-Processes;%s;[ ]\n", O)
    }'
fi
) | send_test_tab $TMP_PATH
