#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

EXPECTED_HOSTNAME=sqjcredis01
EXPECTED_IPV4=10.2.203.112
ACTION=${1:---check}
RUN_ID=${2:-}
SYSCTL_FILE=/etc/sysctl.d/99-zhct-redis.conf
THP_UNIT=/etc/systemd/system/zhct-redis-thp.service

die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
[[ "${EUID}" -eq 0 ]] || die 'must run as root'
[[ "$(hostname -s)" == "${EXPECTED_HOSTNAME}" ]] || die 'hostname mismatch'
ip -o -4 addr show scope global | awk '{print $4}' | cut -d/ -f1 |
  grep -Fxq "${EXPECTED_IPV4}" || die 'expected IPv4 is not configured'

check_values() {
  [[ "$(sysctl -n vm.overcommit_memory)" == 1 ]] || die 'vm.overcommit_memory is not 1'
  grep -Fq '[never]' /sys/kernel/mm/transparent_hugepage/enabled ||
    die 'transparent hugepage is not disabled'
  printf 'REDIS01_SYSTEM_PARAMS_OK\n'
}

case "${ACTION}" in
  --check)
    check_values
    ;;
  --apply)
    [[ "${RUN_ID}" =~ ^q070-[0-9]{8}T[0-9]{6}[+]0800$ ]] || die 'invalid Q070 baseline run id'
    BASELINE_DIR="/var/backups/zhct-q070/evidence/${RUN_ID}"
    [[ -s "${BASELINE_DIR}/baseline-result.env" ]] ||
      die 'matching Q070 baseline result is missing'
    grep -Fxq 'baseline=PASS' "${BASELINE_DIR}/baseline-result.env" ||
      die 'matching Q070 baseline is not PASS'
    install -d -m 0755 /etc/sysctl.d /etc/systemd/system
    printf 'vm.overcommit_memory = 1\n' >"${SYSCTL_FILE}"
    chmod 0644 "${SYSCTL_FILE}"
    {
      printf '%s\n' '[Unit]'
      printf '%s\n' 'Description=Disable Transparent Huge Pages for ZHCT Redis'
      printf '%s\n' 'After=sysinit.target local-fs.target'
      printf '%s\n' 'Before=redis5.service redis7.service sentinel5.service sentinel7.service'
      printf '\n%s\n' '[Service]'
      printf '%s\n' 'Type=oneshot'
      printf '%s\n' 'ExecStart=/bin/sh -c '\''echo never > /sys/kernel/mm/transparent_hugepage/enabled'\'
      printf '%s\n' 'RemainAfterExit=yes'
      printf '\n%s\n' '[Install]'
      printf '%s\n' 'WantedBy=multi-user.target'
    } >"${THP_UNIT}"
    chmod 0644 "${THP_UNIT}"
    sysctl --system >/dev/null
    systemctl daemon-reload
    systemctl enable --now zhct-redis-thp.service
    check_values
    ;;
  --rollback)
    [[ "${RUN_ID}" =~ ^q070-[0-9]{8}T[0-9]{6}[+]0800$ ]] || die 'invalid Q070 run id'
    EVIDENCE_DIR="/var/backups/zhct-q070/evidence/${RUN_ID}"
    FILES_DIR="/var/backups/zhct-q070/files/${RUN_ID}"
    [[ -s "${EVIDENCE_DIR}/baseline-result.env" ]] || die 'baseline result is missing'
    systemctl disable --now zhct-redis-thp.service >/dev/null 2>&1 || true
    for path in "${SYSCTL_FILE}" "${THP_UNIT}"; do
      state=$(awk -F'\t' -v p="${path}" '$1 == p {print $2}' "${EVIDENCE_DIR}/path-state-before.tsv")
      case "${state}" in
        PRESENT)
          source_path="${FILES_DIR}/${path#/}"
          [[ -e "${source_path}" || -L "${source_path}" ]] || die "backup missing: ${path}"
          rm -rf "${path}"
          cp -a "${source_path}" "${path}"
          ;;
        ABSENT) rm -f "${path}" ;;
        *) die "unknown baseline state: ${path}" ;;
      esac
    done
    old_overcommit=$(awk -F'\t' '$1 == "vm.overcommit_memory" {print $2}' \
      "${EVIDENCE_DIR}/sysctl-state-before.tsv")
    [[ "${old_overcommit}" =~ ^[012]$ ]] || die 'invalid baseline overcommit value'
    sysctl -w "vm.overcommit_memory=${old_overcommit}" >/dev/null
    old_thp=$(sed -n 's/.*\\[\\([^]]*\\)\\].*/\\1/p' "${EVIDENCE_DIR}/thp-enabled-before.txt")
    case "${old_thp}" in always|madvise|never) ;; *) die 'invalid baseline THP selector' ;; esac
    printf '%s\n' "${old_thp}" >/sys/kernel/mm/transparent_hugepage/enabled
    systemctl daemon-reload
    printf 'REDIS01_SYSTEM_PARAMS_ROLLBACK_OK\n'
    ;;
  *) die 'usage: redis01-system-params.sh --check | --apply Q070-RUN-ID | --rollback Q070-RUN-ID' ;;
esac
