#!/usr/bin/env bash
#
# The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
# (the "License"). You may not use this work except in compliance with the License, which is
# available at www.apache.org/licenses/LICENSE-2.0
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied, as more fully set forth in the License.
#
# See the NOTICE file distributed with this work for information regarding copyright ownership.
#

SCRIPT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"; pwd)"

get_env() {
  DEFAULT_LIBEXEC_DIR="${SCRIPT_DIR}"/../../../libexec
  ALLUXIO_LIBEXEC_DIR=${ALLUXIO_LIBEXEC_DIR:-${DEFAULT_LIBEXEC_DIR}}
  . ${ALLUXIO_LIBEXEC_DIR}/alluxio-config.sh

  ALLUXIO_FUSE_JAR=${SCRIPT_DIR}/../target/alluxio-integration-fuse-${VERSION}-jar-with-dependencies.jar
  FUSE_MAX_WRITE=131072
  CLASSPATH=${CLASSPATH}:${ALLUXIO_FUSE_JAR}
}

check_java_version() {
  local java_mjr_vers=$("${JAVA}" -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F'.' '{print $1 $2}')
  if [[ ${java_mjr_vers} -lt 18 ]]; then
    echo "You are running a version of Java which is older than Java 8.
     Please use Java 8 to use alluxio-fuse" >&2
    return 1
  else
    return 0
  fi
}

check_fuse_jar() {
  if ! [[ -f ${ALLUXIO_FUSE_JAR} ]]; then
    echo "Cannot find ${ALLUXIO_FUSE_JAR}. Please compile alluxio with fuse profile and Java 8"
    return 1
  else
    return 0
  fi
}

set_java_opt() {
  JAVA_OPTS+=" -server -Xms1G -Xmx1G -XX:MaxDirectMemorySize=4g"

  ALLUXIO_FUSE_JAVA_OPTS+=" ${ALLUXIO_JAVA_OPTS}"
  ALLUXIO_FUSE_JAVA_OPTS+=" -Dalluxio.logger.type=FUSE_LOGGER"
}

mount_fuse() {
  echo "Starting alluxio-fuse on local host."
  local mount_point=$1
  local alluxio_root=$2
  local full_mount_option=""
  if [[ ! -z "${mount_option}" ]]; then
    full_mount_option="big_writes,${mount_option}"
  else
    full_mount_option="big_writes"
  fi

  if [[ ${NO_DAEMON} -eq "1" ]]; then
    # Assumes that the end of ALLUXIO_FUSE_JAVA_OPTS is -Dalluxio.logger.type=FUSE_LOGGER
    ALLUXIO_FUSE_JAVA_OPTS+=",Console"
  fi

  local cmd="${JAVA} -cp ${CLASSPATH} ${JAVA_OPTS} ${ALLUXIO_FUSE_JAVA_OPTS} \
    alluxio.fuse.AlluxioFuse \
    -o ${full_mount_option} \
    -m ${mount_point} \
    -r ${alluxio_root}"

  if [[ ${NO_DAEMON} -eq "1" ]]; then
    exec ${cmd}
  else
    (nohup ${cmd} > ${ALLUXIO_LOGS_DIR}/fuse.out 2>&1) &
    # sleep: workaround to let the bg java process exit on errors, if any
    sleep 2s
    if kill -0 $! > /dev/null 2>&1 ; then
      echo "Successfully mounted Alluxio path \"${alluxio_root}\" to ${mount_point}."
      echo "See ${ALLUXIO_LOGS_DIR}/fuse.log for logging messages"
      return 0
    else
      echo "Failed to mount Alluxio path \"${alluxio_root}\" to ${mount_point}."
      echo "See ${ALLUXIO_LOGS_DIR}/fuse.out for more details"
      return 1
    fi
  fi
}

umount_fuse() {
  local mount_point=$1
  local fuse_pid=$(fuse_stat | awk '{print $1,$2}' | grep -w ${mount_point} | awk '{print $1}')
  if [[ -z ${fuse_pid} ]]; then
    echo "${mount_point} not mounted" >&2
    return 1
  else
    echo "Unmount fuse at ${mount_point} (PID: ${fuse_pid})."
    kill ${fuse_pid}
    return $?
  fi
}

fuse_stat() {
  local jps="jps"
  if [[ ! -z ${JAVA_HOME} ]]; then
    jps="${JAVA_HOME}/bin/jps"
  fi
  local fuse_info=$("${jps}" | grep AlluxioFuse)
  if [[ -z ${fuse_info} ]]; then
    echo "No mount point found. AlluxioFuse process is not running."
    echo -e "${MOUNT_USAGE}"
    return 1
  else
    echo -e "pid\tmount_point\talluxio_path"
    echo -e "$(ps aux | grep [A]lluxioFuse | awk -F' ' '{print $2 "\t" $(NF-2) "\t" $NF}')"
    return 0
  fi
}

USAGE_MSG="Usage:\n\talluxio-fuse [mount|umount|stat]

mount \tmount an Alluxio path to local file system
umount \tunmount an Alluxio path from local file system
stat \tshow status of Alluxio mount points"

MOUNT_USAGE="
Mounts a path in Alluxio namespace (defaults to "/") to mount point on local file system.
When no argument is given, list the current mount point

Usage:\talluxio-fuse mount [-n] [-o <mount option>] <mount_point> [alluxio_path]
\talluxio-fuse mount

-o \tmount options for the fuse daemon
-n \tno-daemon. This launches the process in the foreground and logs to stdout"

if [[ $# -lt 1 ]]; then
  echo -e "${USAGE_MSG}" >&2
  exit 1
fi

get_env
check_java_version && check_fuse_jar
set_java_opt
if [[ $? -ne 0 ]]; then
  exit 1
fi

case $1 in
  mount)
    shift
    while getopts "o:n" option; do
      case "${option}" in
        o)
          mount_option=${OPTARG}
          ;;
        n)
          NO_DAEMON="1"
          ;;
        *)
          echo -e "${MOUNT_USAGE}" >&2
          exit 1
          ;;
      esac
    done
    shift $((${OPTIND} - 1))
    if [[ $# -eq 0 ]]; then
      fuse_stat
      exit $?
    fi
    if [[ $# -eq 1 ]]; then
      mount_fuse $1 /
      exit $?
    fi
    if [[ $# -eq 2 ]]; then
      mount_fuse $1 $2
      exit $?
    fi
    echo -e "${MOUNT_USAGE}" >&2
    exit 1
    ;;
  umount|unmount)
    if [[ $# -eq 2 ]]; then
      umount_fuse $2
      exit $?
    fi
    echo -e "Usage\n\talluxio-fuse umount mount_point\n\tuse mount stat to show mount points" >&2
    exit 1
    ;;
  stat)
    fuse_stat
    ;;
  *)
    echo -e "${USAGE_MSG}" >&2
    exit 1
    ;;
esac
