#!/bin/bash
set -e

die () {
    echo "$@" >&2
    exit 1
}

die-pause () {
    echo "$@" >&2
    sleep 60
    exit 1
}

JAVA_MAIN=ru.yandex.direct.mysql.RunM2Yt

VERSION=`cat /var/www/direct-mysql-yt-sync/version`

CLUSTER="$1"
if [ -z "$CLUSTER" ]; then
    if [ -f /etc/direct/binlog-to-yt-sync/cluster.name ]; then
        CLUSTER=$(cat /etc/direct/binlog-to-yt-sync/cluster.name)
    else
        die "Cluster not passed in arguments and /etc/direct/binlog-to-yt-sync/cluster.name not exists"
    fi
fi

if [ -f /etc/direct/binlog-to-yt-sync/mysql.server-id ]; then
    MYSQL_SERVER_ID=$(cat /etc/direct/binlog-to-yt-sync/mysql.server-id)
else
    die "Required file /etc/direct/binlog-to-yt-sync/mysql.server-id does not exist"
fi

if [ -f /etc/direct/binlog-to-yt-sync/sync-path.version ]; then
        SYNC_PATH_OVERRIDE="-Dyt-sync.path.version="$(cat /etc/direct/binlog-to-yt-sync/sync-path.version)
    else
        SYNC_PATH_OVERRIDE=""
fi

# в /etc/direct/binlog-to-yt-sync/db.names ожидается список БД вида "ppc:1", разделенных запятой
if [ -f /etc/direct/binlog-to-yt-sync/db.names ]; then
        DB_NAMES=$(cat /etc/direct/binlog-to-yt-sync/db.names)
        JAVA_EXTRA_OPTIONS="$JAVA_EXTRA_OPTIONS -Dyt-sync.db-names-comma-separated=$DB_NAMES"
else
        die "Required file /etc/direct/binlog-to-yt-sync/db.names does not exist"
fi

# Daily snapshot configuration
DAILY_SNAPSHOTS_ENABLED=""
DAILY_SNAPSHOTS_FROM=""
DAILY_SNAPSHOTS_TO=""
DAILY_SNAPSHOTS_ENABLE_ON_PRESTABLE=""
if [ -f /etc/direct/binlog-to-yt-sync/daily-snapshots.enabled ]; then
    DAILY_SNAPSHOTS_ENABLED="-Dyt-sync.${CLUSTER}.daily-snapshots.enabled=true"
fi
if [ -f /etc/direct/binlog-to-yt-sync/daily-snapshots.from ]; then
    DAILY_SNAPSHOTS_FROM="-Dyt-sync.${CLUSTER}.daily-snapshots.interval-from=$(cat /etc/direct/binlog-to-yt-sync/daily-snapshots.from)"
fi
if [ -f /etc/direct/binlog-to-yt-sync/daily-snapshots.to ]; then
    DAILY_SNAPSHOTS_TO="-Dyt-sync.${CLUSTER}.daily-snapshots.interval-to=$(cat /etc/direct/binlog-to-yt-sync/daily-snapshots.to)"
fi
if [ -f /etc/direct/binlog-to-yt-sync/daily-snapshots.enabled-on-prestable ]; then
    DAILY_SNAPSHOTS_ENABLE_ON_PRESTABLE="-Dyt-sync.${CLUSTER}.daily-snapshots.enabled-on-prestable=true"
fi

VERIFY_CHECKSUMS=""
if [ -f /etc/direct/binlog-to-yt-sync/verify-checksums.enabled ]; then
    VERIFY_CHECKSUMS="-Dyt-sync.${CLUSTER}.verify-checksums=true"
fi

if [ -f /etc/direct/binlog-to-yt-sync/java.yt-sync-import-threads ]; then
        JAVA_EXTRA_OPTIONS="$JAVA_EXTRA_OPTIONS -Dyt-sync.import.threads=$(cat /etc/direct/binlog-to-yt-sync/java.yt-sync-import-threads)"
fi

MEM_LIMIT="64g"

if [ -f /etc/direct/binlog-to-yt-sync/java.mem_limit ]; then
        MEM_LIMIT=$(cat /etc/direct/binlog-to-yt-sync/java.mem_limit)
fi

