#!/bin/bash
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://workshop.perforce.com/view/p4-sdp/main/LICENSE
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Version ID Block. Relies on +k filetype modifier.
# VersionID='$Id: //p4-sdp/main/Server/Unix/p4/common/bin/edge_dump.sh#1 $ $Change: 33433 $'

# This script is designed to create a seed checkpoint for an Edge server.
#
# An edge server is naturally filtered, with certain database tables (e.g.
# db.have) excluded.  In addition to implicit filtering, the server spec may
# specify additional tables to be excluded, e.g. by using the
# ArchiveDataFilter field of the server spec.
#
# The script requires the SDP instance and the edge ServerID.

# Run example:
#  ./edge_dump.sh 1 p4d_edge_syd

set -u

declare SDPRoot="${SDP_ROOT:-/p4}"
declare SDPCommon="${SDPRoot}/common"
declare SDPCommonBin="${SDPCommon}/bin"
declare SDPCommonLib="${SDPCommon}/lib"
declare EdgeSeedCheckpoint=
declare ExcludedTables=
declare DumpCmd=
declare LogLink=
declare -i ErrorCount=0
declare -i Threads=4

#==============================================================================
# SDP Library Functions

if [[ -d "$SDPCommonLib" ]]; then
   # shellcheck disable=SC1090 disable=SC1091
   source "$SDPCommonLib/logging.lib" ||\
      bail "Failed to load bash lib [$SDPCommonLib/logging.lib]. Aborting."
fi

#==============================================================================
# Local Functions

function msg () { echo -e "$*"; }
function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; }
function bail () { errmsg "${1:-Unknown Error}"; exit "${2:-1}"; }

function usage () {
   local style=${1:--h}
   local usageErrorMessage=${2:-}

   [[ -n "$usageErrorMessage" ]] && msg "\\n\\nUsage Error:\\n\\n$usageErrorMessage\\n\\n"

   msg "Usage:\n\t${0##*/} <SDP_Instance> <ServerID>\n"

   [[ "$style" == -man ]] || exit 2

   exit 2
}

#==============================================================================
# Command Line Validation

[[ $# -ne 2 || ${1:-Unset} == -h ]] && usage 

export SDP_INSTANCE=${SDP_INSTANCE:-Undefined}
export SDP_INSTANCE=${1:-$SDP_INSTANCE}
if [[ $SDP_INSTANCE == Undefined ]]; then
   usage -h "Instance parameter not supplied."
fi

declare ServerID=${2:-Unset}
if [[ $ServerID == Unset ]]; then
   echo -e "Usage Error: ServerID parameter not supplied."
   usage
fi

#shellcheck disable=SC1091
source "$SDPCommonBin/p4_vars" "$SDP_INSTANCE"
#shellcheck disable=SC1091
source "$SDPCommonBin/backup_functions.sh"
#shellcheck disable=SC1091
source "$SDPCommonBin/edge_vars"

export LOGFILE
LOGFILE="$LOGS/edge_dump.$(date +'%Y-%m-%d-%H%M%S').log"

# The LogLink symlink has no timestamp. It points to the most recent log file.
LogLink="$LOGS/edge_dump.log"

######### Start of Script ##########

if [[ -e "$LogLink" ]]; then
   if [[ -L "$LogLink" ]]; then
      rm -f "$LogLink"
   else
      # If the name that should be a symlink is not a symlink, move it aside before
      # creating the symlink.
      OldLogTimestamp=$(get_old_log_timestamp "$LogLink")
      mv -f "$LogLink" "${LogLink%.log}.${OldLogTimestamp}.log"
   fi
fi

# Point LogLink symlink to current log. Use a subshell so the 'cd' doesn't persist.
( cd "$LOGS" && ln -s "${LOGFILE##*/}" "${LogLink##*/}"; )

echo "Processing. This may take a while depending on checkpoint duration."
echo "Log file is: $LOGFILE"

check_vars
set_vars
check_offline_db_usable
get_offline_journal_num

if [[ "$(is_edge "$ServerID" "$OFFLINE_DB")" == YES ]]; then
   log "Verified: Server $ServerID is an edge server."
else
   die "Could not confirm that $ServerID is an edge server. If you have just created the edge replica spec, please use rotate_journal.sh to update the offline_db and run this script again."
fi

[[ -n "$ExcludedTables" ]] ||\
   die "Value for \$ExcludedTables not defined in $P4CBIN/edge_vars."

EdgeSeedCheckpoint="${CHECKPOINTS}/${P4SERVER}.${ServerID#p4d_}.seed.$OFFLINEJNLNUM"

if [[ -f "${EdgeSeedCheckpoint}" ]]; then
   die "${EdgeSeedCheckpoint} already exists."
fi

ckp_running

# shellcheck disable=SC2072
if [[ -n "${DO_PARALLEL_CHECKPOINTS:-}" && "$DO_PARALLEL_CHECKPOINTS" != "0" && "$P4D_VERSION" > "2022.2" ]]; then
   if [[ "$DO_PARALLEL_CHECKPOINTS" =~ ^[1-9]{1}[0-9]*$ ]]; then
      Threads="$DO_PARALLEL_CHECKPOINTS"
   else
      Threads=4
   fi
   DumpCmd="$P4DBIN -r $OFFLINE_DB -K $ExcludedTables -P $ServerID -N $Threads -jdp -z $EdgeSeedCheckpoint"
else
   DumpCmd="$P4DBIN -r $OFFLINE_DB -K $ExcludedTables -P $ServerID -jd -z ${EdgeSeedCheckpoint}.gz"
fi

log "Create edge seed checkpoint from master offline_db skipping edge-local tables and using the edge server form for any filtered data."
log "Running: $DumpCmd"
{ time $DumpCmd ; } >> "$LOGFILE" 2>&1 || { die "Edge seed checkpoint dump failed!"; }

log "Edge seed checkpoint complete."

# Inform the user about follow up tasks
log "You now need to copy $EdgeSeedCheckpoint to the edge server. If seeding a new edge server, use $SDPCommonBin/load_checkpoint.sh on the remote machine to load the checkpont.  If reseeding an existing edge server, use $SDPCommonBin/recover_edge.sh."

log "End $P4SERVER Edge Dump for ServerID $ServerID"

ckp_complete

cat "$LOGFILE"
