#!/bin/bash
#------------------------------------------------------------------------------
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
#------------------------------------------------------------------------------
# This is a reference edge-content trigger for use with an Edge/Commit server topology - the 
# Edge server uses this trigger to transmit files which are being submitted to the Commit instead
# of using its normal file transfer mechanism.
# This trigger uses Aspera for fast file transfer, and UDP, rather than TCP and is typically 
# much faster, especially with high latency connections.
# See: https://community.perforce.com/s/article/15337
#------------------------------------------------------------------------------
# 'fstat -Ob' with some filtering generates a list of files to be copied.
# Create a temp file with the filename pairs expected by ascp, and
# then perform the copy.
#
# This configurable must be set:
# rpl.submit.nocopy=1
#
# The edge-content trigger looks like this:
#
#   EdgeSubmit edge-content //... "/p4/common/bin/triggers/ascpSubmit.sh %changelist%"
#
# The ascp user needs to have ssl public keys set up or export ASPERA_SCP_PASS.
# The ascp user should be set up with the target as / with full write access to the volume where
# the depot files are located. The easiest way to do that is to use the same user that is
# running the p4d service.
#
# WARNING - ensure ascp is correctly configured and working in your environment:
# https://www-01.ibm.com/support/docview.wss?uid=ibm10747281
# (search for "ascp connectivity testing")
#
# Standard SDP environment is assumed, e.g P4USER, P4PORT, OSUSER, P4BIN, etc.
# are set, PATH is appropriate, and a super user is logged in with a non-expiring
# ticket.

set -u

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

[[ $# -eq 1 ]] || bail "Bad Usage!\n\nUsage:\n\t$0 %changelist%\n\n"

change=$1

#------------------------------------------------------------------------------
# Set this value appropriately, or to ensure it is not accidentally checked in,
# set it in the appropriate SDP file, e.g. /p4/common/config/p4_1.vars
export ASPERA_SCP_PASS=xxxx

LOGFILE=$LOGS/submit.log

declare tmpDir=$P4TMP
declare tmpFile="$tmpDir/tmpfile.$$.$RANDOM"
declare FilesToTransfer="$tmpDir/FilesToTransfer.$$.$RANDOM"
declare -i cnt=0

if [[ ! -d "$tmpDir" ]]; then
   mkdir -p "$tmpDir" || bail "Failed to create temp dir [$tmpDir]."
fi

$P4BIN fstat -e $change -Rs -Ob -F lbrIsLazy=0 -T lbrPath @=$change > $FilesToTransfer 2>&1 ||\
   bail "$0: Non-zero exit code from fstat of change $change."

date=$(date '+%Y-%m-%d %H:%M:%S')
echo "$date $FilesToTransfer" >> $LOGFILE

# Record size summary
$P4BIN sizes -sh @=$change >> $LOGFILE

# Exit happily if the FilesToTransfer file is empty, meaning there are no
# library files reported by the fstat to transfer for that change, e.g.
# if there are only lazy copies.
[[ ! -s $FilesToTransfer ]] && exit 0

while read file; do
   if [[ $file =~ lbrPath ]]; then
      file=${file##*\.\.\. lbrPath }
      echo $file >> $tmpFile
      echo $file >> $tmpFile
      cnt+=1
   fi
done < $FilesToTransfer

if [[ $cnt -eq 0 ]]; then
   exit 0
fi

# See above for checking ascp connectivity when tyring to get the following correctly configured.

# Note: the -l parameter should be adjusted to how much bandwidth you want Aspera to use
# in your environment.
echo Running: ascp -P 33001 -l 500M -d --mode=send --file-pair-list=$tmpFile --user=$OSUSER --host=$P4MASTER / >> $LOGFILE 2>&1
ascp -P 33001 -l 500M -d --mode=send --file-pair-list=$tmpFile --user=$OSUSER --host=$P4MASTER / >> $LOGFILE 2>&1

if [[ $? -ne 0 ]]; then
  bail "$0: failed to execute the ascp command, contact Perforce admin.\n"
fi

date=$(date '+%Y-%m-%d %H:%M:%S')
echo "$date transfer completed" >> $LOGFILE

rm -f "$tmpFile"
rm -f "$FilesToTransfer"

exit 0
