#
# Copyright (C) 2017-2018 Dremio Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#
# Environment Variables:
#
#   JAVA_HOME                  The java implementation to use.
#
#   DREMIO_CLASSPATH            Extra Java CLASSPATH entries.
#
#   DREMIO_CLASSPATH_PREFIX     Extra Java CLASSPATH entries that should
#                               be prefixed to the system classpath.
#
#   HADOOP_HOME                 Hadoop home
#
#   HBASE_HOME                  HBase home

# resolve links - "${BASH_SOURCE-$0}" may be a softlink
this="${BASH_SOURCE-$0}"
while [ -h "$this" ]; do
  ls=`ls -ld "$this"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '.*/.*' > /dev/null; then
    this="$link"
  else
    this=`dirname "$this"`/"$link"
  fi
done

# convert relative path to absolute path
bin=`dirname "$this"`
script=`basename "$this"`
home=`cd "$bin/..">/dev/null; pwd`
this="$home/bin/$script"

# the root of the dremio installation
if [ -z "$DREMIO_HOME" ]; then
  DREMIO_HOME="$home"
fi

#check to see if the conf dir or dremio home are given as an optional arguments
while [ $# -gt 1 ]; do
  if [ "--config" = "$1" ]; then
    shift
    confdir=$1
    shift
    DREMIO_CONF_DIR=$confdir
  else
    # Presume we are at end of options and break
    break
  fi
done

if [ -z "$DREMIO_CONF_DIR" ]; then
  # Defaults to local configuration if configuration is not set
  DREMIO_CONF_DIR="${DREMIO_HOME}/conf"
elif [ ! -d "${DREMIO_CONF_DIR}" -o ! -x "${DREMIO_CONF_DIR}" ]; then
  echo "Dremio conf directory $DREMIO_CONF_DIR does not exist, is not a directory or is not accessible."
  exit 1
fi

# Source ${DREMIO_ENV_SCRIPT} for any user configured values
if [ -f "${DREMIO_CONF_DIR}/${DREMIO_ENV_SCRIPT}" ]; then
  . "${DREMIO_CONF_DIR}/${DREMIO_ENV_SCRIPT}"
fi

# get log directory
DREMIO_LOG_DIR="${DREMIO_LOG_DIR:-${DREMIO_HOME}/log}"

touch "$DREMIO_LOG_DIR/server.out" &> /dev/null
TOUCH_EXIT_CODE=$?
if [ "$TOUCH_EXIT_CODE" = "0" ]; then
  if [ "x$DREMIO_LOG_DEBUG" = "x1" ]; then
    echo "Dremio log directory: $DREMIO_LOG_DIR"
  fi
  DREMIO_LOG_DIR_FALLBACK=0
else
  #Force DREMIO_LOG_DIR to fall back
  DREMIO_LOG_DIR_FALLBACK=1
fi

if [ ! -d "$DREMIO_LOG_DIR" ] || [ "$DREMIO_LOG_DIR_FALLBACK" = "1" ]; then
  if [ "x$DREMIO_LOG_DEBUG" = "x1" ]; then
    echo "Dremio log directory $DREMIO_LOG_DIR does not exist or is not writable, defaulting to $DREMIO_HOME/log"
  fi
  DREMIO_LOG_DIR="$DREMIO_HOME/log"
fi

mkdir -p "$DREMIO_LOG_DIR/json"

# Add Dremio conf folder at the beginning of the classpath
DREMIO_CLASSPATH="$DREMIO_CONF_DIR"

# Followed by any user specified override jars
if [ "${DREMIO_CLASSPATH_USER_FIRST}x" != "x" ]; then
  DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$DREMIO_CLASSPATH_USER_FIRST"
fi

# Next Dremio core jars
DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$DREMIO_HOME/jars/*"

# Followed by Dremio override dependency jars
DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$DREMIO_HOME/jars/ext/*"

# Followed by Hadoop's jar
if [ "${HADOOP_CLASSPATH}x" != "x" ]; then
  DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$HADOOP_CLASSPATH"
fi

# Followed by HBase' jar
if [ "${HBASE_CLASSPATH}x" != "x" ]; then
  DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$HBASE_CLASSPATH"
fi

# Followed by Dremio other dependency jars
# Make sure * is not expended by shell
DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$DREMIO_HOME/jars/3rdparty/*"

# Finally any user specified
if [ "${DREMIO_EXTRA_CLASSPATH}x" != "x" ]; then
  DREMIO_CLASSPATH="$DREMIO_CLASSPATH:$DREMIO_EXTRA_CLASSPATH"
fi

#
# Shared java options
#
DREMIO_JAVA_OPTS="-Djava.util.logging.config.class=org.slf4j.bridge.SLF4JBridgeHandler"

# Set the default path for native hadoop lib
DREMIO_JAVA_OPTS="$DREMIO_JAVA_OPTS -Djava.library.path=${DREMIO_HOME}/lib"

# Test for cygwin
is_cygwin=false
case "`uname`" in
CYGWIN*) is_cygwin=true;;
esac

# Test for or find JAVA_HOME
if [ -z "$JAVA_HOME" ]; then
  if [ -e "`which java`" ]; then
    SOURCE="`which java`"
    while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
      DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
      SOURCE="$(readlink "$SOURCE")"
      [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
    done
    JAVA_HOME="$( cd -P "$( dirname "$SOURCE" )" && cd .. && pwd )"
  fi
  # if we didn't set it
  if [ -z "$JAVA_HOME" ]; then
    cat 1>&2 <<EOF
+======================================================================+
|      Error: JAVA_HOME is not set and Java could not be found         |
+----------------------------------------------------------------------+
| Dremio requires Java 1.8 or later.                                   |
+======================================================================+
EOF
    exit 1
  fi
fi
# Now, verify that 'java' binary exists and is suitable for Dremio.
if $is_cygwin; then
  JAVA_BIN="java.exe"
else
  JAVA_BIN="java"
fi

if [ -z "$JAVA" ]; then
  JAVA="${JAVA_HOME}/bin/${JAVA_BIN}"
  if [ ! -f "${JAVA}" ]; then
    JAVA=`find -L "$JAVA_HOME" -name "$JAVA_BIN" -type f | head -n 1`
  fi
fi
if [ ! -x "$JAVA" ]; then
  echo "Java not found or Java binary not executable at JAVA_HOME=$JAVA_HOME/JAVA=$JAVA."
  exit 1
fi
# Ensure that Java version is at least 1.8
JAVA_VERSION_STRING=`"$JAVA" -version 2>&1 | grep "version" | sed 's/.*"\(.*\)".*/\1/g'`
JAVA_MAJOR_VERSION=
if `echo $JAVA_VERSION_STRING | egrep -q -e "^1\.[0-9]{1,}\."`; then
    JAVA_MAJOR_VERSION=`echo $JAVA_VERSION_STRING | sed 's/^1\.\([0-9]\{1,\}\)\..*/\1/g'`
elif `echo $JAVA_VERSION_STRING | egrep -q -e "^[0-9]{1,}\."`; then
    JAVA_MAJOR_VERSION=`echo $JAVA_VERSION_STRING | sed 's/^\([0-9]\{1,\}\)\..*/\1/g'`
else
    echo "Cannot parse java version: ${JAVA_VERSION_STRING}"
    exit 1
fi

if [ $JAVA_MAJOR_VERSION -lt 8 ]; then
  echo "Java 1.8 or later is required to run Dremio."
  exit 1
fi

# Adjust paths for CYGWIN
if $is_cygwin; then
  DREMIO_HOME=`cygpath -w "$DREMIO_HOME"`
  DREMIO_CONF_DIR=`cygpath -w "$DREMIO_CONF_DIR"`
  DREMIO_LOG_DIR=`cygpath -w "$DREMIO_LOG_DIR"`
  DREMIO_CLASSPATH=`cygpath -w -p "$DREMIO_CLASSPATH"`
  if [ -z "$HADOOP_HOME" ]; then
    HADOOP_HOME=${DREMIO_HOME}/winutils
  fi
fi

export DREMIO_HOME # needed for the HOCON commands below

# Set proper memory values based on user configured values
if [[ -n $DREMIO_MAX_MEMORY_SIZE_MB ]]
then
  DEFAULT_MAX_HEAP_MEMORY_EXECUTOR_MB=4096
  if [ 32768 -le $DREMIO_MAX_MEMORY_SIZE_MB ]; then
    DEFAULT_MAX_HEAP_MEMORY_EXECUTOR_MB=8192
  fi
  ROLES=`$JAVA -cp "$DREMIO_CLASSPATH" -Ddremio.log.path=${DREMIO_LOG_DIR} com.dremio.dac.daemon.GetRolesCommand`
  if ( echo $ROLES | grep -q "executor" ); then
    DREMIO_MAX_HEAP_MEMORY_SIZE_MB=${DREMIO_MAX_HEAP_MEMORY_SIZE_MB:-$DEFAULT_MAX_HEAP_MEMORY_EXECUTOR_MB}
    DREMIO_MAX_DIRECT_MEMORY_SIZE_MB=${DREMIO_MAX_DIRECT_MEMORY_SIZE_MB:-$((DREMIO_MAX_MEMORY_SIZE_MB-DREMIO_MAX_HEAP_MEMORY_SIZE_MB))}
  else
    DREMIO_MAX_DIRECT_MEMORY_SIZE_MB=${DREMIO_MAX_DIRECT_MEMORY_SIZE_MB:-2048}
    DREMIO_MAX_HEAP_MEMORY_SIZE_MB=${DREMIO_MAX_HEAP_MEMORY_SIZE_MB:-$((DREMIO_MAX_MEMORY_SIZE_MB-DREMIO_MAX_DIRECT_MEMORY_SIZE_MB))}
  fi
else
  DREMIO_MAX_HEAP_MEMORY_SIZE_MB=${DREMIO_MAX_HEAP_MEMORY_SIZE_MB:-4096}
  DREMIO_MAX_DIRECT_MEMORY_SIZE_MB=${DREMIO_MAX_DIRECT_MEMORY_SIZE_MB:-8192}
fi

# make sure allocator chunks are done as mmap'd memory (and reduce arena overhead)
# Newer versions of glibc use an arena memory allocator that causes virtual
# memory usage to explode. Tune the variable down to prevent vmem explosion.
export MALLOC_ARENA_MAX=${MALLOC_ARENA_MAX:-4}
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

# Variables exported from this script
export JAVA_VERSION_STRING
export JAVA_MAJOR_VERSION
export HADOOP_HOME
export is_cygwin
export DREMIO_JAVA_OPTS
export DREMIO_CONF_DIR
export DREMIO_LOG_DIR
export DREMIO_CLASSPATH
export DREMIO_MAX_HEAP_MEMORY_SIZE_MB
export DREMIO_MAX_DIRECT_MEMORY_SIZE_MB
