#!/bin/bash
# Shared weekly-maintenance workspace lifecycle. No shell options are changed.
# Source after p4_vars and logging, then call maintenance_workspace_init.

maintenance_workspace_finish() {
    local rc=$?
    trap - EXIT
    if [[ -n ${SDP_MAINTENANCE_WORKDIR:-} ]]; then
        cd "$MAINT_DIR" || rc=1
        if ! rm -rf -- "$SDP_MAINTENANCE_WORKDIR"; then
            echo "ERROR: Unable to remove maintenance run directory: $SDP_MAINTENANCE_WORKDIR" >&2
            rc=1
        fi
    fi
    exec 9>&-
    if declare -F _sdp_on_exit >/dev/null; then
        _sdp_on_exit "$rc" || :
    fi
    exit "$rc"
}

maintenance_workspace_init() {
    local instance=$1
    local base=${P4TMP:-/p4/$instance/tmp}
    local rc
    mkdir -p "$base" || return $?
    # The lock belongs to this open file description. The Python child and
    # this shell share it, so it remains held until the shell closes fd 9.
    # Kernel release on process exit avoids stale pid-file recovery guesses.
    exec 9>"$base/maintenance.lock" || return $?
    python3 -c 'import fcntl, sys
try:
    fcntl.flock(9, fcntl.LOCK_EX | fcntl.LOCK_NB)
except BlockingIOError:
    sys.exit(75)
' 9>&9
    rc=$?
    if (( rc != 0 )); then
        exec 9>&-
        if (( rc == 75 )); then
            echo "Another maintenance run owns instance $instance; skipping this run."
            declare -F sdp_set_status >/dev/null && sdp_set_status skipped
        else
            echo "ERROR: Unable to acquire the maintenance lock for instance $instance." >&2
        fi
        return "$rc"
    fi
    SDP_MAINTENANCE_WORKDIR=$(mktemp -d "$base/maintenance.XXXXXXXX") || {
        rc=$?
        exec 9>&-
        return "$rc"
    }
    export SDP_MAINTENANCE_WORKDIR
    trap maintenance_workspace_finish EXIT
    cd "$SDP_MAINTENANCE_WORKDIR" || return $?
    echo "Maintenance run directory: $SDP_MAINTENANCE_WORKDIR"
}
