#!/bin/bash
#------------------------------------------------------------------------------
set -u
#------------------------------------------------------------------------------
# Sample Usage:
# As perforce:
# source /p4/common/bin/p4_vars N ### Replace 'N' with SDP instance, .e.g. 1.
# cd /p4/common/site/bin
# nohup ./p4d_xx.sh < /dev/null > $LOGS/p4d_xx.$(date +'%Y-%m-%d-%H%M').log 2>&1 &
# This script will do a 'p4d -xx' in the offline_db, so as not to disrupt users.
# It will then replay the generated jnl.fix patch file into P4ROOT.
# WARNINGS:
# * This should be run at a time where it will not collide with checkpoint
# operations, e.g. daily calls to daily_checkpoint.sh.
# * This assumes a recent jnl.fix has already been reviewed by Perforce Support,
# and thus the risk of replaying a just-now generated jnl.fix is mitigated.
# Alternately, if this is run in a sandbox environment, the risk is also
# mitigated.
#------------------------------------------------------------------------------
declare ThisScript=${0##*/}
declare ThisUser=
declare Version=1.3.4
declare -i ErrorCount=0
declare -i NoOp=${DEBUG:-0}
declare JournalFixFile=
declare SDPInstance=${SDP_INSTANCE:-1}
function msg () { echo -e "$*"; }
function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; }
function bail () { errmsg "${1:-Unknown Error}"; exit "${2:-1}"; }
function cmd () {
local cmdAndArgs="${1:-echo}"
local desc="${2:-}"
local -i exitCode=0
[[ -n "$desc" ]] && msg "$desc"
msg "Executing: $cmdAndArgs"
if [[ "$NoOp" -eq 0 ]]; then
eval "$cmdAndArgs"
exitCode=$?
else
msg "NO_OP: Would run: $cmdAndArgs"
fi
return $exitCode
}
# shellcheck disable=SC1091
source /p4/common/bin/p4_vars "${SDPInstance}" ||\
bail "Could not do: source /p4/common/bin/p4_vars \"${SDPInstance}\""
ThisUser=$(id -u -n)
msg "Starting $ThisScript v$Version as $ThisUser@${HOSTNAME%%.*} on $(date)."
if [[ "$NoOp" -eq 0 ]]; then
msg "\\nThis script is operation in Live Operation mode.\\n"
else
msg "\\nThis script is operation in DRY RUN mode.\\n"
fi
JournalFixFile="/p4/$SDPInstance/offline_db/jnl.fix"
[[ -r "$JournalFixFile" ]] && \
bail "The journal fix file to be generated already exists: $JournalFixFile\\nAborting"
if cmd "p4d -r /p4/$SDPInstance/offline_db -xx" \
"Doing deep data scan, generating $JournalFixFile"; then
msg "The p4d -xx check found no errors. We are done here."
if [[ -f "$JournalFixFile" && ! -s "$JournalFixFile" ]]; then
cmd "rm -f $JournalFixFile" \
"Removing zero-length generaetd jnl.fix file."
errmsg "Error removing zero-length jnl.fix file."
fi
msg "That took $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\\n"
exit 0
else
msg "Inconsistencies detected. Proceeding to replay the generated jnl.fix file."
fi
msg "The generated file is:\\n=== BEGIN GENERATEE FILE ==="
if [[ "$NoOp" -eq 0 ]]; then
cat "$JournalFixFile"
else
msg "@Sample@ @Journal@ @Data@"
fi
msg "=== END GENERATEE FILE ==="
if cmd "p4d -r $P4ROOT -s -jr $JournalFixFile" \
"Replaying generated journal patch to P4ROOT"; then
msg "Replayed journal patch successfully"
cmd "mv $JournalFixFile ${JournalFixFile}.processed.$(date +'%Y-%m-%d-%H%M')" \
"Moved replayed jnl.fix file aside." ||\
errmsg "Error moving replayed jnl.fix aside."
cmd "$P4CBIN/rotate_journal.sh $SDPInstance" \
"Performing journal rotation and replay to offline_db." ||\
errmsg "Journal rotation failed."
else
errmsg "Failed to replay journal patch jnl.fix into P4ROOT."
cmd "mv $JournalFixFile ${JournalFixFile}.replay_failed.$(date +'%Y-%m-%d-%H%M')" \
"Moved jnl.fix file that failed to replay aside." ||\
errmsg "Error moving aside jnl.fix that faield to replay."
fi
msg "That took $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\\n"
exit "$ErrorCount"