#!/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/r26.1.0/Server/Unix/p4/common/bin/edge_dump.sh#1 $ $Change: 33565 $'
# 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"
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 33565 | Claude (AI Agent by Anthropic) | Initial population of r26.1.0 from main. | ||
| //p4-sdp/main/Server/Unix/p4/common/bin/edge_dump.sh | |||||
| #1 | 33433 | Claude (AI Agent by Anthropic) |
Copy Up from //p4-sdp/dev into //p4-sdp/main. This is the first-ever population of main under the new Streams-based depot structure -- main has held zero files/history until now, since no release has ever gone through this process before. 463 files, covering the entire 2026.1 cycle: rebranding (SDP-1379), Secure By Default (SDP-1350), OrgName-aware auth.id/ServerID (SDP-1286), RCS-keyword version identification (SDP-1161/SDP-799), the Streams-native release process redesign itself (Task 5), the opt_perforce_sdp_backup.sh false-error fix, the P4D 2026.1 test-suite targeting, refreshed P4*.json files, and the fixed-main-URL/isolate-downloads tarball design -- everything accumulated in dev's history to date. Isolated paths (ai_dev_support/, Version, doc/*.html, doc/*.pdf, doc/gen/*.man.txt, doc/gen/sdp_install.cfg, Unsupported/doc/*.html, Unsupported/doc/*.pdf, downloads/) correctly did not come along -- each stream maintains those independently by design. Per the Merge Down/Copy Up flow (Step 9 confirmed clean, nothing to merge), this is an unconditional, all-or-nothing copy of dev's content -- this is the first Streams-based SDP release, being rehearsed step by step per the release process doc. Agent: Claude Code, Model: Claude Sonnet 5 (claude-sonnet-5), operating as bot_Claude_Anthropic. |
||
| //p4-sdp/dev/Server/Unix/p4/common/bin/edge_dump.sh | |||||
| #6 | 33409 | Claude (AI Agent by Anthropic) |
Copy Up from //p4-sdp/dev_rebrand into //p4-sdp/dev. This is the first promotion of dev_rebrand's work into dev since dev_rebrand was created (2025-05-24) -- 303 files, covering the entire 2026.1 rebranding effort (SDP-1379), the Secure By Default adaptation (SDP-1350), OrgName-aware auth.id/ServerID (SDP-1286), RCS-keyword version identification (SDP-1161/SDP-799), and the Streams-native release process redesign (Task 5) done this session, plus everything else accumulated in dev_rebrand's history before this session. Per the Merge Down/Copy Up flow, this is intentionally a full, unconditional blast-replace of dev's content from dev_rebrand -- all selectivity/care happened in the preceding Merge Down (dev -> dev_rebrand, changes 33407-33408), which absorbed Robert Cowham's independent dev-side work first so nothing of his is lost by this Copy Up. Two files are worth calling out since they might look alarming in isolation: - tools/mdcu.sh is deleted -- intentional, retired this session in favor of the two direct Streams commands now documented in doc/ReleaseProcessOverview.md. - tools/ReleaseProcessOverview.md is deleted -- this is a stale relic of a file move dev_rebrand made back in 2025-05-24 (tools/ -> doc/) that was never previously propagated to dev; the current, fully-rewritten doc/ReleaseProcessOverview.md is added/updated correctly by this same changelist. |
||
| #5 | 32990 | C. Thomas Tyler |
p4 merge -b SDP_Classic_to_Streams p4 resolve -as All files resolved automatically. The "real" merge work comes in the coming Merge Down from dev->dev_rebrand. |
||
| #4 | 32480 | C. Thomas Tyler |
Routine merge for SDP from Classic to Streams, done with: p4 merge -b SDP_Classic_to_Streams p4 resolve -as The automatic-safe resolve handled all files; neither '-am' nor interative resolves were needed. |
||
| #3 | 32459 | Mark Zinthefer | Changed error message in edge_dump to prompt user to run rotate_journal if the offline_db doesn't know about the edge spec yet. | ||
| #2 | 32138 | C. Thomas Tyler | p4 merge -b SDP_Classic_to_Streams && p4 resolve -as && p4 resolve -at //p4-sdp/dev/Server/Unix/p4/common/lib/run.lib | ||
| #1 | 31397 | C. Thomas Tyler | Populate -b SDP_Classic_to_Streams -s //guest/perforce_software/sdp/...@31368. | ||
| //guest/perforce_software/sdp/dev/Server/Unix/p4/common/bin/edge_dump.sh | |||||
| #13 | 30654 | C. Thomas Tyler |
Revised logic replaying checkpoints to select the most recent checkpoint regardless of whether it is parallel or not. This logic now applies consistently across scripts (even some not in this changelist that call functions in backup_functions.sh), such as sync_replica.sh, sync_replica.sh, load_checkpoint.sh, recover_edge.sh, etc. The edge_dump.sh script now creates parallel checkpoints if parallel checkpoints are configured. The load_checkpoint.sh now reliably detects the most recent checkpoint when '-latest' is used reliably, serial or parallel. This script now also finds checkpoints for a standby of an edge. Also fixed bug cleaning up old *.OK files from earlier parallel checkpoints. The recover_edge.sh script similarly detects the latest checkpoint correctly, serial or parallel. This chagne was tested with a new regression test suite that operates in a Battle School Lab environment, allowing for more sophisticated testing of sequences of operations. #review-30655 |
||
| #12 | 30636 | C. Thomas Tyler |
Incrementally improved log handling in edge_dump.sh, recover_edge.sh, and recreate_offline_db.sh, to use the mechanism pioneered in ccheck.sh. This is a precursor to a coming standardation of log handling in SDP. As before, each script creates a log in $LOGS named <script_log>.<timestamp>.log. With this change, symlinks in the LOGS directory are created so that <script_log>.log (.e. sans the timestamp) points to the timestampped log file. So $LOGS/recover_edge.log points to $LOGS/recover_edge.<most_recent_timestamp>.log. Each run of the script creates a new timestamped log, and updates the symlink very early in proccessing. This change is better for users and also simplifies automated testing. #review-30637 |
||
| #11 | 27264 | ashaikh |
Improve error message for edge_dump.sh when seed file already exists When running the edge_dump.sh script, you would get a generic error message if a seed file already existed making you refer to logs to figure out what happened. Current error message: $ /p4/common/bin/edge_dump.sh 1 edge.1 Processing. This may take a while depending on checkpoint duration. Log file is: /p4/1/logs/edge_dump.20210112-0449.log Edge seed checkpoint dump failed! Improved error message: $ /p4/common/bin/edge_dump.sh 1 edge.1 Processing. This may take a while depending on checkpoint duration. Log file is: /p4/1/logs/edge_dump.20210112-0456.log /p4/1/checkpoints/p4_1.edge.1.seed.6.gz already exists. Refer to job SDP-585. Thanks for the contribution! |
||
| #10 | 25949 | C. Thomas Tyler | Fixed typo in variable name. | ||
| #9 | 25938 | C. Thomas Tyler | Fixed bug in safety check. | ||
| #8 | 25920 | C. Thomas Tyler |
Added new 'edge_vars' file to dynamically set list of edge-specific db tables based on current P4D version. Updated edge_dump.sh, recover_edge.sh, and load_checkpoint.sh to use the new edge_vars file. Made edge_dump.sh and recover_edge.sh shellcheck v0.6.0 compliant, along with load_checkpoint.sh. |
||
| #7 | 23297 | C. Thomas Tyler |
Added safety checks to avoid running commands that will certainly fail in upgrade.sh. Generally, /p4/common/bin will be the same on all hosts in a Helix topolgy. However, on any given machine, the /p4/<N>/bin/<EXE>_<N>_init scripts should exist only for executables that run on that machine. This change to upgrade.sh should work on machines even where only a proxy or broker runs. Also, it will not generate errors in cases where there is, say, a p4p_N_bin symlink in /p4/common/bin but no /p4/N/bin/p4p_N_init script, which will a common situation since /p4/common/bin will contain all executables used anywhere, while /p4/N/bin is host-specific. Also made cosmetic fixes and style convergence change. In dump_edge.sh and recover_edge_dump.sh, just fixed cosmetic typos. |
||
| #6 | 23266 | C. Thomas Tyler |
Fixes and Enhancements: * Enabled daily_checkpoint.sh operate on edge servers, to keep /p4/N/offline_db current on those hosts for site-local recovery w/o requiring a site-local replica (though having a site-local replica can still be useful). * Disabled live_checkpoint.sh for edge servers. * More fully support topologies using edge severs, in both geographically distributed and horizaontal scaling "wokspace server" solutions. * Fix broken EDGESERVER value definition. * Modified name of SDP counter that gets set when a checkpoint is taken to incorporate ServerID, so now the counter name will look like lastSDPCheckpoint.master.1, or lastSDPCheckpoint.p4d_edge_sfo, rather than just lastSDPCheckpoint. There will be multiple such counters in a topology that uses edge servers, and/or which takes checkpoints on replicas. * Added comments for all functions. For the master server, journalPrefix remains: /p4/N/checkpoints/p4_N The /p4/N/checkpoints is reserved for writing by the master/commit server only. For non-standby (possibly filtered) replicas and edge serves, journalPrefix is: /p4/N/checkpoints.<ShortServerID>/p4_N.<ShortServerID> Here, ShortServerID is just the ServerID with the 'p4d_' prefix trimmed, since it is redundant in this context. See mkrep.sh, which enshines a ServerID (server spec) naming standard, with values like 'p4d_fr_bos' (forwarding replica in Boston) and p4d_edge_blr (Edge server in Bangalore). So the journalPrefix for the p4d_edge_bos replica would be: /p4/N/checkpoints.edge_bos/p4_N.edge_bos For "standby" (aka journalcopy) replicas, journalPrefix is set to /p4/N/journals.rep. which is written to the $LOGS volume, due to the nature of standby replicas using journalPrefix to write active server logs to pre-rotated journals. Some take-away to be updated in docs: * The /p4/N/checkpoints folder must be reserved for checkpoints that originate on the master. It should be safe to rsync this folder (with --delete if desired) to any replica or edge server. This is consistent with the current SDP. * I want to change 'journals.rep' to 'checkpoints.<ShortServerID>' for non-standby replicas, to ensure that checkpoints and journals taken on those hosts are written to a volume where they are backed up. * In sites with multiple edge serves, some sharing achive files ('workspace servers'), multiple edge servers will share the same SAN. So we one checkpoints dir per ServerID, and we want that dir to be on the /hxdepots volume. Note that the journalPrefix for replicas was a fixed /p4/N/journals.rep. This was on the /hxlogs volume - a presumably fast-for-writes volume, but typically NOT backed up and not very large. This change puts it under /p4/N/checkpoints.* for edge servers and non-standby replicas, but ensures other replica types and edge servers can generate checkpoints to a location that is backed up and has plenty of storage capacity. For standby replicas only (which cannot be filtered), the journalPrefix remains /p4/N/journals.rep on the /hxlogs volume. |
||
| #5 | 22752 | Russell C. Jackson (Rusty) | Corrected comments about -K flag. | ||
| #4 | 22720 | Robert Cowham | Fix script to create a filtered checkpoint for edge server. | ||
| #3 | 22617 | Russell C. Jackson (Rusty) | Added +x | ||
| #2 | 22615 | Russell C. Jackson (Rusty) |
Added suggested comments. By passing review since this is a comment only change. |
||
| #1 | 22614 | Russell C. Jackson (Rusty) |
New script to create a filtered checkpoint to use to rebuild an edge server. This is not required unless you are filtering data via the server spec. If you are not doing that, then you can reseed the edge using the latest checkpoint of the master. |
||