#!/usr/bin/env bash
#
#/**
# * Licensed to the Apache Software Foundation (ASF) under one
# * or more contributor license agreements.  See the NOTICE file
# * distributed with this work for additional information
# * regarding copyright ownership.  The ASF licenses this file
# * to you 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.
# */

set -e

BINDIR=`dirname "$0"`
BK_HOME=`cd ${BINDIR}/..;pwd`

source ${BK_HOME}/bin/common.sh

# default variables
DEFAULT_CONF=${BK_HOME}/conf/bk_server.conf
DEFAULT_ZK_CONF=${BK_HOME}/conf/zookeeper.conf

if [ -z "$BOOKIE_CONF" ]; then
  BOOKIE_CONF_TO_CHECK=${DEFAULT_CONF}
else
  BOOKIE_CONF_TO_CHECK=${BOOKIE_CONF}
fi

FIND_TABLE_SERVICE_RESULT=$(find_table_service ${BOOKIE_CONF_TO_CHECK} $1)

if [ "x${FIND_TABLE_SERVICE_RESULT}" == "xtrue" ]; then
  BOOKIE_MODULE_PATH=stream/server
  BOOKIE_MODULE_NAME=${TABLE_SERVICE_MODULE_NAME}
elif [ "x${FIND_TABLE_SERVICE_RESULT}" == "xfalse" ]; then
  BOOKIE_MODULE_PATH=bookkeeper-server
  BOOKIE_MODULE_NAME=${BOOKIE_SERVER_MODULE_NAME}
else
  echo ${FIND_TABLE_SERVICE_RESULT}
  exit 1
fi

# find the module jar
BOOKIE_JAR=$(find_module_jar ${BOOKIE_MODULE_PATH} ${BOOKIE_MODULE_NAME})

# set up the classpath
BOOKIE_CLASSPATH=$(set_module_classpath ${BOOKIE_MODULE_PATH})

bookkeeper_help() {
    cat <<EOF
Usage: bookkeeper <command>
where command is one of:

[service commands]

    bookie              Run a bookie server
    autorecovery        Run AutoRecovery service daemon
    zookeeper           Run zookeeper server

[development commands]

    localbookie <n>     Run a test ensemble of <n> bookies locally
    standalone          Run a standalone cluster (with all service components) locally

[tooling commands]

    upgrade             Upgrade bookie filesystem
    shell               Run shell for admin commands

[other commands]

    help                This help message

or command is the full name of a class with a defined main() method.

Environment variables:
   BOOKIE_LOG_CONF        Log4j configuration file (default ${DEFAULT_LOG_CONF})
   BOOKIE_CONF            Configuration file (default: ${DEFAULT_CONF})
   BOOKIE_ZK_CONF         Configuration file for zookeeper (default: $DEFAULT_ZK_CONF)
   BOOKIE_EXTRA_OPTS      Extra options to be passed to the jvm
   BOOKIE_EXTRA_CLASSPATH Add extra paths to the bookkeeper classpath
   ENTRY_FORMATTER_CLASS  Entry formatter class to format entries.
   BOOKIE_PID_DIR         Folder where the Bookie server PID file should be stored
   BOOKIE_STOP_TIMEOUT    Wait time before forcefully kill the Bookie server instance, if the stop is not successful

These variable can also be set in conf/bkenv.sh
EOF
}