# Здесь важно не добавлять в двойных кавычках переменные, которые могут оказаться пустыми
# потому что в этом случае они превратятся в серию аргументов-пустых строк вида '' '' ''
# и джава решит, что main-class приложения -- это пустая строка
CONFIG_OVERRIDES=(
    -Dyt-sync.cluster="${CLUSTER}"
    -Dyt-sync.mysql-server-id="${MYSQL_SERVER_ID}"
    ${DAILY_SNAPSHOTS_ENABLED}
    ${DAILY_SNAPSHOTS_FROM}
    ${DAILY_SNAPSHOTS_TO}
    ${DAILY_SNAPSHOTS_ENABLE_ON_PRESTABLE}
    ${VERIFY_CHECKSUMS}
)

if [ -z "$JAVA" ]; then
    JAVA=/usr/local/yandex-direct-jdk11/bin/java
fi
if [ -z "$APPDIR" ]; then
    APPDIR="/var/www/direct-mysql-yt-sync"
fi
if [ -z "$LOGDIR" ]; then
    LOGDIR=/var/log/yandex
fi
if [ -z "$LOCKDIR" ]; then
    LOCKDIR=/var/run/lock
fi

# Make sure only a single instance is running per cluster
LOCKFILE="$LOCKDIR/binlog-to-yt-$CLUSTER.lock"
exec 200>"$LOCKFILE"
flock -n 200 || die-pause "Another instance is already running"

# Roll olded GC logs into per-date files
for log in $LOGDIR/binlog-to-yt-$CLUSTER.gc.????????.??????.*; do
    if [ -f "$log" ]; then
        cat "$log" >>"$LOGDIR/binlog-to-yt-$CLUSTER.gc.$(date '+%Y%m%d')"
        rm "$log"
    fi
done

# Configure Java GC
GC_LOGFILE="$LOGDIR/binlog-to-yt-$CLUSTER.gc.$(date '+%Y%m%d.%H%M%S')"
GC_OPTIONS=(
    -Xms$MEM_LIMIT
    -Xmx$MEM_LIMIT
    # Tune G1
    -XX:+UseG1GC
    -XX:+UseStringDeduplication
    -XX:MaxGCPauseMillis=200
    # Enable GC logging
    -verbose:gc
    -verbose:sizes
    -Xlog:gc*=info,safepoint=info,age*=trace:file="${GC_LOGFILE}":time,uptime,level,tags:filecount=100,filesize=100M
    -XX:-UsePerfData
    -XX:-OmitStackTraceInFastThrow
)

JAVA_OPTIONS=(
    -server
    # Лекарство от io.netty.handler.codec.TooLongFrameException: HTTP header is larger than 8192 bytes
    # https://st.yandex-team.ru/DIRECT-96850
    -Dhttp.netty.maxHeaderSize:16384
    # В рамках перехода на JDK 11
    -Djava.util.Arrays.useLegacyMergeSort=true
    -Dfile.encoding="UTF-8"
    -Djava.net.preferIPv4Stack=false
    -Djava.net.preferIPv6Addresses=true
    -Dsun.net.inetaddr.ttl=60
    -Dsun.net.inetaddr.negative.ttl=0
    -DYT_SYNC_LOG_NAME="binlog-to-yt-$CLUSTER"
    "${GC_OPTIONS[@]}"
    "${CONFIG_OVERRIDES[@]}"
    "$SYNC_PATH_OVERRIDE"
    -cp "hotfix/$VERSION/classes/:direct-mysql-yt-sync/*:"
    $JAVA_EXTRA_OPTIONS
)

# Make sure mysqld is in PATH
export PATH="/usr/sbin:$PATH"

# Make sure java has enough virtual memory
ulimit -v unlimited || :

# для запускаемых приложением процессов mysql, чтобы их можно было отследить по содержимому /proc/.../environ
export DIRECT_B2YT_PID="$$"

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting MySQL to Yt synchronization..."

# Redirect stderr to a special logfile
ERROR_LOG="$LOGDIR/binlog-to-yt-sync.error.log"
if [ -f "$ERROR_LOG" ]; then
    TODAY_ERROR_LOG=$ERROR_LOG.$(date +%Y%m%d)
    if [ -f "$TODAY_ERROR_LOG" ]; then
        cat "$ERROR_LOG" >>"$TODAY_ERROR_LOG"
        rm "$ERROR_LOG"
    else
        mv "$ERROR_LOG" "$TODAY_ERROR_LOG"
    fi
fi

cd "$APPDIR"
exec $JAVA "${JAVA_OPTIONS[@]}" "$JAVA_MAIN" >> "$ERROR_LOG" 2>&1
