#!/bin/bash
# Bash library for basic script functions

# Check directories/files existence
lmba_checkexist() {
  # Takes the checked type as parameter 1, the path itself as parameter 2 and
  # the exit code on failure as parameter 3
  # If the failure exit code is 0, no exit is performed and the module returns
  # normally
  # Returns 0 on existence
  # Returns 1 on nonexistence (if failure exit code is set to 0)

  # Check
  if [ -"$1" "$2" ]
    then
      # Existing dir/file
      return 0
    else
      if [ "$3" = "0" ]
        then
          # Nonexistence is deemed not critical
          return 1
        else
          # Nonexistence is deemed critial, log that
          lmba_echolog "$2 of type $1 does not exist!"
          exit "$3"
      fi
  fi
}

# Debug logging
# Logs differencial time between start and the time the log is written
lmba_difflogger() {
  # Takes the message as parameter 1; demands for LMBA_LOG and LMBA_STARTTIME
  # to be set
  # Returns nothing
  
  # Only log on set log file
  if [ "$LMBA_LOG" != "" -a "$LMBA_STARTTIME" != "" ]
    then
      local TIME=$(echo "$(date +'%s.%N') - $LMBA_STARTTIME" | bc -l)
      if [ "${TIME:0:1}" = "." ]
        then
          TIME="0$TIME"
      fi
      echo "$TIME: $*" >> "$LMBA_LOG"
  fi
}

# Logging with additional echo to STDOUT
lmba_echolog() {
  # Takes the message as parameter 1; submodules demand for LMBA_LOG to be set
  # If LMBA_STARTTIME is set too, it will use lmba_difflogger as submodule,
  # otherwise it'll be lmba_logger
  # Returns nothing

  # Push message to STDOUT
  echo "$*"
  # Invoke submodule for logging to file
  if [ "$LMBA_STARTTIME" != "" ]
    then
      lmba_difflogger "$*"
    else
      lmba_logger "$*"
  fi
}

# Logging
lmba_logger() {
  # Takes the message as parameter 1; demands for LMBA_LOG to be set
  # Returns nothing
  
  # Only log on set log file
  if [ "$LMBA_LOG" != "" ]
    then
      echo "$(date +'%F %T'): $*" >> "$LMBA_LOG"
  fi
}

# Managing a PID file
lmba_pidfile() {
  # Gets the action as parameter 1; demands for LMBA_PIDFILE and LMBA_MYPID to
  # be set
  # Returns 0 on OK
  # Returns 1 on errors
  
  # Check prerequisites
  if [ "$LMBA_MYPID" = "" -o "$LMBA_PIDFILE" = "" ]
    then
      return 1
  fi
  
  # Set or delete the PID file
  case "$1" in
    delete)
      if rm -f "$LMBA_PIDFILE" > /dev/null 2>&1
        then
          return 0
        else
          return 1
      fi
      ;;
    set)
      # Probes for orphaned PID
      if [ -f "$LMBA_PIDFILE" ]
        then
          local PID=$(<"$LMBA_PIDFILE")
          # Check if this PID is still used by a running process
          if ps ax | grep "$PID" | grep "$0" > /dev/null
            then
              # Check if we are the running process
              if [ "$PID" = "$LMBA_MYPID" ]
                then
                  # PID file is ours, no need to set again
                  return 0
                else
                  # PID file belongs to a running process
                  return 1
              fi
            else
              rm -f "$LMBA_PIDFILE"
          fi
      fi

      # Write PID file
      echo "$LMBA_MYPID" > "$LMBA_PIDFILE"
      # Sleep for a random amount of milliseconds before reading the PID file
      # again to provide hardening against race conditions
      sleep 0.${RANDOM}
      local PID=$(<"$LMBA_PIDFILE")
      if [ "$PID" = "$LMBA_MYPID" ]
        then
          return 0
        else
          return 1
      fi
      ;;
  esac
}