# if no args specified, show usage
if [ $# = 0 ]; then
  bookkeeper_help;
  exit 1;
fi

# get arguments
COMMAND=$1
shift

LOCALBOOKIES_CONFIG_DIR="${LOCALBOOKIES_CONFIG_DIR:-/tmp/localbookies-config}"
if [ ${COMMAND} == "shell" ]; then
  DEFAULT_LOG_CONF=${BK_HOME}/conf/log4j.shell.properties
  if [[ $1 == "-localbookie"  ]]; then
    if [[ $2 == *:* ]];
    then
      BOOKIE_CONF=${LOCALBOOKIES_CONFIG_DIR}/$2.conf
      shift 2
    else
      BOOKIE_CONF=${LOCALBOOKIES_CONFIG_DIR}/baseconf.conf
      shift
    fi
  fi
fi

if [ -z "$BOOKIE_ZK_CONF" ]; then
    BOOKIE_ZK_CONF=$DEFAULT_ZK_CONF
fi

if [ -z "$BOOKIE_CONF" ]; then
  BOOKIE_CONF=${DEFAULT_CONF}
fi

# Configure logging
if [ -z "$BOOKIE_LOG_CONF" ]; then
  BOOKIE_LOG_CONF=${DEFAULT_LOG_CONF}
fi
BOOKIE_LOG_DIR=${BOOKIE_LOG_DIR:-"$BK_HOME/logs"}
BOOKIE_LOG_FILE=${BOOKIE_LOG_FILE:-"bookkeeper-server.log"}
BOOKIE_ROOT_LOGGER=${BOOKIE_ROOT_LOGGER:-"INFO,CONSOLE"}

# Configure the classpath
BOOKIE_CLASSPATH="$BOOKIE_JAR:$BOOKIE_CLASSPATH:$BOOKIE_EXTRA_CLASSPATH"
BOOKIE_CLASSPATH="`dirname $BOOKIE_LOG_CONF`:$BOOKIE_CLASSPATH"

# Build the OPTS
BOOKIE_OPTS=$(build_bookie_opts)
GC_OPTS=$(build_bookie_jvm_opts ${BOOKIE_LOG_DIR} "gc_%p.log")
NETTY_OPTS=$(build_netty_opts)
LOGGING_OPTS=$(build_logging_opts ${BOOKIE_LOG_CONF} ${BOOKIE_LOG_DIR} ${BOOKIE_LOG_FILE} ${BOOKIE_ROOT_LOGGER})

OPTS="${OPTS} -cp ${BOOKIE_CLASSPATH} ${BOOKIE_OPTS} ${GC_OPTS} ${NETTY_OPTS} ${LOGGING_OPTS} ${BOOKIE_EXTRA_OPTS}"

# Create log dir if it doesn't exist
if [ ! -d ${BOOKIE_LOG_DIR} ]; then
    mkdir ${BOOKIE_LOG_DIR}
fi

#Change to BK_HOME to support relative paths
cd "$BK_HOME"
if [ ${COMMAND} == "bookie" ]; then
  exec ${JAVA} ${OPTS} ${JMX_ARGS} org.apache.bookkeeper.server.Main --conf ${BOOKIE_CONF} $@
elif [ ${COMMAND} == "autorecovery" ]; then
  exec ${JAVA} ${OPTS} ${JMX_ARGS} org.apache.bookkeeper.replication.AutoRecoveryMain --conf ${BOOKIE_CONF} $@
elif [ ${COMMAND} == "localbookie" ]; then
  NUMBER=$1
  shift
  exec ${JAVA} ${OPTS} ${JMX_ARGS} -Dzookeeper.4lw.commands.whitelist='*' org.apache.bookkeeper.util.LocalBookKeeper ${NUMBER} ${BOOKIE_CONF} $@
elif [ ${COMMAND} == "standalone" ]; then
  exec ${JAVA} ${OPTS} ${JMX_ARGS} -Dzookeeper.4lw.commands.whitelist='*' org.apache.bookkeeper.stream.cluster.StandaloneStarter --conf ${BK_HOME}/conf/standalone.conf $@
elif [ ${COMMAND} == "upgrade" ]; then
  exec ${JAVA} ${OPTS} org.apache.bookkeeper.bookie.FileSystemUpgrade --conf ${BOOKIE_CONF} $@
elif [ $COMMAND == "zookeeper" ]; then
    BOOKIE_LOG_FILE=${BOOKIE_LOG_FILE:-"zookeeper.log"}
    exec $JAVA $OPTS -Dbookkeeper.log.file=$BOOKIE_LOG_FILE org.apache.zookeeper.server.quorum.QuorumPeerMain $BOOKIE_ZK_CONF $@
elif [ ${COMMAND} == "shell" ]; then
  ENTRY_FORMATTER_ARG="-DentryFormatterClass=${ENTRY_FORMATTER_CLASS:-org.apache.bookkeeper.util.StringEntryFormatter}"
  exec ${JAVA} ${OPTS} ${ENTRY_FORMATTER_ARG} org.apache.bookkeeper.bookie.BookieShell -conf ${BOOKIE_CONF} $@
elif [ ${COMMAND} == "help" ]; then
  bookkeeper_help;
else
  exec ${JAVA} ${OPTS} ${COMMAND} $@
fi

