# # # The contents of this file are subject to the terms of the Common Development and # Distribution License (the License). You may not use this file except in compliance with the # License. # # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the # specific language governing permission and limitations under the License. # # When distributing Covered Software, include this CDDL Header Notice in each file and include # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL # Header, with the fields enclosed by brackets [] replaced by your own identifying # information: "Portions copyright [year] [name of copyright owner]". # # Copyright 2026 3A Systems, LLC. # What a replication convergence run (#1090) leaves behind, sourced by run.sh: the summary of # every run, and the state of every server of a failed one - what #534 could not get from its # reporter. # The server id each directory server has in the replication domain of BASE_DN, which the # samples name the servers by: "Directory server DS() " (ReplicationMonitor) record_server_ids() { local n for n in $DS_NODES; do admin_search $n "$MONITOR_DOMAIN" one "(objectClass=*)" 1.1 \ | sed -n 's/^dn: cn=Directory server DS(\([0-9]*\)).*/\1/p' | sed "s/\$/ $n/" done >"$OUT/server-ids.txt" # the changelog check looks for the changes of each of them [ "$(wc -l <"$OUT/server-ids.txt")" -eq "$(echo $DS_NODES | wc -w)" ] \ || fail "the server id of a directory server is missing, see server-ids.txt" } # Every server's container log, logs/, config/ and changelogDb, packed into state.tgz; docker cp # reads a stopped or killed container as well. Nothing here may fail the run a second time collect() { local n for n in $ALL_NODES; do docker inspect $n >/dev/null 2>&1 || continue mkdir -p "$OUT/state/$n" docker logs $n >"$OUT/state/$n/container.log" 2>&1 || true docker cp $n:/opt/opendj/data/logs "$OUT/state/$n/" >/dev/null 2>&1 || true docker cp $n:/opt/opendj/data/config "$OUT/state/$n/" >/dev/null 2>&1 || true docker cp $n:/opt/opendj/data/changelogDb "$OUT/state/$n/" >/dev/null 2>&1 || true done [ ! -d "$OUT/state" ] || { tar czf "$OUT/state.tgz" -C "$OUT" state 2>/dev/null && rm -rf "$OUT/state"; } || true } # The summary of the run, into $OUT/summary.md and, in GitHub Actions, the job summary summarize() { # { echo "### Replication convergence ($TOPOLOGY): $1" echo echo "| | |" echo "|---|---|" echo "| servers | $ALL_NODES |" echo "| load | $DURATION s on each directory server, at most $LOAD_MOD_RATE modifications and $LOAD_ADD_RATE adds or deletes a second |" echo "| seeded users | $SAMPLE_DATA |" echo "| converged | ${CONVERGED_IN:--} s after the load |" if [ -s "$OUT/samples.txt" ]; then awk '{ t[$1] = 1 } END { for (s in t) { n++; if (!min || s < min) min = s; if (s > max) max = s } printf "| samples of the monitor | %d, one every %d s |\n", n, (n > 1 ? (max - min) / (n - 1) : 0) }' "$OUT/samples.txt" fi if [ -s "$OUT/samples.txt" ] && [ -s "$OUT/server-ids.txt" ]; then echo echo "Peaks during the load, over every replication server (a restart resets the counters, so these are maxima of the samples, not sums), and the connections to a replication server again after the topology came up, whatever made them:" echo echo "| directory server | peak missing-changes | peak approximate-delay (s) | reconnections |" echo "|---|---|---|---|" awk 'FILENAME == ARGV[1] { reconnections[$1] = $2; next } FILENAME == ARGV[2] { name[$1] = $2; next } ($3 in name) { if ($4 > m[$3]) m[$3] = $4; if ($5 > d[$3]) d[$3] = $5; seen[$3] = 1 } END { for (id in seen) printf "| %s | %d | %d | %s |\n", name[id], m[id], d[id], \ (name[id] in reconnections) ? reconnections[name[id]] : "-" }' \ "$([ -f "$OUT/reconnections.txt" ] && echo "$OUT/reconnections.txt" || echo /dev/null)" \ "$OUT/server-ids.txt" "$OUT/samples.txt" | sort fi if ls "$OUT"/changelog/*.txt >/dev/null 2>&1; then echo echo "Changes of the load missing from the changelog of each replication server (gaps in the sequence numbers of a replica; which ones in changelog/):" echo echo '```' for f in "$OUT"/changelog/*.txt; do grep -E ' [1-9][0-9]* missing$|cannot be read|encrypted|no domain' "$f" | sed "s/^/$(basename "$f" .txt): /" done | grep . || echo "none" echo '```' fi if ls "$OUT"/load/*.csv >/dev/null 2>&1; then echo echo "| client | average ops/s | intervals |" echo "|---|---|---|" for f in "$OUT"/load/*.csv; do awk -F, -v c="$(basename "$f" .csv)" '$1 ~ /^[0-9.]+$/ { rows++; avg = $3 } END { printf "| %s | %s | %d |\n", c, avg, rows }' "$f" done fi echo echo '```' sort -rn <<<"${PHASE_TIMES%$'\n'}" echo '```' } >"$OUT/summary.md" 2>/dev/null || true [ -z "${GITHUB_STEP_SUMMARY:-}" ] || cat "$OUT/summary.md" >>"$GITHUB_STEP_SUMMARY" || true }