Seven new lib tools — covers the remaining Bryan-requested gaps.
lib/nc-engine.sh
- Cloverleaf process control. Wraps shipped binaries (hcienginestop,
hcienginerun, hcienginerestart, hciengineroutetest). Every action
is Y/N confirmed AND journaled into engine-actions.tsv.
- Subcommands: stop, start, bounce/restart, status, resend-ib,
resend-ob, route-test, testxlate, tpstest.
lib/nc-status.sh
- Runtime status, v1-modelled. Subcommands: sites, threads, not-up,
connections, queued, raw. Auto-discovers hcienginestat / tstat /
connstatus binaries; falls back to file-presence heuristics.
lib/nc-table.sh
- Read+CRUD for .tbl lookup tables. Subcommands: list, show, pairs
(→csv/tsv), lookup, reverse-lookup, add, delete, create, replace.
- All modifications journal-backed. Composes csv-to-table /
table-to-csv for format conversion.
lib/nc-xlate.sh
- Visualize .xlt files. Parses the TCL nested-block ops format.
Subcommands: list, show, ops (TSV), tree (ASCII flow), summary
(counts + segments + tables touched), diff (cross-xlate).
- Confirmed working against Epic_ADT_CodaMetrix.xlt: identified
12 PATHCOPY + 1 COPY ops across MSH/EVN/PID/PV1/PV2/PD1/ZPD/ZPV/
AL1/GT1/IN1/IN2.
lib/nc-smat-diff.sh
- Cross-env smat content diff. Samples N msgs from each side,
pairs by configurable HL7 field (default MSH.10 = control ID),
hl7-diffs each pair with --ignore MSH.7. Outputs per-pair reports
+ master _summary.md with paired/A-only/B-only counts.
lib/nc-create-thread.sh
- High-level: create a new protocol + optionally splice a route from
an existing thread to the new one. Both writes journal-backed.
Confirmed end-to-end: created to_metrics_test outbound + routed
IB_ADT_muxS → to_metrics_test via journal entries 001+002.
lib/nc-tclgen.sh
- TCL UPOC scaffolding from intent. Templates: tps-presc, tps-postsc,
tps-iclkill, xlate-helper, trxid, ack, field-rewrite. Produces
clean syntax-correct TCL ready to edit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
200 lines
5.8 KiB
Bash
Executable File
200 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# nc-create-thread.sh — high-level: create a new thread in a NetConfig and
|
|
# (optionally) wire a route from another thread to it.
|
|
#
|
|
# Combines nc-make-jump's emit helpers + nc-insert-protocol for a single
|
|
# user-facing operation. Goes through the journal.
|
|
#
|
|
# Usage:
|
|
# nc-create-thread.sh --name NEW_THREAD --site SITE --netconfig PATH
|
|
# --type tcpip|file
|
|
# --direction inbound|outbound
|
|
# --port PORT [--host HOST]
|
|
# [--process PROC]
|
|
# [--encoding ASCII]
|
|
# [--connect-from EXISTING_THREAD] # add a route on EXISTING → NEW
|
|
# [--route-type raw|xlate|generate] # default raw
|
|
# [--xlate XLATENAME] # if route-type=xlate
|
|
# [--trxid REGEX] # default .*
|
|
#
|
|
# Example: create a new outbound thread `to_metrics` in process `metrics` on
|
|
# 10.0.0.50:51999, raw-route from existing `IB_ADT_muxS` to it.
|
|
set -o pipefail
|
|
|
|
NC_SELF="$0"
|
|
LIB_DIR="$(cd "$(dirname "$NC_SELF")" && pwd)"
|
|
NCP="$LIB_DIR/nc-parse.sh"
|
|
NCI="$LIB_DIR/nc-insert-protocol.sh"
|
|
|
|
die() { printf 'nc-create-thread: %s\n' "$*" >&2; exit 1; }
|
|
|
|
NAME=""; SITE="${HCISITE:-}"; NC=""
|
|
TYPE="tcpip"; DIRECTION="outbound"; PORT=""; HOST=""
|
|
PROCESS=""; ENCODING="ASCII"
|
|
CONNECT_FROM=""; ROUTE_TYPE="raw"; XLATE=""; TRXID=".*"
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--name) shift; NAME="$1" ;;
|
|
--site) shift; SITE="$1" ;;
|
|
--netconfig) shift; NC="$1" ;;
|
|
--type) shift; TYPE="$1" ;;
|
|
--direction) shift; DIRECTION="$1" ;;
|
|
--port) shift; PORT="$1" ;;
|
|
--host) shift; HOST="$1" ;;
|
|
--process) shift; PROCESS="$1" ;;
|
|
--encoding) shift; ENCODING="$1" ;;
|
|
--connect-from) shift; CONNECT_FROM="$1" ;;
|
|
--route-type) shift; ROUTE_TYPE="$1" ;;
|
|
--xlate) shift; XLATE="$1" ;;
|
|
--trxid) shift; TRXID="$1" ;;
|
|
-h|--help) sed -n '2,20p' "$NC_SELF"; exit 0 ;;
|
|
*) die "unknown arg: $1" ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -n "$NAME" ] || die "missing --name"
|
|
[ -n "$PORT" ] || die "missing --port"
|
|
[ -n "$NC" ] || NC="${HCIROOT:-}/${SITE}/NetConfig"
|
|
[ -f "$NC" ] || die "no such netconfig: $NC"
|
|
[ -z "$PROCESS" ] && PROCESS="$SITE"
|
|
|
|
is_server=0
|
|
outonly=1
|
|
obib=0
|
|
case "$DIRECTION" in
|
|
inbound) is_server=1; outonly=0; obib=1 ;;
|
|
outbound) is_server=0; outonly=1; obib=0 ;;
|
|
*) die "bad --direction" ;;
|
|
esac
|
|
|
|
# Build the protocol block
|
|
build_block() {
|
|
cat <<EOF
|
|
protocol ${NAME} {
|
|
{ AUTOSTART 1 }
|
|
{ BITMAP {} }
|
|
{ COORDS {0 0} }
|
|
{ DATAFORMAT {
|
|
{ FRLTYPE offlen }
|
|
{ OFFLEN { { LEN 0 } { OFF 0 } } }
|
|
{ TYPE frl }
|
|
} }
|
|
{ DATAXLATE {
|
|
|
|
} }
|
|
{ EDIBATCH {
|
|
{ IN_DATA { { TYPE {} } { VERSION {} } } }
|
|
{ OUT_DATA { { HEADER {} } { TRIGGER { { COUNT {} } { SCHEDULER {} } { TIMER {} } } } { TYPE {} } { VERSION {} } } }
|
|
} }
|
|
{ ENCODING ${ENCODING} }
|
|
{ ENCODING_BOM_IB 0 }
|
|
{ ENCODING_BOM_OB 0 }
|
|
{ ENCODING_HL7 0 }
|
|
{ ENCODING_XML 0 }
|
|
{ EOCONFIG {} }
|
|
{ ERRDBTPS {
|
|
{ ERRTPSPROCS { { ARGS {} } { PROCS {} } { PROCSCONTROL {} } } }
|
|
{ RETRIES -1 }
|
|
} }
|
|
{ GROUPS {larry_created} }
|
|
{ HOSTDOWN 0 }
|
|
{ ICLSERVERPORT {} }
|
|
{ KEEPMSGONDISK 0 }
|
|
{ META {} }
|
|
{ OBWORKASIB ${obib} }
|
|
{ OUTBOUNDONLY ${outonly} }
|
|
{ PROCESSNAME ${PROCESS} }
|
|
{ PROTOCOL {
|
|
{ CA_FILE {} }
|
|
{ CA_PATH {} }
|
|
{ CERT_FILE {} }
|
|
{ CIPHERSUITES {} }
|
|
{ CLOSE 0 }
|
|
{ CONTROLMSGS 0 }
|
|
{ COPYCLIENTIPP 0 }
|
|
{ DELAYCONNECT 0 }
|
|
{ ENCODE_FILL {} }
|
|
{ ENCODE_INCLUSIVE 1 }
|
|
{ ENCODE_ISNATIVE 0 }
|
|
{ ENCODE_JUST r }
|
|
{ ENCODE_LEN 4 }
|
|
{ ENCODE_TYPE encapsulated }
|
|
{ HOST ${HOST:-{}} }
|
|
{ IPV4_V6_DUAL 0 }
|
|
{ IS_SSL 0 }
|
|
{ ISMULTI 0 }
|
|
{ ISSERVER ${is_server} }
|
|
{ LOCAL_IP {} }
|
|
{ MAXCLIENT 0 }
|
|
{ MAXOBQD 0 }
|
|
{ MAXPREXLTQD 0 }
|
|
{ MLP_ERROR RESET }
|
|
{ MLP_MODE MLP }
|
|
{ MLP_TIMEOUT 30 }
|
|
{ MODE {} }
|
|
{ PASSWORD {} }
|
|
{ PORT ${PORT} }
|
|
{ PRIVATE_KEY {} }
|
|
{ RECONNECT 1 }
|
|
{ REOPEN 5 }
|
|
{ SSL_PROTOCOL All }
|
|
{ TCP_CONNECTION_TIMEOUT {} }
|
|
{ TYPE ${TYPE} }
|
|
{ WRITEZERO 0 }
|
|
} }
|
|
{ RECVCONTROL { { ACKCONTROL { { ARGS {} } { PROCS {} } { PROCSCONTROL {} } } } { EOMSG {} } { HOLDMSGS 0 } { MSGPRIO 5120 } } }
|
|
{ SAVECONTROL { { ARGS {} } { PROCS {} } { PROCSCONTROL {} } } }
|
|
{ TPS_INBOUND { { ARGS {} } { PROCS {} } { PROCSCONTROL {} } } }
|
|
{ TPS_OUTBOUND { { ARGS {} } { PROCS {} } { PROCSCONTROL {} } } }
|
|
{ TRACING 0 }
|
|
}
|
|
EOF
|
|
}
|
|
|
|
build_route_entry() {
|
|
local xlate_block="{ PROCS { { ARGS {} } { PROCS {} } { PROCSCONTROL {} } } }"
|
|
local extra=""
|
|
if [ "$ROUTE_TYPE" = "xlate" ] && [ -n "$XLATE" ]; then
|
|
extra="{ XLATE ${XLATE} }"
|
|
fi
|
|
cat <<EOF
|
|
{
|
|
{ CACHEMSG 0 }
|
|
{ DEL_ON_ERR_ROUTE 0 }
|
|
{ ROUTE_DETAILS {
|
|
{
|
|
{ DEST ${NAME} }
|
|
${xlate_block}
|
|
${extra}
|
|
{ TYPE ${ROUTE_TYPE} }
|
|
}
|
|
} }
|
|
{ ROUTE_ENABLED 1 }
|
|
{ TRXID ${TRXID} }
|
|
{ WILDCARD ON }
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Generate block
|
|
BLOCK_FILE=$(mktemp); build_block > "$BLOCK_FILE"
|
|
printf '\n=== Generated protocol block for %s ===\n\n' "$NAME"
|
|
cat "$BLOCK_FILE"
|
|
printf '\n'
|
|
|
|
# Insert it
|
|
"$NCI" insert "$NC" "$BLOCK_FILE"
|
|
|
|
# If --connect-from, also splice a route into the source thread's DATAXLATE
|
|
if [ -n "$CONNECT_FROM" ]; then
|
|
ROUTE_FILE=$(mktemp); build_route_entry > "$ROUTE_FILE"
|
|
printf '\n=== Route to splice into %s DATAXLATE ===\n\n' "$CONNECT_FROM"
|
|
cat "$ROUTE_FILE"
|
|
printf '\n'
|
|
"$NCI" add-route "$NC" "$CONNECT_FROM" "$ROUTE_FILE"
|
|
rm -f "$ROUTE_FILE"
|
|
fi
|
|
rm -f "$BLOCK_FILE"
|